近来由于业务量急剧增长,业务种类越来越多,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 #!/bin/bash ## ABSOLUTE path to the spawn-fcgi binary SPAWNFCGI=”/home/y/opt/lighttpd/bin/spawn-fcgi” ## ABSOLUTE path to the PHP binary FCGIPROGRAM=”/home/y/opt/php/bin/php-cgi” ## TCP port to which to bind on localhost FCGIPORT=”1026” ## number of PHP children to spawn PHP_FCGI_CHILDREN=10 ## maximum number of requests a single PHP process can serve before it is restarted PHP_FCGI_MAX_REQUESTS=1000 ## IP addresses from which PHP should access server connections FCGI_WEB_SERVER_ADDRS=”127.0.0.1,192.168.2.10” # allowed environment variables, separated by spaces ALLOWED_ENV=”ORACLE_HOME PATH USER” ## if this script is run as root, switch to the following user USERID=y GROUPID=y ################## no config below this line if test x$PHP_FCGI_CHILDREN = x; then PHP_FCGI_CHILDREN=5 fi export PHP_FCGI_MAX_REQUESTS export FCGI_WEB_SERVER_ADDRS ALLOWED_ENV=”$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS” if test x$UID = x0; then EX=”$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN” else EX=”$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN” fi # copy the allowed environment variables E= for i in $ALLOWED_ENV; do E=”$E $i=${!i}” done # clean the environment and set up a new one env - $E $EX 2.接着我们建立这样的文件:http.txt for($i=0;$i<100;$i++) { echo rand(); echo ‘….Scene of shooting at Nebraska shopping centre Eight killed in Nebraska shooting A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people. Scene of shooting at Nebraska shopping centre Eight killed in Nebraska shooting A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people. Scene of shooting at Nebraska shopping centre Eight killed in Nebraska shooting A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people. Scene of shooting at Nebraska shopping centre Eight killed in Nebraska shooting A gunman opens fire in a shopping centre in the US state of Nebraska, killing at least eight people. ‘; } print “done!”; 这个做为是远程接口。 3.下面比较CURL和fastCGI两种访问remote API的方式: A:走FastCGI: include “./mod_fcgi.php”; $fcgi=new mod_fcgi(); $args=”127.0.0.1:1026”; $filename=”/home/y/www/qps/http.php”; $fcgi->parser_open($args,$filename,$rq_err,$cgi_headers); print($fcgi->parsed_output); echo “n=============n”; B:走CURL通道: include “./curl.php”; $curl=& new CURL(); echo $curl->get(“http://localhost/qps/http.php"); echo “n=============n”; 4我们比较FCGI方式和CURL方式的差异: FCGI方式进行远程调用的QPS: Total transferred: 249306 bytes HTML transferred: 244410 bytes Requests per second: 275.77 [#/sec] (mean) Time per request: 3.626 [ms] (mean) Time per request: 3.626 [ms] (mean, across all concurrent requests) Transfer rate: 2233.76 [Kbytes/sec] received HTTP通道进行远程调用的QPS: Total transferred: 2244515 bytes HTML transferred: 2240015 bytes Requests per second: 204.18 [#/sec] (mean) Time per request: 4.898 [ms] (mean) Time per request: 4.898 [ms] (mean, across all concurrent requests) 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扩展). 因此,我忙活了半天,最后得出的结论是,目前还不能在公司大规模加以运用。 但是对于小型企业,创业型公司来说,这种效率对比还是很有用的,可以加以挖掘。