首页
下载
文档
问答社区
视频
捐赠
源代码
AI 助理
赞助商
CRMEB
Apipost
腾讯云
微擎
禅道
51Talk
商业产品
Swoole AI 智能文档翻译器
Swoole-Compiler PHP 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
Swoole v4.7 版本预览之支持 c-ares
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 函数原型: ```php 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 ```php Swoole\Coroutine\System::dnsLookup(string $domain, float $timeout = 5, int $type = AF_INET): string|false ``` ### 示例代码 - IPv6 ```php 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 日志 ```php use Swoole\Coroutine\System; use function Swoole\Coroutine\run; run(function () { $ip = System::gethostbyname("www.taobao.com", AF_INET, 0.5); echo $ip; }); ``` ```text 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 ``` ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/swoole/wechat.png)
发布于3年前 · 36 次浏览 · 来自
分享
鲁飞
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 函数原型: ```php 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 ```php Swoole\Coroutine\System::dnsLookup(string $domain, float $timeout = 5, int $type = AF_INET): string|false ``` ### 示例代码 - IPv6 ```php 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 日志 ```php use Swoole\Coroutine\System; use function Swoole\Coroutine\run; run(function () { $ip = System::gethostbyname("www.taobao.com", AF_INET, 0.5); echo $ip; }); ``` ```text 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 ``` ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/swoole/wechat.png)
赞
2
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
还没有评论!
微信公众号
热门内容
作者其它话题
- thinkphp5.1在使用think-swoole的时候报错unsupported option [host]
- WSL 下服务器响应数据过大无法接收
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。