200分求优化建议
问题是这样的:
a -> b -> c
a是我们的合作方,他们负责通过http协议给我们同步数据。
b是我们,负责接收a推过来的数据,做业务逻辑处理后,再把整理好的数据推给我们的合作方c(有很多c)。
我的程序整体架构是这样的:
1 有一个入口文件,其实就是个php文件,负责接收a的数据,存入数据库。
2 我用nohup命令调用php cli模式开了一个php进程运行一个php文件在系统后台处理下面的事情:从数据库中一次取出10条数据,循环fetch出每一条,然后根据业务逻辑,根据每条数据的不同,转发给不同的c(其实就是要访问不同的url)。
a给我同步数据的时候,一秒可能会来10几条,他们是多线程发包。而我这边经过入库,一次取出10条数据,循环推送到不同的url地址,在收到他们接口给我响应的'ok'后,做标记,然后推送下一条数据,如果在我设置的超时时间5秒后还没有收到对方的'ok',则重发,超时时间依然是5秒,共重发2次。等于一条数据最多推送3次,3次都推不过去的话就不管了。并且,我在每次推送数据间设置sleep了1秒。
遇到的问题:
正常情况下,推一条数据应该大概在2秒以内,但如果某个c,他的接口受网络原因或程序的问题,我3次推送都没推过去(也就是说他的接口响应速度大于5秒或根本没响应),它会令我的数据队列最多懈怠18秒的时间。这会令推送速度大大降低!我今天看了下,我的数据队列比正常速度大概慢了一个小时。请问有什么好的方法解决这个问题吗?
php本身不支持多线程,我无法设置不同的线程去给不同的c推送数据。所以一个c的接口响应慢,会影响所有的c,影响整个数据队列。
不知有没有朋友做过这方面的东西,指教点经验。除了要求c提高接口响应速度,和保证网络畅通外。有没有我自己这边解决问题的方法?我的一些合作方它们用的都是java,可以建立线程池多线程发包,但php这点比较无奈。
其实在以前,我采用的方式是同步转发,也就是接到a的数据后,立刻处理业务逻辑,然后立刻把数据同步转发给c,不入队列。这样是没有上述问题的,但这样会产生很多其它问题,所以我现在才改成这种队列的方式。
我想了两个解决方案不知是否可行:
1 php本身不支持多线程,但linux下的curl,wget,或apache带的ab。它们支持多线程的,我是否可以用php去调用它们来实现多线程推数据?给每个不同的c分配一个线程,这样,一个c堵塞,不会影响其它的c。
2 不支持多线程,我用多进程,我给每个不同的c开一个单独的php进程,这样也可以避免c之间互相影响。但我不清楚开这么多进程无限死循环着运行会对操作系统有多大影响。目前我们这个业务大概有10个c。
希望大家给点意见,指点下,谢谢!
------解决方案--------------------
开多进程,给每个c开一个单独的php进程,
影响,就同时开2个,一直用,一个监视一些其它进程,一个做文件操作,都死循环样运行,
没发现死循环 本身对负载有影响。当调度文件操作的时候,肯定会影响负载。cpu/硬盘读写够强,应该没问题吧,或者减少到5个,每个对应2个c
------解决方案--------------------
频繁查库不知到是否有瓶颈,如果是a来的直接数据,没有作处理,不如除了存库,另外放到内存,产生队列,让php进程去内存队列拿
------解决方案--------------------用SOAP解决
------解决方案--------------------用SOAP解决可行性高
原理是,soap监听接收数据
然后soap后台启动多进程
------解决方案--------------------对了,不如不等待返回
x.php一直运行,定时从内存队列获得数据,并给内存中数据作个标记,然后处理后推送c端,但不等待返回
x.php获取数据时,在一段时间内只获得无标记的数据
c端返回要求,发到另外一个,m.php,接收返回,并和内存队列对比,删除符合的
------解决方案--------------------
PHP CLI模式在非WIN下可以多线程 但很弱
HTTP是无状态协议 完全可以多进程来做 但其中有个严重的问题
A-> 10+/S
->C 10/5S
也就是说 C的发送速度要低于A的接收速度 造成前一个C还未退出就再启动一个C 最后堆积了N个进程系统崩溃 或者每个C一个进程 造成很大的数据延迟
可以给每个C单独一个进程 但每次不限于10条 应该是积压了几条就发几条 这样能有效的控制进程数量和延迟 最大延迟基本上就是运行时间+传输时间
再或者每个C单独进程+多线程 弄个列队每个线程10条 积压超过10条就启动新的线程 基本上每个进程启动20个线程就足够保证同步了
数据提供俺的做法是被动访问 毕竟用户不多 几K节点的XML生成发送 负载都不算高 而且可以利用缓存
呵呵 SOAP可能更合适 可需要上游和下游一起支持
------解决方案--------------------
我的建议:
1、把你当前的处理B->C的php cli程序放到apache下,即http://www.x.com/b2c.php
2、开一个独立的php CLI进程php.exe db_read.php,去循环读数据库并将读取的字段提交给b2c.php
你可以一次提交10个都没问题,因为apache支持多线程:)
------解决方案--------------------我不大了解这个,不过前段时间看到一个“服务器推”技术。或许有用。
另外,我说说sql查询这块儿,假设你的sql数据库没有太多优化的话,每次查询10条,这样速度会有瓶颈,当然,或许数据的要求对于这个查询完全能够满足。
以你的推送速度来推理,建议一次性读取数据比如100条,暂存为一个文件,文件操作毕竟比数据库操作要快。
推送出去10条删除10条,当只剩下10条的时候,再读取100条。这样能减少数据库的读取次数。
想要优化,就要优化到牙齿。其它的方面恕我没有想到什么方式,材疏学浅,帮不上忙了。
------解决方案--------------------开多进程,给每个c开一个单独的php进程,
影响,就同时开2个,一直用,一个监视一些其它进程,一个做文件操作,都死循环样运行,
------解决方案--------------------