Heim >Backend-Entwicklung >PHP-Tutorial >PHP 每小时百万级的curl请求服务器 丢失数据
服务器A会通过 curl
将数据转发到服务器B 上,服务器A 每小时转发量在百万级。curl
请求的是服务器B上的 一个 0字节的文件 , 只要把请求记录在服务器B的nginx日志里就可以了。
现在通过两边的数据比对, 发现数据一天会丢几千条,一小时会丢一两百条。
服务器A 用curl_errno()
,甚至加了curl_getinfo()
判断返回的是否是200 都没有记录到curl报错
这部分丢失的curl请求, 想请教大家有什么好的分析思路跟经验可以借鉴的。
补充: 服务器间用的内网dns解析,排除了 dns解析超时的故障
服务器A会通过 curl
将数据转发到服务器B 上,服务器A 每小时转发量在百万级。curl
请求的是服务器B上的 一个 0字节的文件 , 只要把请求记录在服务器B的nginx日志里就可以了。
现在通过两边的数据比对, 发现数据一天会丢几千条,一小时会丢一两百条。
服务器A 用curl_errno()
,甚至加了curl_getinfo()
判断返回的是否是200 都没有记录到curl报错
这部分丢失的curl请求, 想请教大家有什么好的分析思路跟经验可以借鉴的。
补充: 服务器间用的内网dns解析,排除了 dns解析超时的故障
合并请求是个好的思路,并发处理过多的话,不仅是B服务器,A服务器也不见得能按照期望去处理。
或者也可以使用队列来处理,每秒并发可以控制一个量级下去请求B服务器。
首先你没贴代码没办法帮你“猜”答案,以为简单的描述文字就能代替代码逻辑万万不可,我们写代码的人扣的是1和0的区别,靠描述没办法猜的。
对于任何对精确度有要求的请求方式(例如你这个简单的计数),最好都不要直接用Curl,网络的不确定性是一点,如果你要发送数据给另一台主机,至少发送方要确认对方收到消息是不是?从设计程序的角度来讲,你放个空文件,与向数据库插入信息却不确认成功与否有何区别?
我不懂看PHP源码,以有限的知识猜测一下,百万级的请求数大约280qps,你只交代了A服务器是转发服务器,但没有说明A服务器是多线程还是单线程,是apache模块还是cgi方式执行,并发多少,我只能告诉你,在任何并发数量下,PHP error出现的的概率都是有的,随着并发数的提高,程序无Bug的情况下3xx, 4xx, 5xx错误也都会出现,这是web服务器负载过大的正常响应,我的直觉是你没对A机进行精确统计,错误的认为服务器A所有的请求都成功执行了。这部分丢失的请求不是CURL错误,是PHP错误,所以你用CURL函数处理不到。
如果非要沿用现在的方法,建议B机接口返回成功码和失败码,A机凭借返回的code去logging。
如果我说错了,你仍然要从请求数和http请求上着手改善(不知道为什么,直觉就是不靠谱,哪怕你把B机改成纯MySQL的内存表都会比这种方式靠谱)。另外还有两点想法,1是开启CURL的多线程(不建议用CURL了),或者干脆给PHP加个多线程扩展,将PHP以守护进程运行,消除web服务器的并发瓶颈! 2是把数据分块吧,这非常重要,这种类似日志的东西,实时性没那么高,在A机积攒一万条发一次不行么?我曾抓Twitter数据,从华盛顿发往北京就是这样打包发。
以前做过实验,一次并发50个左右的请求,比较稳定。多了就开始丢失请求了。不知道为什么。
何不考虑先使用A服务器将B服务器需要的日志形式写入A服务器的磁盘某个角落,然后每分钟curl
一次B服务器,让B服务器抓A服务器这一分钟的数据记录,然后写入B服务器nginx
日志集?
这样每小时请求60次,甚至两边通信可做失败重传,大大减轻高并发下的网络丢包现象。具体通信时间间隔可根据每次通信传输的数据量来定,比如控制一次curl
只传输1MB的内容,以保证通信正常完成。
仅提供一个思路,写这种脚本也是要花时间的,酌情考虑。
如果单纯只是记录请求的日志,建议使用UDP传输吧
合每秒才 300 左右的请求。
nginx 每秒处理 1W 请求应该不成问题。
所以,问题肯定出在 curl 上。curl 虽然负有盛名,但真的不怎么好使。
建议还是自己拼 HTTP 请求吧。
为什么要curl去?如果仅仅是为了留下日志的话。那在a的nginx上开个location。proxy到b。页面script src到a的这个location
敢问题主,你们服务器之间这样打点之后的日志分析入库是如何实现的?另,我觉得丢失数据是一定会发生的,几百万条一条也不丢失几乎都是科研而不是工程了。我同题主一样需要这样的打点并写入mysql。题主能跟我讲下现有你们的架构吗?