背景
最近研究的同事对识别内核做了一些优化,将原先集成在casrserver的内核计算逻辑单独抽离出来做成了服务并且测试后性能有提升,需要casrserver服务配合做一些改造,我之前也有过类似的想法,这次正好识别工程团队没有人力支持,加上我之前维护过casrserver, 于是就去协助casrserver改造了。在修改之前先介绍一下当前的架构
当前架构
如上图,当前casrserver中既处理了网络连接,又完成了识别的计算任务,图中是一次语音请求的核心交互逻辑, 一条客户端连接过来,网络进程里会对应三个协程:
- recv协程负责接收客户端发上来的数据
- rpc协程负责将recv的数据发送给计算进程,然后接收计算进程返回的识别结果
- send协程将识别结果再回给客户端
为了做到异步三个协程之间用了两个队列进行通信, 关于这套架构更详细的介绍,见顺哥在2016年openresty大会做的 ppt分享。之前的架构介绍到这里,让我们再来看看新版修改后的架构。
改动后的架构
如图,原先在openresty中worker进程fork出来的计算进程已经抽离出来成为独立的服务,casrserver和asr kernel server通过cosocket进行通信。
实现
针对上述架构,在新的casrserver中主要做了如下修改:
消息格式
asr-kernel-server服务的同事定义了一套新的消息格式, casrserver对应的实现如下:
- 针对这个消息格式,casrserver里封装了protocol.lua, 用于tcp底层的数据包封装。
- 针对上层的业务数据,由 asr_kernel_helper.lua 中的pack和unpack完成业务数据的打包, 使用protobuf对数据进行序列化。
处理逻辑
- 客户端websocket连接进来的时候,同步建一条到asr-kernel-server的连接
- 在主协程中新起了两个协程分别做接收和发送逻辑,接收和发送可以全双工进行,不再需要发送完后一帧数据后等计算进程返回了才能发送下一帧数据,具体实现在asr_kernel.lua中的kernel.send和kernel.recv。
其他
由于移除了计算进程,因此对原有的代码进行了删减,主要有这些:
- 移除了服务启动前资源的同步、预热逻辑
- 移除了原先的rpc协程
- 移除了计算进程池的管理
- 移除了与计算进程的luasocket通信
优势
我认为将识别计算部分分离出来有如下好处
- 职责更加单一化,使基于openresty的casrserver可以更加专注于自身的业务逻辑,团队分工更加明确,识别内核的更新,不再需要casrserver出版本。
- 计算服务分离后,不再需要进程池管理,worker中也不用进行fork,可以充分发挥多worker的优势,使casrserver可以更加专注地处理网络io,
- 解决了casrserver和计算内核的绑定,单个casrserver支持更多的client连接,可以更好地进行分布式部署
- 原先nginx worker和计算内核通信使用的是阻塞式的,发送完一帧数据需要receive后才能发送下一帧,改造后收发可以用cosocket完全分离
- 困扰casrserver很久的计算内核相关的监控和日志问题,可以更好的解决掉。
关于识别计算进程分离的介绍大致就到这里了,下一篇讲讲实现文中protocol.lua时性能的优化。
微信扫一扫,订阅我的博客动态^_^