日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Netty:透明地使用SPDY和HTTP

發(fā)布時(shí)間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Netty:透明地使用SPDY和HTTP 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
大多數(shù)人已經(jīng)從谷歌那里聽(tīng)說(shuō)過(guò)SPDY,該協(xié)議被提議作為老化的HTTP協(xié)議的替代品。 Web服務(wù)器是瀏覽器正在緩慢地實(shí)現(xiàn)該協(xié)議,并且支持正在增長(zhǎng)。 在最近的文章中,我已經(jīng)寫(xiě)過(guò)SPDY的工作方式以及如何在Jetty中啟用SPDY支持。 由于Netty(最初來(lái)自JBoss)幾個(gè)月以來(lái)也支持SPDY 。由于Netty通常用于高性能協(xié)議服務(wù)器,因此SPDY是合乎邏輯的。 在本文中,我將向您展示如何創(chuàng)建一個(gè)基于Netty的基本服務(wù)器,該服務(wù)器在SPDY和HTTP之間進(jìn)行協(xié)議協(xié)商。 它使用Netty snoop示例中的示例HTTPRequestHandler來(lái)消耗并產(chǎn)生一些HTTP內(nèi)容。 為了使一切正常,我們需要做以下事情:
  • 在Java中啟用NPN以確定要使用的協(xié)議。
  • 根據(jù)協(xié)商的協(xié)議,確定使用HTTP還是SPDY。
  • 確保使用HTTP發(fā)送回正確的SPDY標(biāo)頭。
SPDY使用TLS擴(kuò)展來(lái)確定要在通信中使用的協(xié)議。 這稱(chēng)為NPN。 我寫(xiě)了一個(gè)更完整的說(shuō)明,并顯示了文章中有關(guān)如何在Jetty上使用SPDY的消息,因此,有關(guān)該文章的更多信息,請(qǐng)參見(jiàn)。 基本上,此擴(kuò)展的作用是在TLS交換期間,服務(wù)器和客戶(hù)端也會(huì)交換它們支持的傳輸級(jí)別協(xié)議。 對(duì)于SPDY,服務(wù)器可以同時(shí)支持SPDY協(xié)議和HTTP協(xié)議。 然后,客戶(hù)端實(shí)現(xiàn)可以確定要使用的協(xié)議。 由于這不是標(biāo)準(zhǔn)Java實(shí)現(xiàn)中可用的功能,因此我們需要使用NPN擴(kuò)展Java TLS功能。 在Java中啟用NPN支持 到目前為止,我發(fā)現(xiàn)了兩個(gè)可以用來(lái)在Java中添加NPN支持的選項(xiàng)。 其中一個(gè)來(lái)自https://github.com/benmmurphy/ssl_npn ,他的回購(gòu)中也有一個(gè)基本的SPDY / Netty示例,他使用自己的實(shí)現(xiàn)。 我將要使用的另一個(gè)選項(xiàng)是Jetty提供的NPN支持。 Jetty提供了一個(gè)易于使用的API,可用于將NPN支持添加到Java SSL上下文中。 再次,在關(guān)于碼頭的文章中,您可以找到關(guān)于此的更多信息。 要為Netty設(shè)置NPN,我們需要執(zhí)行以下操作:
  • 將NPN lib添加到引導(dǎo)路徑
  • 將SSL上下文連接到NPN Api
  • 將NPN庫(kù)添加到boothpath 首先是第一件事。 從http://repo2.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/8.1.2.v2012下載NPN引導(dǎo)jar,并確保在運(yùn)行服務(wù)器時(shí)像這樣啟動(dòng)它: java -Xbootclasspath/p:<path_to_npn_boot_jar> 通過(guò)這段代碼,Java SSL支持NPN。 但是,我們?nèi)匀恍枰L問(wèn)此協(xié)商的結(jié)果。 我們需要知道我們使用的是HTTP還是SPDY,因?yàn)檫@決定了我們?nèi)绾翁幚斫邮盏降臄?shù)據(jù)。 為此,Jetty提供了一個(gè)API。 為此和所需的Netty庫(kù),我們將以下依賴(lài)項(xiàng)添加到pom中,因?yàn)槲沂褂玫氖莔aven。 <dependency><groupId>io.netty</groupId><artifactId>netty</artifactId><version>3.4.1.Final</version></dependency><dependency><groupId>org.eclipse.jetty.npn</groupId><artifactId>npn-api</artifactId><version>8.1.2.v20120308</version></dependency> 將SSL上下文連接到NPN API 現(xiàn)在,我們已啟用NPN并將正確的API添加到項(xiàng)目中,我們可以配置Netty SSL處理程序。 在Netty中配置處理程序是在PipelineFactory中完成的。 對(duì)于我們的服務(wù)器,我創(chuàng)建了以下PipelineFactory: package smartjava.netty.spdy; import static org.jboss.netty.channel.Channels.pipeline;import java.io.FileInputStream; import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine;import org.eclipse.jetty.npn.NextProtoNego; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.handler.ssl.SslHandler;public class SPDYPipelineFactory implements ChannelPipelineFactory {private SSLContext context;public SPDYPipelineFactory() {try {KeyStore keystore = KeyStore.getInstance("JKS");keystore.load(new FileInputStream("src/main/resources/server.jks"),"secret".toCharArray());KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");kmf.init(keystore, "secret".toCharArray());context = SSLContext.getInstance("TLS");context.init(kmf.getKeyManagers(), null, null);} catch (Exception e) {e.printStackTrace();}}public ChannelPipeline getPipeline() throws Exception {// Create a default pipeline implementation.ChannelPipeline pipeline = pipeline();// Uncomment the following line if you want HTTPSSSLEngine engine = context.createSSLEngine();engine.setUseClientMode(false);NextProtoNego.put(engine, new SimpleServerProvider());NextProtoNego.debug = true;pipeline.addLast("ssl", new SslHandler(engine));pipeline.addLast("pipeLineSelector", new HttpOrSpdyHandler());return pipeline;} } 在此類(lèi)的構(gòu)造函數(shù)中,我們?cè)O(shè)置了基本的SSL上下文。 我們使用的密鑰庫(kù)和密鑰是我使用java keytool創(chuàng)建的,這是常規(guī)的SSL配置。 收到請(qǐng)求后,將調(diào)用getPipeline操作來(lái)確定如何處理該請(qǐng)求。 在這里,我們使用Jetty-NPN-API提供的NextProtoNego類(lèi)將SSL連接連接到NPN實(shí)現(xiàn)。 在此操作中,我們傳遞一個(gè)提供程序,該提供程序用作服務(wù)器的回調(diào)和配置。 我們還將NextProtoNego.debug設(shè)置為true。 這會(huì)打印出一些調(diào)試信息,從而使調(diào)試更加容易。 SimpleServerProvider的代碼非常簡(jiǎn)單: public class SimpleServerProvider implements ServerProvider {private String selectedProtocol = null;public void unsupported() {//if unsupported, default to http/1.1selectedProtocol = "http/1.1";}public List<String> protocols() {return Arrays.asList("spdy/2","http/1.1");}public void protocolSelected(String protocol) {selectedProtocol = protocol;}public String getSelectedProtocol() { return selectedProtocol;} } 此代碼幾乎是不言自明的。
    • 當(dāng)客戶(hù)端不支持NPN時(shí),將調(diào)用不受支持的操作。 在這種情況下,我們默認(rèn)為HTTP。
    • protocol()操作返回服務(wù)器支持的協(xié)議
    • 服務(wù)器和客戶(hù)端協(xié)商協(xié)議后,將調(diào)用protocolSelected操作
    getSelectedProtocol是一種用于從Netty管道中的其他處理程序獲取所選協(xié)議的方法。 根據(jù)協(xié)商的協(xié)議確定使用HTTP還是SPDY 現(xiàn)在,我們需要配置Netty,使其為HTTPS請(qǐng)求和SPDY請(qǐng)求運(yùn)行特定的管道。 為此,讓我們回顧一下管道工廠的一小部分。 pipeline.addLast("ssl", new SslHandler(engine)); pipeline.addLast("pipeLineSelector", new HttpOrSpdyHandler()); 該管道的第一部分是配置了NPN支持的SslHandler。 下一個(gè)將被調(diào)用的處理程序是HttpOrSpdyHandler。 該處理程序根據(jù)協(xié)議確定要使用的管道。 接下來(lái)列出此處理程序的代碼: public class HttpOrSpdyHandler implements ChannelUpstreamHandler {public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)throws Exception {// determine protocol typeSslHandler handler = ctx.getPipeline().get(SslHandler.class);SimpleServerProvider provider = (SimpleServerProvider) NextProtoNego.get(handler.getEngine());if ("spdy/2".equals(provider.getSelectedProtocol())) {ChannelPipeline pipeline = ctx.getPipeline();pipeline.addLast("decoder", new SpdyFrameDecoder());pipeline.addLast("spdy_encoder", new SpdyFrameEncoder());pipeline.addLast("spdy_session_handler", new SpdySessionHandler(true));pipeline.addLast("spdy_http_encoder", new SpdyHttpEncoder());// Max size of SPDY messages set to 1MBpipeline.addLast("spdy_http_decoder", new SpdyHttpDecoder(1024*1024)); pipeline.addLast("handler", new HttpRequestHandler());// remove this handler, and process the requests as spdypipeline.remove(this);ctx.sendUpstream(e);} else if ("http/1.1".equals(provider.getSelectedProtocol())) {ChannelPipeline pipeline = ctx.getPipeline();pipeline.addLast("decoder", new HttpRequestDecoder());pipeline.addLast("http_encoder", new HttpResponseEncoder());pipeline.addLast("handler", new HttpRequestHandler());// remove this handler, and process the requests as httppipeline.remove(this);ctx.sendUpstream(e);} else {// we're still in protocol negotiation, no need for any handlers// at this point.}} } 使用NPN API和當(dāng)前的SSL上下文,我們可以檢索之前添加的SimpleServerProvider。 我們檢查是否已設(shè)置selectedProtocol,如果已設(shè)置,則設(shè)置一條鏈進(jìn)行處理。 我們?cè)诖祟?lèi)中處理三個(gè)選項(xiàng):
  • 沒(méi)有協(xié)議 :可能尚未協(xié)商任何協(xié)議。 在那種情況下,我們沒(méi)有做任何特別的事情,只需正常處理即可。
  • 有一個(gè)http協(xié)議 :我們建立了一個(gè)處理程序鏈來(lái)處理HTTP請(qǐng)求。
  • 有一個(gè)spdy協(xié)議 :我們建立了一個(gè)處理程序鏈來(lái)處理SPDY請(qǐng)求。
  • 有了這個(gè)鏈,我們最終由HttpRequestHandler接收到的所有消息都是HTTP請(qǐng)求。 我們可以正常處理此HTTP請(qǐng)求,然后返回HTTP響應(yīng)。 各種管道配置將正確處理所有這些問(wèn)題。 確保使用HTTP發(fā)送回正確的SPDY標(biāo)頭 我們需要做的最后一步是測(cè)試。 我們將使用最新版本的Chrome進(jìn)行測(cè)試,以測(cè)試SPDY是否正常運(yùn)行,并使用wget測(cè)試正常的http請(qǐng)求。 我提到了鏈中最后一個(gè)處理程序HttpRequestHandler進(jìn)行我們的HTTP處理。 我已經(jīng)使用http://netty.io/docs/stable/xref/org/jboss/netty/example/http/snoop/Http…作為HTTPRequestHandler,因?yàn)槟呛芎玫胤祷亓擞嘘P(guān)HTTP請(qǐng)求的信息,而我卻沒(méi)有做任何事。 如果不做任何更改就運(yùn)行它,則會(huì)遇到問(wèn)題。 為了將HTTP響應(yīng)與正確的SPDY會(huì)話相關(guān)聯(lián),我們需要將傳入請(qǐng)求中的標(biāo)頭復(fù)制到響應(yīng)中:“ X-SPDY-Stream-ID”標(biāo)頭。 我將以下內(nèi)容添加到HttpSnoopServerHandler中,以確保復(fù)制了這些標(biāo)頭(實(shí)際上應(yīng)該在單獨(dú)的處理程序中完成此操作)。 private final static String SPDY_STREAM_ID = = "X-SPDY-Stream-ID";private final static String SPDY_STREAM_PRIO = "X-SPDY-Stream-Priority";// in the writeResponse method addif (request.containsHeader(SPDY_STREAM_ID)) {response.addHeader(SPDY_STREAM_ID,request.getHeader(SPDY_STREAM_ID));// optional header for prioresponse.addHeader(SPDY_STREAM_PRIO,0);} 現(xiàn)在剩下的就是一臺(tái)具有啟動(dòng)所有內(nèi)容的主服務(wù)器的服務(wù)器,并且我們可以測(cè)試SPDY實(shí)現(xiàn)。 public class SPDYServer {public static void main(String[] args) {// bootstrap is used to configure and setup the serverServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool()));bootstrap.setPipelineFactory(new SPDYPipelineFactory());bootstrap.bind(new InetSocketAddress(8443));} } 啟動(dòng)服務(wù)器,啟動(dòng)Chrome,然后查看是否一切正常。 打開(kāi)https:// localhost:8443 / thisIsATest網(wǎng)址,您應(yīng)該得到如下所示的結(jié)果: 在服務(wù)器的輸出中,您可以看到一些NPN調(diào)試日志記錄: [S] NPN received for 68ce4f39[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL] [S] NPN protocols [spdy/2, http/1.1] sent to client for 68ce4f39[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL] [S] NPN received for 4b24e48f[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL] [S] NPN protocols [spdy/2, http/1.1] sent to client for 4b24e48f[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL] [S] NPN selected 'spdy/2' for 4b24e48f[SSLEngine[hostname=null port=-1] SSL_NULL_WITH_NULL_NULL] 額外的檢查是使用以下網(wǎng)址查看chrome瀏覽器中打開(kāi)的SPDY會(huì)話:chrome:// net-internals /#spdy 現(xiàn)在讓我們檢查普通的舊HTTP是否仍在工作。 從命令行執(zhí)行以下操作: jos@Joss-MacBook-Pro.local:~$ wget --no-check-certificate https://localhost:8443/thisIsATest --2012-04-27 16:29:09-- https://localhost:8443/thisIsATest Resolving localhost... ::1, 127.0.0.1, fe80::1 Connecting to localhost|::1|:8443... connected. WARNING: cannot verify localhost's certificate, issued by `/C=NL/ST=NB/L=Waalwijk/O=smartjava/OU=smartjava/CN=localhost':Self-signed certificate encountered. HTTP request sent, awaiting response... 200 OK Length: 285 Saving to: `thisIsATest'100%[==================================================================================>] 285 --.-K/s in 0s 2012-04-27 16:29:09 (136 MB/s) - `thisIsATest' saved [285/285]jos@Joss-MacBook-Pro.local:~$ cat thisIsATest WELCOME TO THE WILD WILD WEB SERVER =================================== VERSION: HTTP/1.1 HOSTNAME: localhost:8443 REQUEST_URI: /thisIsATestHEADER: User-Agent = Wget/1.13.4 (darwin11.2.0) HEADER: Accept = */* HEADER: Host = localhost:8443 HEADER: Connection = Keep-Alivejos@Joss-MacBook-Pro.local:~$ 而且有效! Wget使用標(biāo)準(zhǔn)的HTTPS,我們得到一個(gè)結(jié)果,而chrome使用SPDY,并從同一處理程序中呈現(xiàn)結(jié)果。 在最后的幾天里,我還將發(fā)布有關(guān)如何為Play Framework 2.0啟用SPDY的文章,因?yàn)樗鼈兊腤eb服務(wù)器也基于Netty。 參考:來(lái)自Smart Java博客的JCG合作伙伴 Jos Dirksen 透明地使用Netty使用SPDY和HTTP 。

    翻譯自: https://www.javacodegeeks.com/2012/05/netty-using-spdy-and-http-transparently.html

    總結(jié)

    以上是生活随笔為你收集整理的Netty:透明地使用SPDY和HTTP的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。