在4.4
之前的版本中,Swoole
一直不支持CURL
协程化,在代码中无法使用curl
。由于curl
使用了libcurl
库实现,无法直接hook
它的socket
,4.4
版本使用SwooleCoroutineHttpClient
模拟实现了curl
的API
,并在底层替换了curl_init
等函数的C Handler
。
提示
CURL Hook
的特性尚处于试验阶段,请勿在生产环境中直接使用- 暂不支持文件上传、
CURL Multi
- 仍然需要依赖
curl
,请务必安装curl
扩展
支持的特性列表
- GET/POST
- Header
- Cookie
- Https
经过验证
Guzzle CURL
完全可以使用
开启
使用Runtime::enableCoroutine
来开启CURL Hook
。
代码语言:javascript复制默认不开启
CURL Hook
SwooleRuntime::enableCoroutine(SWOOLE_HOOK_ALL);
SwooleRuntime::enableCoroutine(SWOOLE_HOOK_CURL);
使用
代码语言:javascript复制$n = 10;
while($n--) {
go(function () {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.xinhuanet.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
if ($output === FALSE) {
echo "CURL Error:" . curl_error($ch);
}
curl_close($ch);
echo strlen($output) . " bytesn";
});
}
要将上面两段代码合并到一个文件中执行
运行结果
代码语言:javascript复制htf@LAPTOP-0K15EFQI:~/swoole-src/examples$ time php curl.php
177173 bytes
177173 bytes
177173 bytes
177173 bytes
177173 bytes
177173 bytes
177173 bytes
177173 bytes
177173 bytes
177173 bytes
real 0m0.534s
user 0m0.031s
sys 0m0.297s
可以看到整个程序是并行的,进程没有任何阻塞。
strace 跟踪
使用strace
跟踪发现,所有系统调用均变成epoll
socket
的异步非阻塞调用了。
epoll_create(512) = 3
mmap(NULL, 258048, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc038a50000
mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc028910000
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 4
fcntl(4, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC)
fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0
setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
pipe([5, 6]) = 0
fcntl(5, F_GETFL) = 0 (flags O_RDONLY)
fcntl(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
fcntl(6, F_GETFL) = 0x1 (flags O_WRONLY)
fcntl(6, F_SETFL, O_WRONLY|O_NONBLOCK) = 0
epoll_ctl(3, EPOLL_CTL_ADD, 5, {EPOLLIN, {u32=5, u64=34359738373}}) = 0
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fc028100000
mprotect(0x7fc028101000, 8388608, PROT_READ|PROT_WRITE) = 0
clone(child_stack=0x7fc0288ffb70, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fc0289009d0, tls=0x7fc028900700, child_tidptr=0x7fc0289009d0) = 55
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fc0237f0000
mprotect(0x7fc0237f1000, 8388608, PROT_READ|PROT_WRITE) = 0
clone(child_stack=0x7fc023fefb70, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fc023ff09d0, tls=0x7fc023ff0700, child_tidptr=0x7fc023ff09d0) = 56
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fc022fe0000
mprotect(0x7fc022fe1000, 8388608, PROT_READ|PROT_WRITE) = 0
clone(child_stack=0x7fc0237dfb70, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fc0237e09d0, tls=0x7fc0237e0700, child_tidptr=0x7fc0237e09d0) = 57
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fc0227d0000
mprotect(0x7fc0227d1000, 8388608, PROT_READ|PROT_WRI