V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaobaiyihao
V2EX  ›  程序员

PHP 并发请求有没有更好的方法

  •  
  •   xiaobaiyihao · 2021-09-14 14:46:29 +08:00 · 2675 次点击
    这是一个创建于 926 天前的主题,其中的信息可能已经有所发展或是发生改变。
    PHP 请求多个 URL,除了用 curl_multi 函数,有没有效率更高的方法,感觉 curl 是 fork 进程来请求,效率感觉不是很高
    29 条回复    2021-09-15 20:52:39 +08:00
    zjsxwc
        1
    zjsxwc  
       2021-09-14 15:46:35 +08:00
    curl_multi 是基于 io 的 poll-select 的吧,没开多进程
    https://github.com/curl/curl/blob/1b70748e862eaa4d2ae4b8e1d34bc3b47540af22/lib/multi.c#L2543
    xiaobaiyihao
        2
    xiaobaiyihao  
    OP
       2021-09-14 16:33:39 +08:00
    @zjsxwc 有没有更好的方法,现在性能卡在这里
    Gunn27
        3
    Gunn27  
       2021-09-14 16:56:38 +08:00
    你是要做异步请求吗? swoole 了解一下
    JaguarJack
        4
    JaguarJack  
       2021-09-14 17:00:51 +08:00
    `composer require spatie/async` 可以了解下
    zjsxwc
        5
    zjsxwc  
       2021-09-14 17:11:56 +08:00
    @xiaobaiyihao epoll 事件是操作系统级别的性能了,还慢,那只有加带宽了
    fkdtz
        6
    fkdtz  
       2021-09-14 17:52:13 +08:00
    那必须上协程啊,PHP 可以上 swoole 或者直接用 swoft
    xiaobaiyihao
        7
    xiaobaiyihao  
    OP
       2021-09-14 18:03:14 +08:00
    @JaguarJack 今天了解下
    @zjsxwc 上不了 swoole,老项目又大不敢动扩展这些
    zjsxwc
        8
    zjsxwc  
       2021-09-14 19:26:05 +08:00 via Android
    我错了,


    php 的 curl multi 居然不是基于 epoll 的

    虽然 libcurl 库对与 io 复用库是不可知的,可以让开发者在 c 代码里对 socket 使用自己实现的 io 复用库,但 libcurl 库也自带提供了基于 poll 与 select 的两种方式,这个方法名就有两个别名 curl_multi_wait 与 curl_multi_poll,这个具体使用 poll 还是 epoll 哪个得看 curl 的编译参数,当然性能都不能和 epoll 方式相提并论,

    悲剧的是在 php 的 curl 拓展中 php 就使用了这个 curl_multi_wait 方法,而没有使用 epoll 方式相关的代码,所以 php 的 curl multi 比 epoll 慢也是正常,当然 poll 与 select 再拉垮仍旧比顺序执行快。

    参考:
    php curl 拓展提供的 php 方法 curl_multi_select 就是直接调用 libcurl 的 curl_multi_wait 函数: https://github.com/php/php-src/blob/master/ext/curl/multi.c#L185

    libcurl 里默认提供的 curl_multi_wait 函数实现依赖的 curl_poll 函数代码中只用 poll 或者 select 而没有 epoll:
    https://github.com/curl/curl/blob/52fab72397687467650093c86e5479cb1d759042/lib/select.c#L329
    rekulas
        9
    rekulas  
       2021-09-14 21:18:29 +08:00
    原生 php 不好搞,考虑加个微服务 api 实现吧,也就半小时就撸出来了
    honkki
        10
    honkki  
       2021-09-14 21:27:17 +08:00
    单独新写一个服务并发请求返回结果呢
    Actrace
        11
    Actrace  
       2021-09-14 21:33:21 +08:00
    楼主要说一下运行环境,是 CLI 还是 CGI 。
    heybuddy
        12
    heybuddy  
       2021-09-14 21:37:04 +08:00 via iPad
    guzzle 可以做并发请求的,好像是用协程实现的
    sagaxu
        13
    sagaxu  
       2021-09-14 21:39:50 +08:00
    curl_multi 是你目前最靠谱的选项,拿 Go 提炼重写服务你就多了个服务治理,引入 Swoole 解决了 1 个简单问题带来了 10 个困难问题更不靠谱
    fiypig
        14
    fiypig  
       2021-09-14 21:45:10 +08:00 via iPhone
    试试 go ?
    zjsxwc
        15
    zjsxwc  
       2021-09-14 22:09:33 +08:00 via Android
    写错:
    “这个具体使用 poll 还是 epoll 哪个得看 curl 的编译参数”

    需要改成

    “但 libcurl 库也默认自带提供了一个基于 poll 或 select 的两种实现的方式,这个方法有两个功能一样的别名 curl_multi_wait 与 curl_multi_poll,起具体实现使用 poll 还是 select 哪个得看 curl 的编译参数”
    gBurnX
        16
    gBurnX  
       2021-09-14 23:26:12 +08:00
    你想拿 PHP 做高性能,出发点就是错的。哪怕是用 java 撸个微服务都比 PHP 好。
    dusu
        17
    dusu  
       2021-09-15 08:54:47 +08:00 via iPhone   ❤️ 2
    cli 还是 fpm ?
    效率低是几十万还是几千万页面需要在多久时间内请求完?
    资源消耗配置有什么要求?
    没指标没实践光靠感觉去评价
    只能引来一堆语言党 解决不了问题
    NjcyNzMzNDQ3
        18
    NjcyNzMzNDQ3  
       2021-09-15 09:09:20 +08:00
    稳定,不安扩展就 curl_muiti,我用 cli 做好资源回收,服务器 4cpu/4g 内存的机子每秒 100 请求都不耗费资源

    推荐这个库 composer require chuyskywalker/rolling-curl

    设置好地址、并发数,等回调就好了

    其他的 phper 楼上都说了,借用#17 的话

    -----
    没指标没实践光靠感觉去评价
    只能引来一堆语言党 解决不了问题
    star7th
        19
    star7th  
       2021-09-15 09:35:33 +08:00
    感觉你需要异步 http 请求。试着用这个 https://github.com/star7th/htq
    xiaobaiyihao
        20
    xiaobaiyihao  
    OP
       2021-09-15 09:53:09 +08:00
    @JaguarJack 这个 fock 进程,性能更加扛不住
    @Actrace php-fpm,这个可以换的倒是没大问题,就是不能换语言
    @fiypig 不能换语言
    @dusu fpm,性能每次请求必须在 300 ~ 400ms 内答应,百万吧,现在的情况就是卡在这个 curl_multi 请求上,本身这个接口也是高并发接口,接口内部要去并发请求其他接口
    liuyibao
        21
    liuyibao  
       2021-09-15 10:00:38 +08:00
    symfony/http-client

    Responses are always asynchronous, so that the call to the method returns immediately instead of waiting to receive the response:

    https://symfony.com/doc/current/http_client.html

    用这个没错的,解析 Response 的时候才会阻塞,很好用的。
    liuyibao
        22
    liuyibao  
       2021-09-15 10:09:07 +08:00
    symfony/http-client 搜了下源码,好像是用 yield 实现的,性能应该是可以的,只有 php7 以上能用。php8 增加的 fiber 会更强悍。
    zjsxwc
        23
    zjsxwc  
       2021-09-15 12:55:51 +08:00
    @xiaobaiyihao

    > "@dusu fpm,性能每次请求必须在 300 ~ 400ms 内答应,百万吧,现在的情况就是卡在这个 curl_multi 请求上,> 本身这个接口也是高并发接口,接口内部要去并发请求其他接口"

    300 ~ 400ms 内 百万请求,用什么 php 啊, 你带宽都要 2.5Gbps 了
    zjsxwc
        24
    zjsxwc  
       2021-09-15 12:56:27 +08:00
    @xiaobaiyihao

    > "@dusu fpm,性能每次请求必须在 300 ~ 400ms 内答应,百万吧,现在的情况就是卡在这个 curl_multi 请求上,> 本身这个接口也是高并发接口,接口内部要去并发请求其他接口"

    300 ~ 400ms 内 百万请求,用什么 php 啊, 你带宽都要 6Gbps 了
    xiaobaiyihao
        25
    xiaobaiyihao  
    OP
       2021-09-15 13:46:55 +08:00
    @zjsxwc 现在就是怼机器来着,想办法优化
    xiaobaiyihao
        26
    xiaobaiyihao  
    OP
       2021-09-15 13:48:03 +08:00
    @liuyibao 这个好像不支持 protobuf
    xiaobaiyihao
        27
    xiaobaiyihao  
    OP
       2021-09-15 13:49:10 +08:00
    @zjsxwc 而且这是要求,现在就是达不到这种情况
    Actrace
        28
    Actrace  
       2021-09-15 14:35:01 +08:00
    @xiaobaiyihao 更换到 CLI 下会有更多选择。PHP 内置了不少多线程,事件库,甚至可以用协程。可以单独写成一个服务,驻后台运行。
    changz
        29
    changz  
       2021-09-15 20:52:39 +08:00
    @zjsxwc poll/select 在这种场景下性能不会比 epoll 低。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3002 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 14:56 · PVG 22:56 · LAX 07:56 · JFK 10:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.