前言:
提到dns, 让我们想起了 gethostbyname, gethostbyaddr 相关函数(线程安全的使用 getaddrinfo, getnameinfo), 不过他们都是阻塞函数, 在服务器端我们还需要额外构建一个异步环境来支撑这些阻塞函数运行.
需求:
这几天因为这些阻塞函数导致我想编写一个内部的name service, 开始想得是直接在引擎里开多个线程可以并发的处理大量的dns请求, 不过后来发现这样不但和引擎耦合起来, 还导致了引擎不必要的臃肿(每个引擎额外的开了几个线程), 干脆独立出来, 也方便了其他引擎使用 :)
实现原理:
实现起来非常简单, 大体说下思路, 首先创建好一个线程池, 视CPU核心个数调整线程数量, 可以稍微多一些, 毕竟这些函数都是阻塞函数, 多开几条线程也无所谓并不会引起过高的上下文切换, 线程池自带一个队列缓冲未能执行的请求.
诸如getaddrinfo返回的结果通过协议封装发回给原请求端即可, 不过这里需要注意的是, 协议的定制时需要额外增加一个参数用来记录请求的ID, 因为请求端的逻辑为异步, 为了保证能正确唤醒具体的corotinue, 引擎在发送请求时需要为每次请求生成一个ID, 这里使用内部自增ID或者uuid均可.
协议方面, 引擎使用c+lua搭建, 支持4种协议格式: byte, word, dword, string. 像dns这种复杂的结构直接转换成JSON格式传递过去, 对端再解析即可~ , 这样做的好处是既简化了协议层的复杂度, 又让协议层具备了良好的扩展能力.
因为name service是上下文无关, 所以其逻辑具备高度并行性, 完全无锁, ok, 简单精巧, 稳定高效.