Netty:另一种Web(套接字)服务器
如今, Netty已用于Internet上的各種應(yīng)用程序中,以處理數(shù)千(即使不是數(shù)百萬)的聊天對話,包括Minecraft , Twitter和許多其他應(yīng)用程序在內(nèi)的多人游戲。 但是,它并沒有在開發(fā)企業(yè)應(yīng)用程序的企業(yè)程序員的頭腦中走得很遠(yuǎn)。
我相信Netty可以引入一種新的功能,這是其他解決方案無法比擬的,因?yàn)樗哂型耆p向的文本和二進(jìn)制非HTTP數(shù)據(jù)傳輸功能,并且比傳統(tǒng)的“每線程線程數(shù)”支持更多的并發(fā)客戶端”服務(wù)器。
您可能知道Netty在WebSockets方面的能力,但是您知道它可以像傳統(tǒng)的Web服務(wù)器一樣出色地工作嗎? 由于其非常周到的設(shè)計(jì),通過在其管道中添加適當(dāng)?shù)奶幚沓绦?#xff0c;Netty幾乎可以處理任何流量。 它還可以同時(shí)處理多種類型,例如同時(shí)在同一端口上處理WebSocket和HTTP。 通過將這些結(jié)合在一起,程序員可以免于處理諸如CORS(跨源資源共享)之類的麻煩,當(dāng)瀏覽器嘗試向未從其下載的服務(wù)器發(fā)出請求時(shí),這些麻煩可以抬頭。
凈值的力量
為了顯示其轉(zhuǎn)換企業(yè)應(yīng)用程序的功能,我整理了一個(gè)代碼示例,顯示了Web的傳統(tǒng)示例之一,該示例檢索股價(jià)。
其他應(yīng)用程序必須發(fā)出AJAX請求,輪詢,具有刷新按鈕等以更新價(jià)格。 WebSockets消除了任何這些需求。 創(chuàng)建持續(xù)開放的雙向連接后,客戶端和服務(wù)器都可以在需要時(shí)彼此對話,而無需任何協(xié)商。 因此,客戶端讓服務(wù)器知道任何用戶何時(shí)更改標(biāo)準(zhǔn),并且只要相關(guān)數(shù)據(jù)基于該標(biāo)準(zhǔn)發(fā)生變化,服務(wù)器就會(huì)更新客戶端。
- 您可以在此處找到功能齊全的代碼。
我為客戶端設(shè)置了一些基于JSON的協(xié)議,以使服務(wù)器知道用戶的決定。 要將新符號添加到服務(wù)器正在監(jiān)視客戶端的列表中,只需要一個(gè)簡單的調(diào)用即可。 這是一個(gè)例子:
doSend('{"command":"add", "tickerSymbol":"GOOG"}');這會(huì)將符號添加到列表中。 服務(wù)器的下一次更新將在其數(shù)據(jù)中包括新符號的當(dāng)前股價(jià)(來自Yahoo Finance的REST API)。 刪除項(xiàng)目同樣容易:
doSend('{"command":"remove", "tickerSymbol":"GOOG"}');使用這兩個(gè)命令,客戶端可以控制服務(wù)器正在為每個(gè)用戶監(jiān)視的符號列表。 在Netty處理程序的服務(wù)器端,程序員要考慮多個(gè)用戶的唯一工作是確保為每個(gè)新連接創(chuàng)建一個(gè)新的處理程序,并且在不共享數(shù)據(jù)的地方不使用靜態(tài)成員。 。 除非另有說明,否則Netty假定處理程序不可共享。
讓我們看看如何為Netty管道定義處理程序。 這來自StockTickerServer類:
ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast("encoder", new HttpResponseEncoder()); p.addLast("decoder", new HttpRequestDecoder()); p.addLast("aggregator", new HttpObjectAggregator(65536)); p.addLast("handler", new StockTickerServerHandler()); } });這里的順序非常重要,因?yàn)楣艿乐械拿總€(gè)處理程序都有機(jī)會(huì)處理(或不處理)數(shù)據(jù)并將其傳遞給下一個(gè)處理程序。 股票行情處理程序位于底部,因?yàn)樗菍?shù)據(jù)發(fā)送回客戶端的程序,因此位于管道的末端。 通過創(chuàng)建處理程序的新實(shí)例,每個(gè)新連接都將獲得每個(gè)處理程序自己的實(shí)例。 如果處理程序是無狀態(tài)的并且是線程安全的,則可以在適用的情況下使用單例代替以節(jié)省內(nèi)存。 我使用的處理程序中沒有一個(gè)是可共享的,因此這里沒有顯示示例。
Netty作為Web服務(wù)器
使用一些技巧來使Netty同時(shí)處理HTTP和WebSocket通信。
1. StockTickerServerHandler擴(kuò)展了SimpleChannelInboundHandler <Object>
這告訴Netty,我們希望所有流量都到達(dá)此處理程序。 否則,如果只想處理HTTP通信,則可以使用SimpleChannelInboundHandler <FullHttpRequest>;如果只想處理WebSocket通信,則可以使用SimpleChannelInboundHandler <WebSocketFrame>。
2. channelRead0(通道讀取為零)方法
@Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof FullHttpRequest) { this.handleHttpRequest(ctx, (FullHttpRequest)msg); } else if (msg instanceof WebSocketFrame) { this.handleWebSocketFrame(ctx, (WebSocketFrame)msg); } }這使我們能夠根據(jù)每種協(xié)議處理HTTP和WebSocket通信。 handleHttpRequest提供HTML,圖像,CSS,JavaScript和所有其他正常的網(wǎng)絡(luò)流量,handleWebSocketFrame指出了如何處理從客戶端發(fā)送的自定義消息。
3.啞劇類型
Netty沒有內(nèi)置對處理mime類型的支持,因?yàn)閃ebSocket調(diào)用本質(zhì)上并不需要它們。
我添加了Apache的mime類型文件的稍作修改的版本,并靜態(tài)加載了它。 我正在負(fù)載上進(jìn)行同步,因?yàn)槿绻枰?#xff0c;Netty可以在池的開頭創(chuàng)建很多處理程序,并且構(gòu)造函數(shù)可以同時(shí)由多個(gè)處理程序執(zhí)行。 由于該字段是靜態(tài)的,因此在映射變?yōu)榉莕ull之前,可以對其進(jìn)行多次加載。 同步靜態(tài)鎖(不是類的當(dāng)前實(shí)例)可以防止這種情況的發(fā)生。
其他詳情
handleWebSocketFrame方法處理WebSocket協(xié)議定義的不同“已知”幀類型。 收到全文框后,我會(huì)將其傳遞給我創(chuàng)建的接口的實(shí)現(xiàn)者,以指定如何處理業(yè)務(wù)邏輯。
該代碼存在于StockTickerMessageHandler中。 它創(chuàng)建一個(gè)后臺(tái)線程來檢索股票報(bào)價(jià)并將其發(fā)送給客戶端,并處理客戶端發(fā)送的命令。
那里有一些凌亂的代碼,用于處理Yahoo發(fā)送的Gzip壓縮數(shù)據(jù)并解析服務(wù)返回的JSON,以及一些使用java.util.concurrent類(例如Executor,AtomicBoolean,AtomicReference和CopyOnWriteArrayList)的代碼來保持后臺(tái)線程和Netty處理程序彼此踩踏,因?yàn)樗鼈児蚕碛嘘P(guān)通道和當(dāng)前符號列表的詳細(xì)信息。
我還使用Gson將傳入的JSON轉(zhuǎn)換為POJO,以便更輕松地對其進(jìn)行處理。 除此之外,這只是本例的業(yè)務(wù)目的。
關(guān)于身份驗(yàn)證的注意事項(xiàng)
我沒有時(shí)間向此示例添加身份驗(yàn)證。 如果這樣做的話,我會(huì)使用Shiro ,它是一種功能強(qiáng)大的身份驗(yàn)證/授權(quán)/密碼框架,可與普通應(yīng)用程序和Web應(yīng)用程序一起使用。 還缺少HTTPS支持,因?yàn)檫@是檢查股票價(jià)格的公共應(yīng)用程序。 有添加HTTPS(和WSS)的例子在這里 。
使用JavaScript WebSockets很難(如果不是不可能的話)的一件事是發(fā)送身份驗(yàn)證數(shù)據(jù)以及升級請求(即調(diào)用新的WebSocket(uri))。 因此,通常像通常的網(wǎng)站一樣首先發(fā)送HTTPS POST并設(shè)置auth cookie令牌。 這樣,當(dāng)發(fā)送升級請求時(shí),cookie會(huì)自動(dòng)發(fā)送。 使用身份驗(yàn)證時(shí),請記住使用HTTPS和WSS而不是HTTP和WS來保護(hù)數(shù)據(jù)。 身份驗(yàn)證到位后,就變成了在必要時(shí)檢查經(jīng)過身份驗(yàn)證的用戶的問題,注意某些流量應(yīng)始終通過(HTML,圖像等)。
- 代碼項(xiàng)目
結(jié)論
Netty已成為構(gòu)建新應(yīng)用程序的一種高性能,改變游戲規(guī)則的方法。 通過利用WebSockets提供的功能,當(dāng)今的企業(yè)應(yīng)用程序可以比現(xiàn)在更具交互性。 我希望您喜歡這個(gè)進(jìn)入Netty的小冒險(xiǎn),并請?jiān)徳愀獾臑g覽器客戶端,我只是沒有時(shí)間為此示例制作一個(gè)不錯(cuò)的Backbone.js客戶端應(yīng)用程序。
謝謝!
翻譯自: https://www.javacodegeeks.com/2015/03/netty-a-different-kind-of-websocket-server.html
總結(jié)
以上是生活随笔為你收集整理的Netty:另一种Web(套接字)服务器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓手机卸载软件怎么卸载干净(安卓手机卸
- 下一篇: 未来人类21w电脑配置(未来人类21万笔