我在 Python3 DNS 服务器上工作,我遇到了使用 socketserver 模块每秒最大查询数的问题。
经典Bind9服务器有统计:
DNS Performance Testing Tool
Version 2.11.2
[Status] Command line: dnsperf -s 127.0.0.1 -d example.com -l 60
[Status] Sending queries (to 127.0.0.1:53)
[Status] Started at: Mon May 8 14:26:55 2023
[Status] Stopping after 60.000000 seconds
[Status] Testing complete (time limit)
Statistics:
Queries sent: 3055286
Queries completed: 3055286 (100.00%)
Queries lost: 0 (0.00%)
Response codes: NOERROR 3055286 (100.00%)
Average packet size: request 29, response 45
Run time (s): 60.010743
Queries per second: 50912.317483
Average Latency (s): 0.001872 (min 0.000050, max 0.077585)
Latency StdDev (s): 0.000859
**vic@waramik:/home/vic/scripts$ uptime**
14:27:58 up 2 days, 4:09, 1 user, load average: 0.73, 0.29, 0.25
如您所见,1m 的 LA 速率约为 50k q/s 是 2 个核心的 0.73。
还有在 Python3 上用 socketserver 模块制作的 echo DNS 服务器:
import socketserver
class UDPserver(socketserver.BaseRequestHandler):
def handle(self):
data, sock = self.request
sock.sendto(data, self.client_address)
if __name__ == "__main__":
host = "127.0.0.2"
port = 53
addr = (host, port)
with socketserver.ThreadingUDPServer(addr, UDPserver) as udp:
print(f'Start to listen on {addr}')
udp.serve_forever(0.1)
哪个会做这样的事情:
$ dig example.com @127.0.0.2
;; Warning: query response not set
; \<\<\>\> DiG 9.18.12-0ubuntu0.22.04.1-Ubuntu \<\<\>\> example.com @127.0.0.2
;; global options: +cmd
;; Got answer:
;; -\>\>HEADER\<\<- opcode: QUERY, status: NOERROR, id: 10796
;; flags: rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 12158dbef76fddc9 (echoed)
;; QUESTION SECTION:
;example.com. IN A
;; Query time: 0 msec
;; SERVER: 127.0.0.2#53(127.0.0.2) (UDP)
;; WHEN: Mon May 08 14:24:33 MSK 2023
;; MSG SIZE rcvd: 52
PyDNS服务器压力测试后统计:
DNS Performance Testing Tool
Version 2.11.2
[Status] Command line: dnsperf -s 127.0.0.2 -d example.com -l 60
[Status] Sending queries (to 127.0.0.2:53)
[Status] Started at: Mon May 8 14:29:35 2023
[Status] Stopping after 60.000000 seconds
[Status] Testing complete (time limit)
Statistics:
Queries sent: 478089
Queries completed: 478089 (100.00%)
Queries lost: 0 (0.00%)
Response codes: NOERROR 478089 (100.00%)
Average packet size: request 29, response 29
Run time (s): 60.024616
Queries per second: 7964.882274
Average Latency (s): 0.012543 (min 0.000420, max 0.082480)
Latency StdDev (s): 0.003576
$ uptime
14:30:49 up 2 days, 4:12, 1 user, load average: 1.22, 0.56, 0.34
如您所见,统计性能接近 ~8k q/s,1m 的 LA 是 2 个核心的 1.22。
你能告诉我我做错了什么吗?
在我尝试使用一组套接字和线程模块之前,最大 q/s 约为 5k。 我也读过很多类似的例子,但没有找到解决方案。
好吧,我找到了解决方案。 我已经在 asincio 数据报协议上替换了 socketserver,它现在可以工作了