如何在Jetty中使用SPDY

SPDY是Google提出的一种新协议,是针对网络的新协议。 SPDY与HTTP兼容,但尝试通过压缩,多路复用和优先级降低网页负载。准确地说,快速的目标是:( http://dev.chromium.org/spdy/spdy-whitepaper )。 SPDY项目为Web定义并实现了一个应用程序层协议,可大大减少延迟。

SPDY的高级目标是:

  • 旨在将页面加载时间减少50%。 我们的初步结果已经接近这个目标(见下文)。
  • 以最小化部署复杂性。 SPDY使用TCP作为基础传输层,因此不需要更改现有的网络基础结构。
  • 为了避免网站作者对内容进行任何更改。 支持SPDY的唯一更改是在客户端用户代理和Web服务器应用程序中。
  • 将对探索协议感兴趣的志趣相投的各方聚集在一起,以解决延迟问题。 我们希望与开源社区和行业专家合作开发此新协议

一些特定的技术目标是:

  • 允许多个并发HTTP请求在单个TCP会话中运行。
  • 通过压缩头并消除不必要的头来减少HTTP当前使用的带宽。
  • 定义易于实施且服务器效率高的协议。 我们希望通过减少边缘情况并定义易于解析的消息格式来降低HTTP的复杂性。
  • 使SSL成为基础传输协议,以提高安全性和与现有网络基础结构的兼容性。 尽管SSL确实会带来延迟损失,但我们认为网络的长期发展取决于安全的网络连接。 另外,必须使用SSL以确保跨现有代理的通信不中断。
  • 使服务器能够启动与客户端的通信并将数据推送到客户端。

安装专家

在本文中,我们不会过多地研究此协议的技术实现,但是我们将向您展示如何开始自己使用SPDY并进行试验。 为此,我们将使用在最新版本( http://wiki.eclipse.org/Jetty/Feature/SPDY )中提供SPDY实现的Jetty。

因此,让我们开始吧。 对于此示例,我们将让Maven处理依赖关系。 我们将使用以下POM。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>smartjava.jetty.spdy</groupId><artifactId>SPDY-Example</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><dependency><groupId>org.eclipse.jetty.aggregate</groupId><artifactId>jetty-all-server</artifactId><version>8.1.2.v20120308</version><type>jar</type><scope>compile</scope><exclusions><exclusion><artifactId>mail</artifactId><groupId>javax.mail</groupId></exclusion></exclusions></dependency><dependency><groupId>org.eclipse.jetty.spdy</groupId><artifactId>spdy-jetty</artifactId><version>8.1.2.v20120308</version></dependency><dependency><groupId>org.eclipse.jetty.spdy</groupId><artifactId>spdy-core</artifactId><version>8.1.2.v20120308</version></dependency><dependency><groupId>org.eclipse.jetty.spdy</groupId><artifactId>spdy-jetty-http</artifactId><version>8.1.2.v20120308</version></dependency><dependency><groupId>org.eclipse.jetty.npn</groupId><artifactId>npn-api</artifactId><version>8.1.2.v20120308</version><scope>provided</scope></dependency></dependencies>
</project>

NTP TLS扩展

通过此POM,将加载正确的库,因此我们可以开始在Jetty中使用特定的SPDY类。 但是,在真正使用SPDY之前,我们还需要配置Java以使用TLS协议的扩展:TLS下一协议协商或简称NPN。 可以在googles技术说明( http://technotes.googlecode.com/git/nextprotoneg.html )上找到此扩展程序的详细信息,但总而言之,可以归结为这个问题。 通过TLS与服务器建立连接时,如果我们想使用不同于HTTP的协议该怎么办? 我们不知道服务器是否支持该协议,并且由于SPDY专注于速度,因此我们不希望增加往返行程的延迟。 即使有几种不同的解决方案,大多数解决方案也具有不可预测性,额外的往返次数或破坏现有代理的麻烦(有关更多信息,请参阅( http://www.ietf.org/proceedings/80/slides/tls-1.pdf )。
Google提出的解决方案是使用TLS的扩展机制来确定要使用的协议。 这称为“下一协议协商”或简称NPN。 使用此扩展,在TLS握手期间将执行以下步骤:

  1. 客户端显示对此扩展程序的支持
  2. 服务器响应此支持并包括支持的协议列表
  3. 客户端发送他要使用的协议,而不必由服务器提供。

这导致以下TLS握手:

客户端服务器
ClientHello(NP扩展)——–>
ServerHello(NP扩展和协议列表)
证书*
ServerKeyExchange *
证书申请*
<——– ServerHelloDone
证书*
ClientKeyExchange
证书验证*
[ChangeCipherSpec] NextProtocol
成品——–>
[ChangeCipherSpec] <——–已完成
应用数据<——->应用数据

有关TLS / SSL握手的更多信息,请参阅我以前的文章,该文章有关如何分析Java SSL错误: http : //www.smartjava.org/content/how-analyze-java-ssl-errors 。
因此,我们需要NPN来快速确定我们要使用的协议。 由于这不是标准的TLS,因此我们需要配置Java以使用NPN。 标准Java还不支持NPN,因此我们不能在标准JVM上运行SPDY。 为了解决这个问题,Jetty创建了一个可以与OpenJDK 7一起使用的NPN实现(有关更多详细信息,请参见http://wiki.eclipse.org/Jetty/Feature/NPN )。 您可以从此处下载此实现: http : //repo2.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/ ,您必须像这样将其添加到启动类路径中:

java -Xbootclasspath/p:<path_to_npn_boot_jar> ...

在SPDY中包装HTTP请求

现在,您可以开始使用Jetty的SPDY。 Jetty以两种不同方式支持此功能。 您可以使用它来将SPDY透明地转换为HTTP,然后再次返回,也可以使用它直接对话SPDY。 让我们创建一个简单的服务器配置,使用启用SPDY的连接托管一些静态内容。 为此,我们将使用以下Jetty配置:

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.spdy.http.HTTPSPDYServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;public class SPDYServerLauncher {public static void main(String[] args) throws Exception {// the server to startServer server = new Server();// the ssl context to useSslContextFactory sslFactory = new SslContextFactory();sslFactory.setKeyStorePath("src/main/resources/spdy.keystore");sslFactory.setKeyStorePassword("secret");sslFactory.setProtocol("TLSv1");// simple connector to add to serve content using spdyConnector connector = new HTTPSPDYServerConnector(sslFactory);connector.setPort(8443);// add connector to the serverserver.addConnector(connector);// add a handler to serve contentContextHandler handler = new ContextHandler();handler.setContextPath("/content");handler.setResourceBase("src/main/resources/webcontent");handler.setHandler(new ResourceHandler());server.setHandler(handler);server.start();server.join();}
}

由于Jetty还具有非常灵活的XML配置语言,因此您可以使用以下XML配置执行相同的操作。

<Configure id="Server" class="org.eclipse.jetty.server.Server"><New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory"><Set name="keyStorePath">src/main/resources/spdy.keystore</Set><Set name="keyStorePassword">secret</Set><Set name="protocol">TLSv1</Set></New><Call name="addConnector"><Arg><New class="org.eclipse.jetty.spdy.http.HTTPSPDYServerConnector"><Arg><Ref id="sslContextFactory" /></Arg><Set name="Port">8443</Set></New></Arg></Call>// Use standard XML configuration for the other handlers and other// stuff you want to add</Configure>

如您所见,我们指定了SSL上下文。 这是必需的,因为SPDY可在TLS上运行。 当我们运行此配置时,Jetty将开始在端口8443上侦听SPDY连接。 并非所有浏览器都支持SPDY,我已经使用最新的Chrome浏览器测试了此示例。 如果浏览到https:// localhost:8443 / dummy.html (我创建用来测试的文件),则将看到该文件的内容,就像您使用HTTPS请求该文件一样。 那么这里发生了什么? 首先,让我们看一下Chrome提供的SPDY会话视图,以确定我们是否真的在使用SPDY。 如果您导航到以下网址:chrome:// net-internals /#events&q = type:SPDY_SESSION%20is:active。 您会看到类似下图的内容。

Chrome中的SPDY

在此视图中,您可以看到所有当前的SPDY会话。 如果一切配置正确,您还可以看到连接到本地主机的SPDY会话。 进行额外检查以查看是否一切正常,以启用NPN扩展的调试功能。 您可以通过在用于启动服务器的Java代码中添加以下行来做到这一点:

NextProtoNego。 调试 = true ;

直接使用SPDY协议

现在我们已经可以使用HTTP over SPDY了,让我们看一下Jetty提供的另一个选项,它允许我们直接发送和接收SPDY消息。 对于此示例,我们将创建一个每5秒向服务器发送一条消息的客户端。 服务器以每秒接收的消息数发送响应到连接的客户端。 首先,我们创建服务器代码。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.SPDYServerConnector;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;public class SPDYListener {public static void main(String[] args) throws Exception {// Frame listener that handles the communication over speedy  ServerSessionFrameListener frameListener = new ServerSessionFrameListener.Adapter() {/*** As soon as we receive a syninfo we return the handler for the stream on * this session*/@Overridepublic StreamFrameListener onSyn(final Stream stream, SynInfo synInfo) {// Send a reply to this messagestream.reply(new ReplyInfo(false));// and start a timer that sends a request to this stream every 5 secondsScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();Runnable periodicTask = new Runnable() {private int i = 0;public void run() {// send a request and don't close the streamstream.data(new StringDataInfo("Data from the server " + i++, false));}};executor.scheduleAtFixedRate(periodicTask, 0, 1, TimeUnit.SECONDS);// Next create an adapter to further handle the client input from specific stream.return new StreamFrameListener.Adapter() {/*** We're only interested in the data, not the headers in this* example*/public void onData(Stream stream, DataInfo dataInfo) {String clientData = dataInfo.asString("UTF-8", true);System.out.println("Received the following client data: " + clientData);}};}};// Wire up and start the connectororg.eclipse.jetty.server.Server server = new Server();SPDYServerConnector connector = new SPDYServerConnector(frameListener);connector.setPort(8181);server.addConnector(connector);server.start();server.join();}
}

客户端代码如下所示:

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;import org.eclipse.jetty.spdy.SPDYClient;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;/*** Calls the server every couple of seconds.* * @author jos*/
public class SPDYCaller {public static void main(String[] args) throws Exception {// this listener receives data from the server. It then prints out the dataStreamFrameListener streamListener = new StreamFrameListener.Adapter() {public void onData(Stream stream, DataInfo dataInfo)  {// Data received from serverString content = dataInfo.asString("UTF-8", true);System.out.println("SPDY content: " + content);}};// Create clientSPDYClient.Factory clientFactory = new SPDYClient.Factory();clientFactory.start();SPDYClient client = clientFactory.newSPDYClient(SPDY.V2);// Create a session to the server running on localhost port 8181Session session = client.connect(new InetSocketAddress("localhost", 8181), null).get(5, TimeUnit.SECONDS);// Start a new session, and configure the stream listenerfinal Stream stream = session.syn(new SynInfo(false), streamListener).get(5, TimeUnit.SECONDS);//start a timer that sends a request to this stream every secondScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();Runnable periodicTask = new Runnable() {private int i = 0;public void run() {// send a request, don't close the streamstream.data(new StringDataInfo("Data from the client " + i++, false));}};executor.scheduleAtFixedRate(periodicTask, 0, 1, TimeUnit.SECONDS);}
}

这将在客户端和服务器上显示以下输出:

客户:
..
SPDY内容:来自服务器的数据3
SPDY内容:来自服务器的数据4
SPDY内容:来自服务器的数据5
SPDY内容:来自服务器的数据6
..
服务器:

收到以下客户端数据:来自客户端的数据2
收到以下客户端数据:来自客户端的数据3
收到以下客户端数据:来自客户端的数据4
收到以下客户端数据:来自客户端的数据5

代码本身应该易于从内联注释中理解。 唯一要记住的是,当您想通过一个流发送多条数据消息时,要确保将StringDataInfo的构造函数的第二个参数设置为false。 如果设置为true,则在发送数据后将关闭流。

stream.data(new StringDataInfo("Data from the client " + i++, false));

这仅显示了一个简单的用例,您可以直接使用SPDY协议。 可以在Jetty Wiki和SPDY API文档中找到更多信息和示例。

参考: Smart Java博客上来自JCG合作伙伴 Jos Dirksen的如何将SPDY与Jetty结合使用 。


翻译自: https://www.javacodegeeks.com/2012/04/how-to-use-spdy-with-jetty.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虐杀外星人java,逆天游戏《毁灭全人类2》登PS4 外星人疯狂虐杀地球人

逆天游戏《毁灭全人类2》登PS4 外星人疯狂虐杀地球人2016-10-17 10:45:58来源&#xff1a;游戏下载编辑&#xff1a;小年青评论(0)广大的小伙伴都有看过许多外星人企图入侵毁灭地球的电影&#xff0c;已此为题材而开发的游戏也不在少数。近日泛欧洲游戏信息组织又为一款该种题材…

Android之仿微信图片选择器

先上效果图。第一张图显示的是“相机”文件夹中的所有图片&#xff1b;通过点击多张图片可以到第二张图所示的效果&#xff08;被选择的图片会变暗&#xff0c;同时选择按钮变亮&#xff09;&#xff1b;点击最下面的那一栏可以到第三张图所示的效果&#xff08;显示手机中所有…

loss function

什么是loss? loss: loss是我们用来对模型满意程度的指标。loss设计的原则是&#xff1a;模型越好loss越低&#xff0c;模型越差loss越高&#xff0c;但也有过拟合的情况。     loss function: 在分类问题中&#xff0c;输入样本经过含权重矩阵θ的模型后会得出关于各个类别…

oracle查询表的id,oracle 查看所有用户及密码 实现Oracle查询用户所有表

1、oracle 查看所有用户及密码SQL> select username from dba_users;2、 实现Oracle查询用户所有表下面为您介绍的语句用于实现Oracle查询用户所有表&#xff0c;如果您对oracle查询方面感兴趣的话&#xff0c;不妨一看。select * from all_tab_comments-- 查询所有用户的表…

FindBugs和JSR-305

假设那组开发人员在大型项目的各个部分上并行工作–一些开发人员在进行服务实现&#xff0c;而其他开发人员在使用该服务的代码。 考虑到API的假设&#xff0c;两个小组都同意服务API&#xff0c;并开始单独工作。 您认为这个故事会有幸福的结局吗&#xff1f; 好吧&#xff0c…

什么是Akka?

在深入研究什么是Akka之前&#xff0c;让我们退后一步来了解并发编程的概念在应用程序开发世界中是如何演变的。 应用程序已经从大型的整体程序演变为面向对象的模型。 随着Java EE和Spring框架的出现&#xff0c;应用程序设计演变为更多的基于流程或任务的设计模型。 EJB或Poj…

Unity3d 实现顶点动画

在今年GDC上发现一个非常有趣的演讲&#xff0c;叫做Animating With Math&#xff0c;遂实现之&#xff0c;是讲述顶点shader动画的&#xff0c;举了几个经典的例子&#xff0c;但是讲者并没有给代码&#xff0c;而是像虚幻引擎那样的节点&#xff0c;这样更加清楚明了之前博主…

windows2012同步linux时间,Windows server2012时间同步NTP配置

遇到经常服务器时间无法同步&#xff0c;可以自己建立一台时间同步服务器&#xff0c;NTP配置如下&#xff1a;一、服务端配置 (Ntp服务器&#xff0c;客户端将根据这台服务器的时间进行同步)1、微软键R键&#xff0c;进入“运行”&#xff0c;输入“regedit”,进入注册表2、 H…

Java EE 6示例– Galleria第2部分

您可能在最后一篇Java EE 6 Galleria示例帖子中关注了我。 第一个是基本介绍。 第二个是关于在最新的GlassFish上运行它。 有人提到RedHat&#xff0c;我们应该研究将这个示例从GlassFish中移除。 很好;&#xff09;感谢您的好主意。 这正是我们今天要做的。 我将把Galleria示例…

与reCAPTCHA的Spring集成

有时我们只需要CAPTCHA &#xff0c;这是一个可悲的事实。 今天&#xff0c;我们将学习如何与reCAPTCHA集成。 因为主题本身并不是特别有趣和高级&#xff0c;所以我们将通过使用Spring Integration处理低级细节来过度设计&#xff08;&#xff1f;&#xff09;。 Google决定使…

《机器学习基石》---感知机算法

1 推导感知机模型 基本思想是&#xff0c;把特征的线性加权值作为一个分数&#xff0c;根据这个分数与一个门限值的关系来进行分类&#xff1a; 我们加一个特征x0等于1&#xff0c;门限值就可以放到w里面去&#xff0c;得到更简单的形式&#xff1a; 这就是感知机模型&#xff…

Python之路【第八篇】:堡垒机实例以及数据库操作

Python之路【第八篇】&#xff1a;堡垒机实例以及数据库操作 堡垒机前戏 开发堡垒机之前&#xff0c;先来学习Python的paramiko模块&#xff0c;该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接&#xff1a; 12…

ADF BC:创建绑定到业务组件的UI表

在此示例中&#xff0c;我们将展示如何创建绑定到业务组件的简单UI表&#xff08;af&#xff1a;table&#xff09;。 我再次尝试使用简单的标准在网上进行搜索&#xff1a; “如何创建绑定到业务组件ADF 11g的af&#xff1a;table” 我必须承认我没有得到我想要的答案。 信息…

MyBaits 错误分析

错误原因&#xff1a;在DAO的映射文件中&#xff0c;在映射标签中的type类型写成DAO类了&#xff0c;应该写成javaBean转载于:https://www.cnblogs.com/shuaiandjun/p/5428847.html

斑马打印机linux驱动安装教程,linux-Zebra软件包的基本安装与配置

Zebra是一个路由软件包&#xff0c;提供基于TCP/IP路由服务&#xff0c;支持RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, BGP- 4,和 BGP-4等众多路由协议。Zebra还支持BGP特性路由反射器(Route Reflector)。除了传统的 IPv4路由协议&#xff0c;Zebra也支持IPv6路由协议。如果运行的…

Java 7对抑制异常的支持

在JDK 7中 &#xff0c;向Throwable类&#xff08; Exception和Error类的父类&#xff09;添加了一个新的构造函数和两个新方法。 添加了新的构造函数和两个新方法以支持“抑制的异常”&#xff08;不要与吞咽或忽略异常的不良做法相混淆&#xff09;。 在本文中&#xff0c;我…

易于使用的单位和集成代码

此示例说明如何使用Maven和Sonar生成单元测试和集成测试的覆盖率。 它使用非常简单的技术&#xff0c;只需10-15分钟即可在任何现有的Maven构建中运行。 它可用于单元&#xff0c;集成&#xff0c;ATDD或任何其他类型的测试套件。 覆盖率结果显示在Sonar中。 有什么事吗&#x…

Ubuntu 16.04 安装 VMware-Workstation-12

以前一直使用 Ubuntu Virtaulbox &#xff0c;最近测试了 VMware-Workstation-9,性能超过 Virtaulbox-4.2.x,下面是详细步骤:1 首先准备一个Ubuntu 系统 lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04 LTS Release: 16.04 …

SSH实战 · 唯唯乐购项目(中)

用户模块三&#xff1a;一级分类的查询创建一级分类表并导入基本数据CREATE TABLE category (cid int(11) NOT NULL AUTO_INCREMENT,cname varchar(255) DEFAULT NULL,PRIMARY KEY (cid)) ENGINEInnoDB AUTO_INCREMENT11 DEFAULT CHARSETutf8;建包及相应的类:com.weiwei.shoppi…

Android的IPC机制(一)——AIDL的使用

综述 IPC(interprocess communication)是指进程间通信&#xff0c;也就是在两个进程间进行数据交互。不同的操作系统都有他们自己的一套IPC机制。例如在Linux操作系统中可以通过管道、信号量、消息队列、内存共享、套接字等进行进程间通信。那么在Android系统中我们可以通过Bin…