这俩天把之前写过的Zinx框架再重新回顾总结了一遍,这个项目对于我的帮助很大。当时就是让我醍醐灌顶一般,原来之前用的Web框架底层是这样子实现的。
Socket网络编程
服务端绑定端口Bind()
服务端开启监听端口Listen()
客户端向服务器ip、port发起拨号连接请求Dial()
服务端接收请求Accept()
高并发模型
服务端监听连接由一个go程承载,读写业务各由一个go程承载,而处理业务由一个go程承载。
如果有1000个用户连接,则会开启1+1000+1000+1000=3001个go程,由于读写业务有大部分时间不占CPU资源,所以会空闲。
但是感觉也可以变成1+1+1+1000=1003个go程,专门由1个go程负责读,一个go程负责写。
让我想起之前学习过的Linux中网络I/O复用并发模型中Reactor、Proactor模型
- Reactor 是非阻塞同步网络模式,感知的是就绪可读写事件。在每次感知到有事件发生(比如可读就绪事件)后,就需要应用进程主动调用 read 方法来完成数据的读取,也就是要应用进程主动将 socket 接收缓存中的数据读到应用进程内存中,这个过程是同步的,读取完数据后应用进程才能处理数据。
- Proactor 是异步网络模式, 感知的是已完成的读写事件。在发起异步读写请求时,需要传入数据缓冲区的地址(用来存放结果数据)等信息,这样系统内核才可以自动帮我们把数据的读写工作完成,这里的读写工作全程由操作系统来做,并不需要像 Reactor 那样还需要应用进程主动发起 read/write 来读写数据,操作系统完成读写工作后,就会通知应用进程直接处理数据。
工作池、消息队列机制
Zinx中使用工作池来代替频繁的创建、销毁go程所带来的资源消耗,使用M:N模型,设置工作池中Worker数量为CPU核数,每个Worker有一个消息队列,每个消息通过对连接ip进行取模进行映射到响应的Worker的负载均衡手段。
这让我想起了GMP模型,但是GMP模型有着更多的机制,比如全局任务消息队列,消息偷取,当某个Worker阻塞时,该Worker上的任务自动分配到其他的Worker等等机制。
负载均衡的手段上,在以后往分布式方向扩展时又让我想起了一致性哈希算法,可以很好的保证流量的均衡。
中间件函数
中间件是介于应用系统和系统软件之间的一类软件。用途是衔接网络上应用系统的各个部分或不同的应用,实现资源共享、功能共享。我们讨论的基础范畴是函数式编程,这里的中间件不是真正意义上的中间件。准确点说,它是一种设计模式、编程思想、是函数与函数之间的组合方式。这种中间件设计模式,应用最广泛的场景是express和koa框架中,数据请求Request和数据响应Response的应用模型,通常叫做洋葱模型。
我用过的Django、Gin框架中都支持中间件函数的调用,也就是在链接成功之后业务函数处理业务之前通过用户自定义函数将请求统一做处理。或者在请求断开之前做处理。
封包、拆包、粘包
通常使用的web框架都是帮我们封装好的,比如你要访问的路由、文件、资源等都会被封装在一个包中给发到服务端,服务端要以相同的格式进行拆包解析,比如http协议中的method(get、post),文件路径等等。Zinx中也对消息进行了简单的TLV格式封装消息。我们可以通过自定义的格式进行消息结构的设计。
架构思想
压力测试
文章参考
感谢 @刘丹冰 大佬的教学视频和项目
https://blog.csdn.net/qq_46284579/article/details/125125980
https://zhuanlan.zhihu.com/p/361954335#
https://zhuanlan.zhihu.com/p/364044293