正在加载...
2007-12
6

近来由于业务量急剧增长,业务种类越来越多,RPC混乱问题就凸现出来.
具体表现是:
a1,a2,a3,a4 为一组服务器,为用户提供A服务.
b1,b2,b3为一组服务器,为用户提供B服务.
c1,c2,c3为一组服务器,为用户提供C服务.
最初各服务器各自服务是不太相关的.随着业务拓展,用户提出新的需求,我们需要
在A服务中调用B组服务器的API接口.
….
最后我们发现这样一个现象:
用户请求a1 提供服务.a1发现他需要知道另一些数据,于是调用b2的rpc服务.但是b2
上这个数据又需要c3的RPC.结果c3又需要a2来提供一些数据….
我们的远程调用调来调去,最后把自己调晕了.

于是我开始考虑一种解决方案。
首先当然是:对远程调用加以控制和规范,避免不必要的远程调用。
接着我注意到,我们利用CURL来通过http通道进行远程调用其实是没必要的。我可以在做远程调用时,走FastCGI协议。

说干就干:
第一步:建立一个fastCGI:spawn-php

  1. #!/bin/bash
  2.  
  3. ## ABSOLUTE path to the spawn-fcgi binary
  4. SPAWNFCGI="/home/y/opt/lighttpd/bin/spawn-fcgi"
  5.  
  6. ## ABSOLUTE path to the PHP binary
  7. FCGIPROGRAM="/home/y/opt/php/bin/php-cgi"
  8.  
  9. ## TCP port to which to bind on localhost
  10. FCGIPORT="1026"
  11.  
  12. ## number of PHP children to spawn
  13. PHP_FCGI_CHILDREN=10
  14.  
  15. ## maximum number of requests a single PHP process can serve before it is restarted
  16. PHP_FCGI_MAX_REQUESTS=1000
  17.  
  18. ## IP addresses from which PHP should access server connections
  19. FCGI_WEB_SERVER_ADDRS="127.0.0.1,192.168.2.10"
  20.  
  21. # allowed environment variables, separated by spaces
  22. ALLOWED_ENV="ORACLE_HOME PATH USER"
  23.  
  24. ## if this script is run as root, switch to the following user
  25. USERID=y
  26. GROUPID=y
  27.  
  28. ################## no config below this line
  29.  
  30. if test x$PHP_FCGI_CHILDREN = x; then
  31. PHP_FCGI_CHILDREN=5
  32. fi
  33.  
  34. export PHP_FCGI_MAX_REQUESTS
  35. export FCGI_WEB_SERVER_ADDRS
  36.  
  37. ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS"
  38.  
  39. if test x$UID = x0; then
  40. EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN"
  41. else
  42. EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN"
  43. fi
  44.  
  45. # copy the allowed environment variables
  46. E=
  47.  
  48. for i in $ALLOWED_ENV; do
  49. E="$E $i=${!i}"
  50. done
  51.  
  52. # clean the environment and set up a new one
  53. env - $E $EX

2.接着我们建立这样的文件:http.txt

  1. for($i=0;$i<100;$i++)
  2. {
  3. echo rand();
  4. echo '....Scene of shooting at Nebraska shopping centre
  5. Eight killed in Nebraska shooting
  6. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  7. Scene of shooting at Nebraska shopping centre
  8. Eight killed in Nebraska shooting
  9. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  10. Scene of shooting at Nebraska shopping centre
  11. Eight killed in Nebraska shooting
  12. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  13. Scene of shooting at Nebraska shopping centre
  14. Eight killed in Nebraska shooting
  15. A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people.
  16. ';
  17. }
  18. print "done!";

这个做为是远程接口。
3.下面比较CURL和fastCGI两种访问remote API的方式:
A:走FastCGI:

  1. include "./mod_fcgi.php";
  2. $fcgi=new mod_fcgi();
  3. $args="127.0.0.1:1026";
  4. $filename="/home/y/www/qps/http.php";
  5. $fcgi->parser_open($args,$filename,$rq_err,$cgi_headers);
  6. print($fcgi->parsed_output);
  7. echo "\n=============\n";

B:走CURL通道:

  1. include "./curl.php";
  2. $curl=& new CURL();
  3. echo $curl->get("http://localhost/qps/http.php");
  4. echo "\n=============\n";

4我们比较FCGI方式和CURL方式的差异:
FCGI方式进行远程调用的QPS:

  1. Total transferred:      249306 bytes
  2. HTML transferred:       244410 bytes
  3. Requests per second:    275.77 [#/sec] (mean)
  4. Time per request:       3.626 [ms] (mean)
  5. Time per request:       3.626 [ms] (mean, across all concurrent requests)
  6. Transfer rate:          2233.76 [Kbytes/sec] received

HTTP通道进行远程调用的QPS:

  1. Total transferred:      2244515 bytes
  2. HTML transferred:       2240015 bytes
  3. Requests per second:    204.18 [#/sec] (mean)
  4. Time per request:       4.898 [ms] (mean)
  5. Time per request:       4.898 [ms] (mean, across all concurrent requests)
  6. Transfer rate:          14911.66 [Kbytes/sec] received

经过多次比较,确认用fastCGI通道时,效率比http方式要高。
但是….这个差别并不大,而且,使用lighttpd的spawn-cgi来充当fastcgi的守护进程,还不是特别稳定。
另外,经过我的测试,只有当远程调用的结果有较多的输出时,FastCGI协议与HTTP协议相比才有优势。在通过网络传输的数据不多的情况下(就是http.php几乎没有输出的情况下),用CURL来调远端调用,反而比FastCGI方式慢(显而易见,mod_fcgi是自行封装的用PHP的socket函数来进行网络操作的class,而Curl是一个编译了的php扩展).
因此,我忙活了半天,最后得出的结论是,目前还不能在公司大规模加以运用。
但是对于小型企业,创业型公司来说,这种效率对比还是很有用的,可以加以挖掘。

: http://www.162cm.com/archives/560.html

本文相关评论 - 才 2 条评论
fcicq
2008-02-18 20:30:33

注意到这个fastcgi 的实现是取自 nanoweb 的? 而且这个脚本有 yahoo的感觉.

2008-02-18 20:43:47

哈哈,/home/y/,一下就显露出是yahoo的了
fastcgi也确实是从nanoweb中取用的现成的