结解析器:模块中的并列性和并发性

时间:2016-10-06 23:55:25

标签: dns

上下文

Dear Knot Resolver用户,我有一个module that hooks into Knot's finish阶段,

 static knot_layer_api_t _layer = {
     .finish = &collect,
 };

收集功能static int collect(knot_layer_t *ctx) {的目的是通过REST API询问外部oraculum是否列出了包含恶意软件或网络钓鱼活动的特定域以及是否应该解析或沉没。

只要Knot Resolver没有针对数百个并发DNS请求,它就能正常工作。 当发生这种情况时,鉴于oraculum的API响应时间变化,有时可能长达数十到数百毫秒, 客户开始暂时感知来自Knot Resolver的非常长的响应时间,远远超过了与oraculum API的通信设置的硬超时。

可能的问题

我认为实际上是scaling-with-processes 渲染模块的效率非常低,因为查询正在排队和处理 模块逐个(在特定的过程中)。这意味着如果n查询了oraculum的API超时限制t,那么客户端 谁将n+1查询发送到此特定的kresd流程,将会感知到累计n*t的响应时间非常长。

还是会吗?我完全离开了吗?

当我使用goroutines在GoDNS中制作类似的功能时,GoDNS服务器(以可怕的CPU使用为代价)让众多 DNS客户端的查询与oraculum交谈并“同时”返回客户端。

问题

  • 是O.K.使用Apache Portable Runtime线程或OpenMP线程并开始隐藏API在模块中的响应时间?它不是一个完整的Knot Resolver反模式吗?
  • 我在一个简单的内存短暂LRU缓存中缓存oraculum的API响应,该缓存位于每个kresd进程中。是否有可能使用kresd自己的MVCC缓存代替我的任意结构?
  • 问题是否可能在其他地方,例如,Knot Resolver不期望finish层中的任何阻塞延迟,因此某些网络队列被填满,后续DNS查询被拒绝和/或无法忍受延迟?

感谢指针(双关语)

2 个答案:

答案 0 :(得分:1)

在这里结DNS开发者(不过解析器)。我想你是对的。我的理解是层代码在守护程序线程中同步执行。异步仅出现在解析器网络I / O级别。

在服务器内部运行libuv循环,它只对libuv(套接字,定时器,信号等)提供的基元上的事件执行回调。问题是你无法在任意点暂停正在运行的回调(C函数),转发回libuv循环,并在稍后的某个时刻继续执行回调执行。

也就是说,异步等待事件只能在预期的情况下发生。并且代码驱动层不期望这样。

<强>数目:

  • 我对libapr或OpenMP不太熟悉。但我不认为如果不重新设计图层界面并使其异步,就可以真正解决这个问题。

  • 可以肯定使用共享缓存。如果你找不到这个API,那么jolly Knot DNS会很乐意接受一个补丁或帮你写一个补丁。

  • 情况确实如此。 Knot Resolver不期望在图层完成回调中阻止代码。

答案 1 :(得分:1)

这里的Knot Resolver开发者:-)(我也重复了Jan已经回答的一些事情。)

  • Scaling-with-processes能够正常工作。等待来自名称服务器的响应由libuv完成(通过事件循环和回调,都在一个线程内)。
  • 由于采用单线程样式,因此不应阻止任何层功能(在I / O上),因为这会阻止所有内容阻塞。 AFAIK目前唯一可以实现的情况是缓存何时(部分)被换出。
  • 有YIELD状态http://knot-resolver.readthedocs.io/en/latest/lib.html?highlight=yield在处理图层可以继续之前需要子请求时使用它,但我目前不知道其工作的细节。我不认为这是直接适用的,因为恢复层目前似乎只是由子请求完成触发。
  • 缓存:如果您将模块放在rrcache模块之前并且更改了RRset,它将被缓存更改。