天天看點

他山之石,可以攻玉,改造fasthttp實作高性能網絡通信

作者:程式員紫龍

前言

如果朋友看過在下上一篇文章《性能不遜Nginx的Gateway,性能測試大PK》,能在反向代理的性能PK中完勝Nginx的Gateway,是使用GO語言在基于比Go的标準http包快10倍以上的Fasthttp的基礎上開發的;Fasthttp在Go語言裡,以其卓著的性能優勢而聞名,為什麼fasthttp能有如此卓越的性能優勢了,網上可以找到很多此方面的文章介紹。

簡要而言:

一、是對每個連接配接請求和連接配接處理的協程進行了池化的處理;

二、是通過合理的對象池的處理盡可能的對性能進行壓縮;

三、盡量減少多餘的記憶體拷貝。

他山之石,可以攻玉,改造fasthttp實作高性能網絡通信

FastNet

Fasthttp的處理http連接配接請求上的通過以上三種主要的優化方式,實作了高于Go标準Http包10倍以上的性能;可惜之處就是僅僅隻支援了http層的第7層應用協定;如果能有一些做到了基于TCP協定之上的會話層的協定的處理包,那就可以基于這個包進行網絡通信的開發,去實作自己的會話協定的各種用戶端/服務端的通信程式,同時還具有和fasthttp同樣高的網絡通信能力,例如: 在我們開發的一款MQTT伺服器中間件的産品中,我們就需要實作自己的伺服器來支援其他傳感器或者物聯網終端通過mqtt發送過來的Mqtt協定消息;我們就是在fastnet的基礎上,根據Mqtt3.1/3.1.1/5.0的協定規範來實作的,在實作的過程中,不需要考慮低層的通信過程的處理;完全把所有的實作都關注在Mqtt的三個版本的協定幀的處理和标準業務處理上;這個就是fastnet能夠給我們帶來的優勢。

他山之石,可以攻玉,改造fasthttp實作高性能網絡通信

GO語言其他Net庫

在構思和立項Fastnet這個項目之初,我們還是希望能夠找到Go語言裡比較的一些開源項目去進行改造來達到類似的效果;并對Go語言裡有關網絡通信的開源項目進行了一定的研究;

其中以兩種類型為多:

一:以epoll、gnet為代表的,通過實作epoll方式來實作Nio通信的網絡通信庫;通過epoll的方式來優化網絡通信的性能和效率

二:以go-netty為代表的,通過實作netty的bootstrap/group/channel/eventLoop/eventHandler對象模式這樣偏重于模仿netty的設計模式來實作通信庫,目的主要是簡易化網絡通信的應用實作。

他山之石,可以攻玉,改造fasthttp實作高性能網絡通信

這兩類方法,

前一類都是借鑒了redis和java實作的netty的nio的實作模式;可能是對網絡底層的知識沒太多掌握,實在是對epoll的一些代碼沒有讀懂;主要是裡面有一些使用了goc的方式,對這塊的彙編代碼實在不懂,加上時間也不太充分,是以就沒有更細緻地開了,加之對etcd的網絡通信這塊的代碼研究的時候,發現其也沒有使用epoll的處理方式,而是直接使用的net庫進行改造的;是以就果斷地放棄了epoll這樣的實作方式。畢竟Hold不住,而且也有知名項目使用了非epoll方式;

對于第二類主要是通過模拟java中netty的對象設計模式,優化的是開發的效率,但是由于設計模式方面的考慮,實作中會使用一些反射和備援多餘的類(設計模式的通病)。這樣的方式性能都是由較大的考驗的,特别是反射,在java中,由于java主要是做業務類項目,相對于CRUD這樣的業務操作比較起來,反射的這點影響完全被忽略了,但是對于Go開發的底層服務來說,反射和底層通信調用的代碼執行效率差的都是幾個兩級的差距,在大并發量的情況下,将會把這個差距放大非常大;是以對于這個go-netty項目而言,我們更多的考慮是借鑒這裡的對象模型,然後實作常用的Decoder/Encoder, 盡量做工具型API級别的封裝。

最終的Fastnet實作方式

Fastnet在這些網絡通信庫的研究基礎上,綜合各自的優點,最終的方案決定采用fasthttp的實作方式。

一、在對連接配接接入和通信的Input/Ouput處理上使用協程池來對協程資源進行優化。

二、盡可能的使用對象池的方式對回收較頻繁的進行池化處理

三、盡可能地減少記憶體複制

四、提供業務的常用的Decoder和Encoder的工具包封裝。

結束語

正所謂的“他山之石,可以攻玉”,通過借用Fasthttp的實作高性能http通信的方式方法;fastnet也實作了非常好的性能的網絡通信,

fastnet的項目位址

github.com/gohutool/boot4go-fastnet

歡迎大家下載下傳使用

在以後的文章中,我們會分享最後的fastnet和epoll的性能PK;

繼續閱讀