• Fastnet,三步完成高性能的网络开发


    前言

    在GO语言里,由于其天生的支持多并发,而且非常完善的实现了比线程更轻量级的协程的支持,使得GO一直在多并发的服务端组件的开发中占有较大的优势;特别是在云原生的大势来袭下;更多的搭建在云原生框架下的底层服务都是用了GO语言进行开发;服务端的底层开发就缺少不了网络通信的开发;今天咱们这个文章要给大家介绍的就是一款GO语言实现的,能非常方便就能实现高性能网络通信的开发包工具——Fastnet。

    Fastnet

    Fastnet的项目的Github地址

    http://github.com/gohutool/boot4go-fastnet

    Fastnet项目的创造思想来源于在GO语言里另一个以高并发,高性能著称的项目Fasthttp;Fasthttp实现比原生GO语言提供的http包要高至少10倍性能以上的http通信服务能力,被誉为当下最快的http GO语言包;有兴趣的朋友,可以查看笔者的另一篇文章《boot4go-gateway和nginx的性能测试大PK》;该文章介绍了使用fasthttp开发的一款Gateway产品,和使用Nginx作为Gateway进行性能测试的过程和PK结果;

    Fastnet采用fasthttp提供高性能http服务的实现思路,通过协程池,缓存池,对象池等实现技巧,将GO语言在多并发,高性能的优势更近一步的进行了提升和优化,从而实现了TCP/IP网络通信的高性能实现;Fastnet也作为了笔者另一个MQTT中间件产品的网络底层通讯的支持架构。

    使用Fastnet

    引入

    Fastnet只支持GO语言;首先引入fastnet包

    1. import (
    2. "github.com/gohutool/boot4go-fastnet"
    3. )

    初始化Listener

    作为网络通信;和http以及其他net包一样;服务端的编程都是从Listener开始; 在Listener初始化指定端口,

    1. l, err := net.Listen("tcp", ":9888")
    2. if err != nil {
    3. fmt.Println("Start server error " + err.Error())
    4. return
    5. }

    如上段代码所示, 初始化了一个服务端的Listener,端口指定为9888,Listener监听9888端口进行TCP/IP方式的通信;

    实现监听业务的Server

    Server是具体处理监听的端口的连接的对象,在监听建立成功以后,创建一个Server对象,该Server对象服务于Listener对象,当Listener对象Accept到客户端的连接以后,Server会处理该连接

    创建Server

    1. var s Server
    2. s = NewServer(WithMaxIdleWorkerDuration(10 * time.Second),
    3. WithMaxPackageFrameSize(1024*10)))

    上段代码,首先定义一个Server对象s; 然后通过fastnet提供的API,NewServer创建出一个Server对象,WithMaxIdleWorkerDuration是一个ServerOption对象,用来进行Server创建时的一些参数指定; 例如这里的WithMaxIdleWorkerDuration就是指定协程池的IDLE选项,10 * time.Second后如何协程没有任何处理内容,该协程将被协程池进行回收;还有更多的Options选项,可以查看github里的API文档

    事件监听

    fastnet通过事件的方式,将具体的处理逻辑交还给程序的开发者, fastnet封装了Accept, Read, Write,协议解析,协议封装等过程,作为开发者不需要关注这些过程,作为开发者,只需要关注在自己的具体业务上,比如解析出来的协议包具体应该去做怎样的业务处理, fastnet就是通过事件的方式,将通信中的过程封装到了内部,然后通过事件的方式,去触发具体的业务实现;

    1. decoder, _ := codec.VariableLengthFieldFrameDecoder(
    2. 1024*1024, 2, 0, func(variableLength uint64) uint64 {
    3. return 2 + variableLength
    4. })
    5. onClose := OnClose(func(ctx *RequestCtx, err error) {
    6. if err != nil {
    7. fmt.Printf("%v\n", err)
    8. }
    9. })
    10. onData := OnData(func(ctx *RequestCtx, b []byte) error {
    11. ctx.Write(b)
    12. // ctx.WriteToChannel(b)
    13. return nil
    14. })
    15. s.ByteBufferDecoder = decoder
    16. s.OnData = onData
    17. s.OnClose = onClose

    上述代码是一个标准的指定业务处理的Sample代码;在代码中指定了decoder是一个变长数据帧的协议包解析器,用来进行协议帧的解析, 接着定义了onClose的事件函数监听Close事件;定义了onData的事件函数监听数据包的解析成功的Data事件,然后指定给server对象,通过上面的处理,fastnet就可以知道协议的通信帧的协议格式,通过协议格式解析到一个协议包以后,就会触发onData事件,交给业务定义的onData函数进行处理;让建立的连接关闭以后,将触发OnClose事件,交个业务逻辑来处理;

    在fastnet里内置了场景的几种协议帧的解析器

    DelimiterBasedFrameDecoder

    LineBasedFrameEncoder

    FixedLengthFrameDecoder

    FixLengthFieldFrameDecoder

    LengthFieldBasedFrameDecoder

    也可以通过fastnet提供的ByteBufferDecoder的扩展机制,自己来进行协议栈的扩展

    启动服务

    完成Server对象的初始化和设置以后,就可以启动Server对象,来完成服务端的启动了;

    1. err = s.Serve(l)
    2. if err != nil {
    3. panic(err)
    4. }

    最后来看看效果

    在fastnet的项目中,自带了一个EchoServer的实现,实现了echo服务,通过echo服务我们可以进行fastnet的性能测试,可以完全纯净的看看TCP/IP通信的性能测试;

    使用tcpdebug进行简单的通讯测试

    使用Jmeter压力测试

    结束语

    本文介绍了GO语言开发的一款提供实现高性能TCP/IP网络编程的开发包fastnet; 文中简要的介绍了fastnet的基础用法,fastnet已经在笔者开发的mqtt的中间件产品里作为底层通讯架构的实现; fastnet不仅实现了高性能的TCP/IP通讯的开发架构,也在开发架构中提供了一些扩展的机制,包括协议栈的扩展,消息机制的扩展;更多的信息可以在github项目里查看。

    谢谢大家继续关注

  • 相关阅读:
    C++入门(3):引用,内联函数
    uniapp移动端实现上拉加载(分页),下拉刷新
    Reset信号如何同步?
    运动学基础列表
    圆通山美食城旅游发展总体规划
    基于web在线餐饮网站的设计与实现——仿Coco线上订奶茶饮料6个页面(HTML+CSS+JavaScript)
    Springboot建筑造价师资格考试应试网站毕业设计源码260839
    改版后的PMP到底有多可怕,考试内容详细解读放这里了,看不看依你!
    华为机试真题 C++ 实现【连接器问题】【2022.11 Q4新题】
    区块链技术如何对抗疫情
  • 原文地址:https://blog.csdn.net/inthirties/article/details/126700874