4

Swoole v4.7 版本预览之支持 c-ares

 2 years ago
source link: https://segmentfault.com/a/1190000040267883
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

c-ares 是什么?

c-ares 是一个异步 DNS 解析库。 它适用于需要在不阻塞的情况下执行 DNS 查询或需要并行执行多个 DNS 查询的应用程序。

默认不开启,如需开启,需要在编译 Swoole 时增加 --enable-cares 参数

gethostbyname

在之前的版本中 Coroutine\System::gethostbyname 是基于同步的线程池模拟实现,底层自动进行协程调度,

依赖操作系统和 AIO 线程池,导致并发能力较弱,而启用 c-ares 之后会变成纯异步 IO 的。

启用 c-ares 之后,所有的网络客户端在解析域名时都会使用 c-ares ,包括 Redis、MySQL、HttpClient ,以及 PHP 的 Hook stream、sockets 之类

dnsLookup

函数原型:

Swoole\Coroutine\System::dnsLookup(string $domain, float $timeout = 5): string|false

Coroutine\System::gethostbyname 不同,Coroutine\System::dnsLookup 是基于 Co\Socket UDP 客户端自行实现的 DNS 协程客户端,

底层是异步 IO,而不是使用 libc 提供的 gethostbyname 函数。在开启 c-ares 之后也会被替换成 c-ares 实现。

此函数在 Swoole 版本 >= v4.4.3 时可用,底层会读取 /etc/resolve.conf 获取 DNS 服务器地址,之前版本中仅支持 AF_INET(IPv4) 域名解析,此版本中对于 IPv6 也增加了支持

对于 Coroutine\System::dnsLookup 增加了第三个参数,用于选择 IPv4 (AF_INET) 还是 IPv6 (AF_INET6),默认为 IPv4

Swoole\Coroutine\System::dnsLookup(string $domain, float $timeout = 5, int $type = AF_INET): string|false
use Swoole\Coroutine\System;
use function Swoole\Coroutine\run;

run(function () {
    var_dump(System::dnsLookup('www.taobao.com', 3, AF_INET6));
});

strace 日志

启用 c-ares 之后会变成纯异步 IO,以下为 strace 日志

use Swoole\Coroutine\System;
use function Swoole\Coroutine\run;

run(function () {
    $ip = System::gethostbyname("www.taobao.com", AF_INET, 0.5);
    echo $ip;
});
epoll_create(512)                       = 3
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=658303392}) = 0
mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4173b8c000
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=658417744}) = 0
open("/etc/resolv.conf", O_RDONLY)      = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=89, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41832b9000
read(4, "; generated by /usr/sbin/dhclien"..., 4096) = 89
read(4, "", 4096)                       = 0
close(4)                                = 0
munmap(0x7f41832b9000, 4096)            = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41832b9000
read(4, "t\205\3006 \273`\271\375\377\273\376\261a\246VP\304Y-\4[\20619@\370\23N\1\223>"..., 4096) = 4096
close(4)                                = 0
munmap(0x7f41832b9000, 4096)            = 0
open("/etc/hosts", O_RDONLY)            = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=242, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41832b9000
read(4, "127.0.0.1 VM-32-17-centos VM-32-"..., 4096) = 242
read(4, "", 4096)                       = 0
close(4)                                = 0
munmap(0x7f41832b9000, 4096)            = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=659074426}) = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
fcntl(4, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK)    = 0
fcntl(4, F_SETFD, FD_CLOEXEC)           = 0
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("183.60.82.98")}, 16) = 0
epoll_ctl(3, EPOLL_CTL_ADD, 4, {EPOLLIN, {u32=37374768, u64=37374768}}) = 0
sendto(4, "f\330\1\0\0\1\0\0\0\0\0\0\3www\5baidu\3com\0\0\1\0\1", 31, MSG_NOSIGNAL, NULL, 0) = 31
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=659365294}) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=659391969}) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=659414437}) = 0
epoll_wait(3, [{EPOLLIN, {u32=37374768, u64=37374768}}], 4096, 500) = 1
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=660754983}) = 0
recvfrom(4, "f\330\201\200\0\1\0\3\0\0\0\0\3www\5baidu\3com\0\0\1\0\1\300"..., 4097, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("183.60.82.98")}, [16]) = 90
epoll_ctl(3, EPOLL_CTL_DEL, 4, NULL)    = 0
close(4)                                = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=2244208, tv_nsec=660917518}) = 0
write(1, "110.242.68.4", 12110.242.68.4)            = 12



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK