摘要:在之前的版本中,一直不支持協(xié)程化,在代碼中無法使用。由于使用了庫(kù)實(shí)現(xiàn),無法直接它的,版本使用模擬實(shí)現(xiàn)了的,并在底層替換了等函數(shù)的。跟蹤使用跟蹤發(fā)現(xiàn),所有系統(tǒng)調(diào)用均變成的異步非阻塞調(diào)用了。
在4.4之前的版本中,Swoole一直不支持CURL協(xié)程化,在代碼中無法使用curl。由于curl使用了libcurl庫(kù)實(shí)現(xiàn),無法直接hook它的socket,4.4版本使用SwooleCoroutineHttpClient模擬實(shí)現(xiàn)了curl的API,并在底層替換了curl_init等函數(shù)的C Handler。
提示CURL Hook的特性尚處于試驗(yàn)階段,請(qǐng)勿在生產(chǎn)環(huán)境中直接使用
暫不支持文件上傳、CURL Multi
仍然需要依賴curl,請(qǐng)務(wù)必安裝curl擴(kuò)展
支持的特性列表GET/POST
Header
Cookie
Https
經(jīng)過驗(yàn)證Guzzle CURL完全可以使用開啟
使用Runtime::enableCoroutine來開啟CURL Hook。
默認(rèn)不開啟CURL Hook
SwooleRuntime::enableCoroutine(SWOOLE_HOOK_ALL); SwooleRuntime::enableCoroutine(SWOOLE_HOOK_CURL);使用
$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) . " bytes "; }); }
要將上面兩段代碼合并到一個(gè)文件中執(zhí)行運(yùn)行結(jié)果
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
可以看到整個(gè)程序是并行的,進(jìn)程沒有任何阻塞。
strace 跟蹤使用strace跟蹤發(fā)現(xiàn),所有系統(tǒng)調(diào)用均變成epoll+socket的異步非阻塞調(diào)用了。
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_WRITE) = 0 clone(child_stack=0x7fc022fcfb70, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fc022fd09d0, tls=0x7fc022fd0700, child_tidptr=0x7fc022fd09d0) = 58 futex(0x7fffd9e01ce0, FUTEX_WAKE_PRIVATE, 1) = 1 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=513190000}) = 0 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=513408000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc0225c0000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 8 fcntl(8, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(8, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(8, SOL_TCP, TCP_NODELAY, [1], 4) = 0 futex(0x7fffd9e01ce0, FUTEX_WAKE_PRIVATE, 1) = 1 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=514359000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc0223b0000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 10 fcntl(10, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(10, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(10, SOL_TCP, TCP_NODELAY, [1], 4) = 0 futex(0x7fffd9e01ce0, FUTEX_WAKE_PRIVATE, 1) = 1 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=515961000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc0221a0000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 9 fcntl(9, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(9, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(9, SOL_TCP, TCP_NODELAY, [1], 4) = 0 futex(0x7fffd9e01ce4, FUTEX_WAKE_PRIVATE, 1) = 1 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=517822000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc021f90000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 7 fcntl(7, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(7, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(7, SOL_TCP, TCP_NODELAY, [1], 4) = 0 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=520138000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc021b60000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 11 fcntl(11, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(11, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(11, SOL_TCP, TCP_NODELAY, [1], 4) = 0 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=521400000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc021950000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 12 fcntl(12, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(12, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(12, SOL_TCP, TCP_NODELAY, [1], 4) = 0 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=523446000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc021530000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 17 fcntl(17, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(17, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(17, SOL_TCP, TCP_NODELAY, [1], 4) = 0 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=524631000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc021320000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 18 fcntl(18, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(18, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(18, SOL_TCP, TCP_NODELAY, [1], 4) = 0 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=525903000}) = 0 mmap(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc021110000 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 19 fcntl(19, F_GETFL) = 0x80002 (flags O_RDWR|O_CLOEXEC) fcntl(19, F_SETFL, O_RDWR|O_NONBLOCK|O_CLOEXEC) = 0 setsockopt(19, SOL_TCP, TCP_NODELAY, [1], 4) = 0 clock_gettime(CLOCK_MONOTONIC, {tv_sec=232, tv_nsec=527295000}) = 0 epoll_wait(3, [{EPOLLIN, {u32=5, u64=34359738373}}], 4096, 1000) = 1 read(5, "0T340331377177