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

2021-07-23 12:21:26 浏览数 (1)

c-ares 是什么?

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

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

gethostbyname

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

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

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

dnsLookup

函数原型:

代码语言:javascript复制
SwooleCoroutineSystem::dnsLookup(string $domain, float $timeout = 5): string|false

CoroutineSystem::gethostbyname 不同,CoroutineSystem::dnsLookup 是基于 CoSocket UDP 客户端自行实现的 DNS 协程客户端,

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

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

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

代码语言:javascript复制
SwooleCoroutineSystem::dnsLookup(string $domain, float $timeout = 5, int $type = AF_INET): string|false

示例代码

  • IPv6
代码语言:javascript复制
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;

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

strace 日志

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

代码语言:javascript复制
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;

run(function () {
    $ip = System::gethostbyname("www.taobao.com", AF_INET, 0.5);
    echo $ip;
});
代码语言:javascript复制
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, "t2053006 273`271375377273376261a246VP304Y-4[20619@37023N1223>"..., 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, "f330113www5baidu3com11", 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, "f330201200133www5baidu3com11300"..., 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
代码语言:javascript复制
好文和朋友一起看~

0 人点赞