问题是这样的:a -> b -> ca是我们的合作方,他们负责通过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。
希望大家给点意见,指点下,谢谢!

解决方案 »

  1.   

    开多进程,给每个c开一个单独的php进程,
    影响,就同时开2个,一直用,一个监视一些其它进程,一个做文件操作,都死循环样运行,
    没发现死循环 本身对负载有影响。当调度文件操作的时候,肯定会影响负载。cpu/硬盘读写够强,应该没问题吧,或者减少到5个,每个对应2个c
      

  2.   

    先谢谢楼上两位,我明天试试看多开几个php进程,开始担心的情况就是进程开多了会对系统负载有影响。死循环本身确实不应该对系统负载产生影响,主要是看里面做的操作是什么。我的程序跑的业务逻辑就是查库,推数据。这和服务器访问频繁效果应该是一样的。之前我做同步转发系统可以受得了,现在这样也应该受得了。
      

  3.   

    频繁查库不知到是否有瓶颈,如果是a来的直接数据,没有作处理,不如除了存库,另外放到内存,产生队列,让php进程去内存队列拿
      

  4.   

    用SOAP解决可行性高
    原理是,soap监听接收数据
    然后soap后台启动多进程
      

  5.   

    对了,不如不等待返回
    x.php一直运行,定时从内存队列获得数据,并给内存中数据作个标记,然后处理后推送c端,但不等待返回
    x.php获取数据时,在一段时间内只获得无标记的数据
    c端返回要求,发到另外一个,m.php,接收返回,并和内存队列对比,删除符合的
      

  6.   

    看来提到SOAP的朋友不少,我对SOAP不是很了解,一会儿去查点资料,但如果使用SOAP需要c的配合或需要c更改接口协议,那就必须放弃了,事实上c不能按我的需求改动他们的接口。我们这个行业有一个无形的标准,就是通过访问对方接口地址直接传几个参数过去。基本上大家都必须遵守这个标准才能合作。另外有位朋友说在a给我推数据过来时应该直接放在内存里,避免推送的时候再去查库。这样的话,如果推送不能达到一定的速度的话,数据会全部堵在内存中,所以我觉得还是先放在数据库,一次取出10条数据,这样更保险一些。如果推送速度能保证很快很稳定的话,直接放内存中无疑是最好的。谢谢各位的建议。我准备尝试下开多个进程,这样如果以后再增加c的话,我还要再开进程,这是一个弊端。应该没有十全十美的办法。
      

  7.   

    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可能更合适 可需要上游和下游一起支持 
      

  8.   

    我的建议:1、把你当前的处理B->C的php cli程序放到apache下,即http://www.x.com/b2c.php2、开一个独立的php CLI进程php.exe db_read.php,去循环读数据库并将读取的字段提交给b2c.php
       你可以一次提交10个都没问题,因为apache支持多线程:)
      

  9.   

    我不大了解这个,不过前段时间看到一个“服务器推”技术。或许有用。另外,我说说sql查询这块儿,假设你的sql数据库没有太多优化的话,每次查询10条,这样速度会有瓶颈,当然,或许数据的要求对于这个查询完全能够满足。以你的推送速度来推理,建议一次性读取数据比如100条,暂存为一个文件,文件操作毕竟比数据库操作要快。推送出去10条删除10条,当只剩下10条的时候,再读取100条。这样能减少数据库的读取次数。想要优化,就要优化到牙齿。其它的方面恕我没有想到什么方式,材疏学浅,帮不上忙了。
      

  10.   

    开多进程,给每个c开一个单独的php进程, 
    影响,就同时开2个,一直用,一个监视一些其它进程,一个做文件操作,都死循环样运行,
      

  11.   

    b->c
    可否考虑由推送改为c向b请求获取或者请求同步更新数据.以减少b的压力.
    把你当前的处理B->C的php cli程序放到apache下,即http://www.x.com/b2c.php 
    ===================================================================
    交给apache去处理可能是一个方法.apache是多线程的.如果以上都不可行,可以考虑用c++来完成php的工作.
      

  12.   

    ps:mysql可以实现主从服务器同步更新, 可以考虑设置单独的数据库服务器,为每个合作方开一端口,让mysql完成数据推送的过程.
      

  13.   


    这样不行的,我不能让c按我们的要求做这么多更改。现在看来,要么开多进程,要么调用linux的curl或apache来实现多线程。要么就开多进程,只有这两种方法最合适了。谢谢大家的意见,结贴了。
      

  14.   

    去年的帖子了,晕。实际纯http协议就可以实现这个需求的。
      

  15.   

    1、php、curl、apache多进程
    2、soap
    3、mysql主从库自动更新
    晕,好多木懂:(
      

  16.   

    把php换掉吧,直接使用C实现