12.25 物聯網,車聯網netty服務器springboot支持圖形化源碼

先轉發,加關注後私信“netty源碼”即可免費獲取源碼

基於netty4,protoBuff的netty心跳服務器支持鑑權、斷線重連、其他業務模塊開發、支持圖形化實時監控,可直接投入生產

Netty心跳服務器

Springboot2.0.8集成 netty4 ,使用protobuf作為ping的數據交換,比json更加的小巧,佔用數據量更小,可用於任何第三方應用做心跳監控

應用場景

比如公司可以使用的一種業務場景是這樣的: 現有多臺服務器,有a業務的 有b業務的 有c業務的 有d業務項目等等,有時候用戶量大或者其他因素,這些服務器down掉了,大多數情況都是基於運維監控報警的,但是由於項目都是多臺機器部署同一個項目,項目掛了後centos主機並不能很快檢查出來,一般時間會比較長在半小時之內,甚至有的時候是用戶來打電話告知項目down掉了,這對公司來說影響多麼的大。 掛上了項目心跳後,可以實時看到100多臺機器的實時ping值是否正常,當然你也可以通過定時請求http接口來判斷是否應用正常,熟知http接口的請求耗費資源,使用本項目的ping或者其他鑑權,protobuff基本上消耗網路開銷非常的小,響應快,netty的長連接上線下立馬感知,性能穩定好。

物聯網,車聯網netty服務器springboot支持圖形化源碼

物聯網,車聯網netty服務器springboot支持圖形化源碼

物聯網,車聯網netty服務器springboot支持圖形化源碼

開發環境

  • JDK8+
  • IntelliJ IDEA
  • springboot 2.0.8.RELEASE
  • Netty4.1.6.Final
  • protobuf-java3.3.0
  • Redis
  • Thymeleaf模板
  • Echarts圖表
  • Tomcat8.5

項目說明

  1. 已完成功能
  • 客戶端授權驗證(基於protoBuff)
  • 心跳檢測(基於protoBuff)
  • 斷線重連
  • 計算ping值(支持到微秒)
  • 其他子業務模塊(架子已搭進去)
  • 為了方便測試,項目已經支持跨域訪問

說明

Netty是一個NIO客戶端服務器框架,可以快速輕鬆地開發協議服務器和客戶端等網絡應用程序。它極大地簡化並簡化了TCP和UDP套接字服務器等網絡編程。 “快速簡便”並不意味著最終的應用程序會受到可維護性或性能問題的影響。Netty經過精心設計,具有豐富的協議,如FTP,SMTP,HTTP以及各種二進制和基於文本的傳統協議。因此,Netty成功地找到了一種在不妥協的情況下實現易於開發,性能,穩定性和靈活性的方法。4x(推薦,穩定,jdk1.6+)

幾個常見的類

  • ServerBootstrap

netty服務器的幫助類

  • NioEventLoopGroup

處理I/O操作的多線程事件循環相當於一組線程池,服務器一般需要指定兩個NioEventLoopGroup,一個作為監控tcp連接的,一個作為處理io事件的,前者默認1個線程就可以,後者最好是cpu核心數的2倍 客戶端用一個就夠了

  • NioServerSocketChannel

主要是server端接收建立SocketChannel用的

  • NioSocketChannel

主要是客戶端接收SocketChannel用的

  • ChannelInboundHandlerAdapter

可以重寫的各種事件處理程序方法,包括channelRead()、exceptionCaught()等方法

  • SimpleChannelInboundHandler

可以重寫的各種事件處理程序方法,包括channelRead0()方法 這個可以跟指定的消息類型比上面的,如果自定義的消息類型用這個稍微多一點

  • ChannelPipeline

存放各種處理器,包括解碼器,編碼器等自定義處理器,idleStateHandler一定要放在第一個,傳送數據時,編碼器和解碼器一定要放在前面,這個加載是分順序的

  • ChannelHandlerContext

ChannelHandlerContext的writeAndFlush和ChannelHandlerContext.channel().writeAndFlush()是有區別的 前者是從當前hanler從後往前找OutputboundHandler,然後交給它執行的,後者是從最後一個開始執行handler的,最常見就是寫錯pipeline中的順序後,客戶端或服務器發消息就收不到了

  • ChannelInitializer

客戶端和服務器都要用這個的SocketChannel,初始化的時候,加載ChannelPipeline

  • Bootstrap

客戶端的連接幫助類

  • idleStateHandler

Netty 可以使用 IdleStateHandler 來實現連接管理,當連接空閒時間太長(沒有發送、接收消息)時則會觸發一個事件,我們便可在該事件中實現心跳機制

基本以上的幾個類就可以滿足日常的80%需求了,剩下就是書寫各自的業務

心跳服務器實現詳細過程

  1. 客戶端網絡空閒5秒沒有進行寫操作是,進行發送一次ping心跳給服務端;用自定義的消息格式類,其中包含驗證auth、ping、pong等類型來代表不同的業務,首次連接時候在ChannelInboundHandlerAdapter中可以建立連接,客戶端會發送一次auth類型的授權信息(用戶名+鹽值密碼),服務器收到後作出校驗響應,只有收到服務器的auth_ack響應客戶端才能做出連接,否則斷開當前鏈接,釋放鏈路;
  2. 客戶端如果在下一個發送ping心跳週期來臨時,還沒有收到服務端pong的心跳應答,則失敗心跳計數器加1;
  3. 每當客戶端收到服務端的pong心跳應答後,失敗心跳計數器清零;
  4. 如果連續超過3次沒有收到服務端的心跳回復,則斷開當前連接,在5秒後進行重連操作,直到重連成功,否則每隔5秒又會進行重連;
  5. 服務端網絡空閒狀態到達10秒後,服務端心跳失敗計數器加1;
  6. 只要收到客戶端的ping消息,服務端心跳失敗計數器清零;
  7. 服務端連續3次沒有收到客戶端的ping消息後,將關閉鏈路,釋放資源,等待客戶端重連;

心跳相關驗證

當客戶端超過三次沒有收到服務器pong,客戶端主動斷開當前channel連接,重連服務器

物聯網,車聯網netty服務器springboot支持圖形化源碼

當服務器超過三次沒有收到客戶端ping,服務器主動斷開當前客戶端的channel連接

物聯網,車聯網netty服務器springboot支持圖形化源碼

ping值設計過程

ping值是基於客戶端來的,即客戶端發送ping之後,會先記錄當前的時間(默認單位是ms),支持微秒的方法,當客戶端再次收到響應後,記錄當前時間a,因為數據傳輸雙方時間是相同的,所以拿當前時間b-a,再除以2就是ping值了。然後把這個ping值,記錄到redis中去。這裡使用的是 System.currentTimeMillis(),用new Date().getTime()時間會出錯,不知道為啥?看源碼是一樣的邏輯不大理解

起初是基於服務器計時的,但是服務器和客戶端不可能在一臺主機上,導致時間存在偏差,ping值就不準確了。 存到redis主要是為了使echarts訪問最近幾次的ping狀態。起初想做成websocket的,但是這樣的話,第一次進來當前頁面數據會不全,而且不好日後做歷史ping的統計

物聯網定製開發


物聯網,車聯網netty服務器springboot支持圖形化源碼


物聯網,車聯網netty服務器springboot支持圖形化源碼

先轉發,加關注後私信“netty源碼”即可免費獲取源碼


分享到:


相關文章: