国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

京東到家基于Netty與WebSocket的實(shí)踐

開源
在京東到家商家中心系統(tǒng)中,商家提出了要在 Web 端實(shí)現(xiàn)自動(dòng)打印的需求,不再需要人工盯守點(diǎn)擊打印,直接打印小票,以節(jié)約人工成本。

在京東到家商家中心系統(tǒng)中,商家提出了要在 Web 端實(shí)現(xiàn)自動(dòng)打印的需求,不再需要人工盯守點(diǎn)擊打印,直接打印小票,以節(jié)約人工成本。

解決思路

關(guān)于問題的兩種思考邏輯:

  • 可以用 ajax 來輪詢服務(wù)端獲取最新訂單,也就是 pull。
  • 可以用類似推送的設(shè)計(jì)來實(shí)現(xiàn),也就是 push。

我們?cè)u(píng)估了兩種思路的優(yōu)缺點(diǎn):

  • ajax 方式實(shí)現(xiàn)簡(jiǎn)單,只需要定時(shí)從服務(wù)端 pull 數(shù)據(jù)即可,但也增加了很多次無效的輪詢,即無形中增加服務(wù)端無效查詢。
  • push 方式實(shí)現(xiàn)稍復(fù)雜,需要服務(wù)端與 PC 端保持連接,這就需要建立長(zhǎng)連接,最終通過長(zhǎng)連接的方式來實(shí)現(xiàn) push 效果。

經(jīng)過討論,我們選擇了第二種,訂單中心生產(chǎn)出的新訂單,通過 MQ 的方式推送給 Web 端,最終獲得一個(gè)比較好的用戶體驗(yàn)。

方案介紹

關(guān)于長(zhǎng)連接方案的選擇,我們參考了不少帖子,最終選擇了使用 websocket 協(xié)議來實(shí)現(xiàn)長(zhǎng)連接,類似場(chǎng)景如 IM,服務(wù)端即時(shí)推送等都使用了這個(gè)協(xié)議。

接下來我們比較一下 websocket 的框架,比較主流的有 netty、tomcat、socketIO 三個(gè)框架:

  • 基于支持 websocket 的容器,開發(fā)簡(jiǎn)單,例如 tomcat,但在高并發(fā)的支持不是很好,連接的時(shí)候容易連接斷開,還有就是依賴容器。
  • netty-socketIO 是在 netty4 基礎(chǔ)之上做了一層封裝,效率如同 netty 一樣,是一個(gè)全平臺(tái)方案,友好的 API。京東的 logbook 也是用了 socketIO 來傳遞日志,也是我們的一個(gè)備選方案。
  • netty 是業(yè)內(nèi)主流的 NIO 框架,netty 對(duì) Java NIO 做了封裝,讓開發(fā)者更多關(guān)注業(yè)務(wù),降低開發(fā)成本。

很多著名的 RPC 框架都采用了 netty 作為傳輸層,友好的 API,功能強(qiáng)大,內(nèi)置了很多編解碼協(xié)議,實(shí)現(xiàn) websocket 協(xié)議也是十分方便。

那我們橫向比較一下這些框架:

所以在選型方面我們還是定位在 socketIO 與 netty 上面,在兼顧擴(kuò)展性與靈活性的同時(shí),我們也考慮到 netty 可以提供 http 的功能。

最終我們選擇了使用 netty,當(dāng)然 socketIO 封裝了很多功能,也是十分強(qiáng)大,相比較來說 netty 更適合我們,比較輕量。

Netty 的特性

netty 具有異步非阻塞的特性,傳統(tǒng) IO 是面向流的,NIO 是面向緩沖區(qū)的,這也是它的非阻塞原因所在。

netty 的線程模型如圖所示:

這種模型就是我們常說的 Reactor 模型,boss 線程其實(shí)是一個(gè)獨(dú)立的 NIO 線程池,用于接收 client 請(qǐng)求,默認(rèn)線程池大小為 1,worker 線程池用于處理具體的讀寫操作,默認(rèn)線程池大小為 2*cpu 個(gè)數(shù)。

在上述模型中要特別注意 ExecutionHandler,ExecutionHandler 是運(yùn)行在 worker 線程中的,所以耗時(shí)的操作最好在線程池中運(yùn)行, 比如 IO 或者計(jì)算,不然會(huì)影響整個(gè) netty 的吞吐。

了解了這些,我們根據(jù)自己的業(yè)務(wù)設(shè)計(jì)出流程,如下圖所示:

  • 步驟 1:Web 端請(qǐng)求服務(wù)端進(jìn)行注冊(cè),注冊(cè)成功保持長(zhǎng)連接。
  • 步驟 2:服務(wù)端發(fā)送 MQ。
  • 步驟 3:netty 將收到的消息推送給 Web 端。
  • 步驟 4:Web 端調(diào)用打印控件進(jìn)行打印,打印控件需提前安裝好(打印控件是 PC 上安裝的一個(gè)驅(qū)動(dòng)程序,用過 JS 方式來調(diào)用)。

如果調(diào)用 JS 成功,控件將把打印信息放入打印隊(duì)列,如果不成功,重復(fù)步驟 4。

當(dāng)然現(xiàn)在的結(jié)構(gòu)只是單機(jī)版,不滿足生產(chǎn)條件,那將來的結(jié)構(gòu)可能會(huì)演變成如下圖所示:

我們會(huì)在服務(wù)端與 netty 之間建立路由層,路由層的主要職責(zé)有:

  • 收集集群存活信息
  • 記錄落點(diǎn),就是落在哪一臺(tái)機(jī)器上面
  • 接收消息與分發(fā)消息

有了這三種能力,我們就可以輕松的指定信息分發(fā)策略。我們希望使用 http 協(xié)議來路由,這就需要 netty 有 http 短連接接收的能力 ,所以 netty 整體上需要長(zhǎng)短連接兩種能力。

下面是部分代碼:

netty 啟動(dòng)類,我們通過 spring 來啟動(dòng) netty,因?yàn)?netty 啟動(dòng)會(huì)阻塞主線程,所以需要在子線程中來啟動(dòng) netty,下面是啟動(dòng)參數(shù)。

接著來寫我們的 ChannelInitializer,HttpServerCodec 為編解碼器,WSServerProtocolHandler 為 websocket 協(xié)議握手。

我們更關(guān)注業(yè)務(wù)層面自定義的兩個(gè) hander,httpRequestHandler,authorizeHandler。

httpRequestHandler 的作用是處理 URL 是否合法,接收參數(shù)。

httpRequestHandler 此方法中也可以根據(jù) URL 來過濾,自定義自己的短連接請(qǐng)求。

authorizeHandler 的作用是校驗(yàn)數(shù)據(jù)是否正確,如果正確會(huì)將 channel 保存到 map 中,通過 map 建立起業(yè)務(wù) ID 與通道之間的關(guān)系。

校驗(yàn)的過程我們?cè)?authorizeHandler 中的 channelRead 展開,如果未通過,直接關(guān)閉當(dāng)前 channel。

如果通過校驗(yàn),則通過 ctx.fireChannelRead(msg);方法將信息傳入下一個(gè) handler 去處理。

在項(xiàng)目里主要是以傳遞參數(shù)來進(jìn)行數(shù)據(jù)校驗(yàn)的,也就是通過 URL 傳參來實(shí)現(xiàn)。

在 httpRequestHandler 中我們將 URL 參數(shù) set 到 channel 的 attr 中,并傳遞給了下一個(gè) handler,也就是 authorizeHandler。

所以在 authorize 方法中我們可以利用 get() 方法得到參數(shù)值,u 是經(jīng)過加密的數(shù)據(jù),我們需要在這里進(jìn)行解密,解密失敗,可認(rèn)為校驗(yàn)失敗。

當(dāng)然如果有跨應(yīng)用的服務(wù),也可以通過 Cookie 的方式來進(jìn)行加密串的讀寫,通過 request.getHeader 是可以獲取 Cookie 中的信息,這就看具體業(yè)務(wù)了。

示例代碼如下:

這個(gè) map 可以理解為 servlet 中的 session,當(dāng)有信息需要傳送給某個(gè)客戶端時(shí),我們調(diào)用 map.get(key) 方式到當(dāng)前該客戶端的 channel,調(diào)用 writeAndFlush 方法將信息發(fā)送出去,下面舉例通過接收 MQ 消息后的處理邏輯。

接下來有人可能想到,如果通道關(guān)閉了怎么辦?map 中的 channel 是不是就失效了呢?

其實(shí)我們還需要有一個(gè)類似心跳的機(jī)制去維護(hù) channel,間接的去維護(hù)這個(gè) map。

如果是通道正常關(guān)閉,可以通過 channelInactive 方法來監(jiān)聽。

如果是長(zhǎng)時(shí)間空閑,在項(xiàng)目中我們使用了增加的 IdleStateHandler 來處理,通過覆蓋 userEventTriggered 方法來監(jiān)聽空閑 channel,當(dāng)某個(gè) channel 到達(dá)我們?cè)O(shè)置的超時(shí)時(shí)間時(shí),netty 會(huì)回調(diào)此方法。

至此,核心部分已經(jīng)處理完成,剩下的就是通過保存的 channel 來發(fā)送信息給客戶端了。

最后在 Web 端,我們采用了 reconnecting-websocket,它是一個(gè)小型的 JavaScript 庫,封裝了 WebSocket API, 提供了在連接斷開時(shí)自動(dòng)重連的機(jī)制,能夠幫助我們完成斷開重連的操作。

遇到的問題

經(jīng)過測(cè)試,在 ws 的 uri 后面不能傳遞參數(shù),不然在 netty 實(shí)現(xiàn) websocket 協(xié)議握手的時(shí)候會(huì)出現(xiàn)斷開連接的情況。

針對(duì)這種情況在 websocketHandler 之前做了一層 httpHander 過濾,將傳遞參數(shù)放入 channel 的 attr 中,然后重寫 request 的 uri,并傳入下一個(gè)管道中,基本上解決了這個(gè)問題。

在讀寫空閑的時(shí)候盡量以發(fā)心跳包的方式維護(hù)連接,但在客戶端由于網(wǎng)絡(luò)不穩(wěn)定或者是服務(wù)端重啟,連接會(huì)斷開,瞬間有可能接收不到訂單消息,為此在客戶端需要實(shí)現(xiàn)斷開重連機(jī)制。

此問題我們采用 reconnecting-websocket的 JS 框架,此框架擴(kuò)展了原生 websocket 的實(shí)現(xiàn),做了斷開重連機(jī)制,有效的防止斷開后不能及時(shí)連接。

在測(cè)試過程中由于控件與小票機(jī)的問題,可能會(huì)出現(xiàn)打印異常或者小票機(jī)沒紙的情況。Lodop 控件可以將打印信息放入電腦的打印隊(duì)列。

如果沒紙了,小票機(jī)會(huì)報(bào)警,再次放入小票紙,打印機(jī)會(huì)自動(dòng)打印隊(duì)列中的數(shù)據(jù)。

出現(xiàn)調(diào)用控件異常偶爾發(fā)生,現(xiàn)在處理辦法是在 JS 中進(jìn)行了的 try catch。

如果失敗,進(jìn)行重試,重試次數(shù)自定義,超過重試次數(shù)暫不做處理,此處還不太嚴(yán)謹(jǐn),需要再進(jìn)行優(yōu)化。

總結(jié)

通過上面的實(shí)踐,我們基本已經(jīng)實(shí)現(xiàn)了 Web 端的自動(dòng)打印,經(jīng)過長(zhǎng)時(shí)間的內(nèi)部測(cè)試,服務(wù)端與客戶端通信穩(wěn)定,我們將灰度商家做用戶體驗(yàn)。

在特定的場(chǎng)景下,選擇適當(dāng)?shù)募夹g(shù)會(huì)提高我們的效率,否則會(huì)適得其反。

選擇長(zhǎng)連接,大家可以把握這三個(gè)大原則:

  • 服務(wù)端是否需要主動(dòng)推送數(shù)據(jù)到客戶端以實(shí)現(xiàn)控制的效果。
  • 對(duì)于實(shí)時(shí)性的要求是否苛刻。
  • 對(duì)于客戶端是否需要關(guān)注它在線狀態(tài)的實(shí)時(shí)變化。

責(zé)任編輯:武曉燕 來源: 達(dá)達(dá)京東到家
相關(guān)推薦

2018-11-06 14:05:27

京東訂單派發(fā)架構(gòu)

2019-08-30 12:30:25

京東到家訂單查詢數(shù)據(jù)存儲(chǔ)

2018-12-20 06:04:02

京東到家訂單中心Elasticsear

2017-12-12 08:40:00

2019-01-14 09:06:40

LBS定位系統(tǒng)架構(gòu)

2019-01-17 09:50:55

京東ES架構(gòu)

2022-02-12 20:51:23

京東程序員代碼

2019-01-02 14:55:54

MySQLES數(shù)據(jù)庫

2024-08-02 09:00:17

NettyWebSocketNIO

2022-02-14 08:13:33

刪庫MySQL備份

2021-03-18 14:34:34

達(dá)達(dá)集團(tuán)京東云電商

2021-11-24 08:55:38

代理網(wǎng)關(guān)Netty

2024-10-15 08:14:51

2022-06-30 09:30:36

FlinkSQL流批一體京東

2022-02-11 15:01:07

程序員刪庫計(jì)算機(jī)

2016-08-05 13:19:29

GET請(qǐng)求github項(xiàng)目 POST請(qǐng)求

2021-02-05 07:28:11

SpringbootNettyWebsocke

2021-12-08 10:35:04

開源監(jiān)控Zabbix

2019-11-01 15:50:06

MySQLES搜索引擎

2021-08-09 09:48:16

NettyChannelHand架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲一区二区三区在线| 素人啪啪色综合| 另类图片综合电影| 亚洲区一区二区三区| 欧美揉bbbbb揉bbbbb| 亚洲乱码精品| 九九在线视频| 亚洲精品欧美极品| 亚洲成在线观看| 亚洲综合图色| 91精选福利| 国自产精品手机在线观看视频| 日本一区二区成人在线| 精品亚洲精品| 日韩加勒比系列| 国产精品自拍网| 色呦呦国产精品| 亚洲国产激情| a级毛片免费观看在线| 欧美在线3区| 亚洲毛片一区二区| 成人免费视频caoporn| 99久久99九九99九九九| 少妇网站在线观看| 国产精品视频26uuu| 一本久道久久综合中文字幕| 亚洲中午字幕| 在线免费看h| 国内外成人免费激情视频| 欧美国产日本高清在线 | 91天堂素人约啪| 露出调教综合另类| 羞羞视频在线免费看| 日本精品二区| 久久精品国产精品亚洲| 一区二区三区资源| 亚洲免费高清| 精品裸体bbb| 另类图片亚洲色图| 国产精品区二区三区日本| 亚洲第一级黄色片| 国产欧美在线观看一区| 欧美三级电影在线| h视频在线观看免费| 超碰97在线看| 国产91精品高潮白浆喷水| 91黄色免费版| 成人综合在线网站| 欧美限制电影| 日韩大片免费观看| 国产jizz| 欧美一区二区三区成人久久片| 九九热精品在线| 欧美性猛交xxxx久久久| 国模一区二区三区白浆| 日韩精选在线| 欧美大胆的人体xxxx| 热久久精品免费视频| 国产亚洲福利社区| 欧美成人精品激情在线观看| 欧美视频一区二区三区…| 国产精品一区二区三区乱码| av中文字幕一区二区| av中文字幕在线观看第一页| 黄色成人av| 7777在线视频| 91网站在线看| 久久视频国产精品免费视频在线| 色综合久久久久网| 99久久99久久免费精品蜜臀| 海角社区69精品视频| 综合欧美精品| 麻豆av在线免费看| 亚州av影院| 4444亚洲人成无码网在线观看| 国产精品激情| 日产精品一区二区| 中文字幕一区二区三区四区| 日韩精品一级中文字幕精品视频免费观看 | www国产亚洲精品久久网站| 91在线看黄| 日韩av一区二区三区四区| 国内久久精品| 九热爱视频精品视频| 久久不射中文字幕| 国产精品乱码妇女bbbb| 久久乐国产精品| 日韩a在线播放| 一级毛片久久久| 国产一区二区三区四区在线观看| 精品亚洲自拍| 异国色恋浪漫潭| www.亚洲免费视频| 日韩av日韩在线观看| 日本一区高清不卡| 午夜视频国产| 一区二区三区四区视频免费观看 | 一片黄亚洲嫩模| 不卡伊人av在线播放| 中文字幕一区二区三区乱码| 在线观看免费版| 亚洲承认在线| 91精品国产福利| 免费久久99精品国产自| 国产精品刘玥久久一区| 久久久久电影| 精品1区2区3区| 国产在线视频一区| 亚洲精品久久久中文字幕| 久草热久草在线频| 在线观看视频免费| 亚洲最大在线| 国产日韩欧美在线一区| 在线中文字幕不卡| 91精品国产综合久久久蜜臀粉嫩| 中文字幕欧美国内| 日本一区二区三区视频免费看| 一不卡在线视频| 亚洲一级淫片| 日韩一级精品视频在线观看| 91在线网站| 成人av综合一区| 蜜桃传媒一区二区| 少妇精品久久久一区二区三区| 亚洲韩国青草视频| 在线免费av网站| 国产精品乱人伦一区二区| 艳母动漫在线观看| 日韩精品1区2区3区| 96pao国产成视频永久免费| 日韩在线视频一区二区三区| 在线日韩中文字幕| 日韩色性视频| 中文字幕综合一区| а√天堂8资源在线| 国产精品美女久久久久高潮| 欧美日韩系列| 狠狠一区二区三区| 日韩欧美成人午夜| 电影天堂爱爱爱爱| 国产精品99久久不卡二区| 欧美做爰性生交视频| 黄色成人免费网| 91麻豆精品国产91久久久更新时间 | 欧美大荫蒂xxx| 欧美女同在线观看| 亚洲老妇xxxxxx| 在线免费观看的av| 久久夜色精品亚洲噜噜国产mv| 日韩欧美亚洲一区| 亚洲精品**不卡在线播he| 国产精品国产成人国产三级| 欧美高清视频免费观看| 免费**毛片在线| 国产精一区二区| 亚洲欧美一区二区三区国产精品 | 中文av一区| 亚洲视频网在线直播| 欧美激情国产日韩精品一区18| 一本大道熟女人妻中文字幕在线| 鲁大师成人一区二区三区| 国产精品成熟老女人| 色的视频在线免费看| 久久a级毛片毛片免费观看| 成人午夜视频免费看| 久久久久久久久电影| 亚洲 自拍 另类小说综合图区| 超碰在线cao| 亚欧成人精品| 91精品国产综合久久福利软件| 91嫩草免费看| 两个人看的免费完整在线观看| 女生裸体视频一区二区三区| www高清在线视频日韩欧美| 免费在线国产精品| 成人看片黄a免费看视频| 亚洲欧美视频| 精品日韩一区二区三区免费视频| 青青操视频在线| 制服.丝袜.亚洲.另类.中文| 青春草视频在线观看| 深夜福利亚洲导航| www.久久99| 国产成人精品在线视频| 欧美va久久久噜噜噜久久| 国产一区二区精品在线| 久久午夜视频| 男女午夜激情视频| 国产人伦精品一区二区| 日本一区二区三区在线视频| 欧美精品91| 国产精品香蕉在线观看| 国产精品免费不| 久久久久一本一区二区青青蜜月| 国产精品1区| 亚洲一区二区国产| 电影一区电影二区| 欧美美女18p| 欧美大片网站| 日韩欧美在线影院|