typingMonkey
typingMonkey
一般通道的接收都是先反序列化,再根据反序列化的结果再match分发处理,如果Clone了,可能对哪个接收者Receiver会收到消息不一定有直观的预期,所以接收者的对于Clone的需求不太大。 但发送者Sender(代指ws-tool内ws相关的所有发送者)大多数时候都有分享到不同线程的需求。比如说推送通知,就有可能来自于不同系统的推送,也有可能来自其他客户端的推送。如果不能把Sender分享到不同线程的话,实现此类功能就很麻烦。 一般而言会考虑两种方式,一种是通道,一种是加锁: 标准库通道、crossbeam-channel、tokio通道、async-channel,都可以实现Sender的跨线程克隆; 标准库锁、parking_lot、tokio异步锁、fast-async-mutex也都可以克隆; 根据测试,同环境里原则上加锁最快(rustcc论坛里有发过测试结果),所以我试了ws-tool(主要是Frame相关的类型),同步环境下用parking_lot::mutex加锁(我是在ubuntu下测试的,window下可能标准库mutex更快),异步环境下用fast-async-mutex加锁,然后放进一个可分享的map里进行全局调度,可以成功运行。 Sender加锁后在执行send固然能够实现多线程分享,但却不是最佳实践,锁的粒度理论上还能够更细,最好细到write/write_all/write_vectored这个级别,但我看了FrameWriteState::send的源码,发现里面部分的write行为是拆分开来的,在单线程或独占的状态下直接write没问题,但不确定锁的粒度进一步细化后,导致write乱序是否会影响功能实现。 建议: 一、如有必要的话,应把同一个send/async_send里的写行为进行合并; 二、增加一个ShardedSender的类型,内建类型是`Arc`,普通Sender需要实现Clone/Into变成ShardedSender,ShardedSender克隆还是本类型,但Arc的引用计数为1时,可以into成Sender(不怎么用得到但也算保持类型可逆性)。
我看example的listenfd应该指的是平滑监听吧?理论上平滑重启的最佳实践是怎样的? 就比如用salvo实现网关,这种场景对平滑监听的要求高点。 关于平滑重启,我个人设想的流程是: - 新程序启动,初始化完成后发信号给旧程序 - 旧程序停止accept进入优雅停机流程,并发送信号给新程序 - 新程序通过旧程序共享的fd信息启动tcp监听 - 旧程序优雅停机结束后自动关闭进程 listenfd是通过环境变量共享fd信息的,但新旧程序传递信号用什么方式(tcp?unix?namedpipe?signals?http?)比较合适?如果双方有别的通信渠道,似乎好像就没必要用listenfd共享fd信息了? 感觉最省事的就是路由里搞一个优雅关闭api,新程序发送一个http请求给旧程序,旧程序启动优雅关闭后响应fd信息给新程序(也可以把需要共享的其他数据(本地缓存之类的)一起发了),然后新程序通过fd启动服务。