代理保持连接到活着的API

在一台服务器上,我有大约30个PHP站点在Apache下运行。 所有这些网站使用相同的(HTTP)API来获取一些数据。 API托pipe在其他地方(在我的控制下)

API使用Nginx保持活动,PHP站点使用CURL来提出API请求。

访问这30个站点中的一个将产生一个API调用,并且一旦HTML被传递给访问者,API的连接将被apache / PHPclosures。

我正在寻找的东西就像API的本地代理,它能够维持与它的连接,所以PHP站点可以从Keepalive中获利。

无论如何完成这个?

configuration为反向代理的 Nginx可以很轻松地做到这一点:

http { upstream remoteserver { # here you add your remote server's IPs or hostnames server 54.175.222.246; # for example here we use HTTPBin's address keepalive 10; # maintain a maximum of 10 open connections } server { listen 80; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # passing the client's IP to the remote server, on a local machine it doesn't do much though proxy_set_header Host $http_host; # passing the Host header as requested by the client, otherwise this will default to the pool's name, "remoteserver" in this case proxy_pass http://remoteserver; # sends the request off to the pool defined above } } } 

现在你可以将你的脚本指向本地服务器而不是远程脚本,下面是一个带有curl的演示:

 $ curl http://localhost/get -H "Host: host header is passed normally" { "args": {}, "headers": { "Accept": "*/*", "Host": "host header is passed normally", "User-Agent": "curl/7.29.0" }, "origin": "127.0.0.1, 1.2.3.4", "url": "http://host header is passed normally/get" } 

正如你所看到的,即使是Host头也是按原样传递的。

或者,您可以通过将远程主机名指向本地计算机(无论是在/etc/hosts还是在DNSparsing器的configuration中)来实现无缝转换。 在这种情况下,请务必在Nginxconfiguration的池定义中只使用IP地址,而不是主机名,否则代理也会循环回自己,这会导致一些灾难。

一旦主机文件被相应地改变,代理是无缝的:

 $ curl http://httpbin.org/get -v * About to connect() to httpbin.org port 80 (#0) * Trying 127.0.0.1... * Connected to httpbin.org (127.0.0.1) port 80 (#0) > GET /get HTTP/1.1 > User-Agent: curl/7.29.0 > Host: httpbin.org > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.6.2 < Date: Sun, 15 Mar 2015 00:41:54 GMT < Content-Type: application/json < Content-Length: 198 < Connection: keep-alive < Access-Control-Allow-Origin: * < Access-Control-Allow-Credentials: true < { "args": {}, "headers": { "Accept": "*/*", "Host": "httpbin.org", "User-Agent": "curl/7.29.0" }, "origin": "127.0.0.1, 1.2.3.4", "url": "http://httpbin.org/get" } 

正如你所看到的,我们的本地服务器就像远程服务器一样,任何试图访问远程主机名的程序都会连接到我们的本地服务器。

请注意,这可能需要对基于HTTPS的主机进行其他configuration。

PHP的套接字函数可能是最简单的方法。 Socket_create将处理IPv4,IPv6和UNIX连接。 一个简单的例子

 $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); $address = '127.0.0.1'; $port = 80; socket_connect($socket,$address,$port); // Sending data socket_write('Your API commands here'); // Reading data while ($buffer = socket_read($socket,1024,PHP_NORMAL_READ)) { if(trim($buffer) == 'END') { break; } } socket_close($socket); 

更多的例子在php.net: 套接字示例

你可能想编写一个php脚本,它将从命令行启动,并将被妖魔化,打开一个curl句柄,并将其用于每个后续请求,因此使用保持活动function。 这个脚本应该提供一个使用消息队列的API(检出beanstalkd / rabbitmq)。 只要队列中有新消息,脚本就会向外部API发出请求,并将结果返回到消息队列中。 或者使用套接字来提供一个API(但是这可能是非常棘手的,因为它应该是multithreading的,PHP中的multithreading可能使用fork来实现,而我不确定curl句柄如果尝试使用一次在多个subprocess中)。 这可能也会影响性能,所以如果你有很多用户,你可能应该创build多个同时运行的守护进程。