近来由于业务量急剧增长,业务种类越来越多,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扩展).
因此,我忙活了半天,最后得出的结论是,目前还不能在公司大规模加以运用。
但是对于小型企业,创业型公司来说,这种效率对比还是很有用的,可以加以挖掘。