1台のサーバーに30個のPHPサイトがApacheで実行されています。これらのサイトはすべて同じ(HTTP)APIを使用してデータをフェッチします。APIは他の場所でホストされています(私の管理下にあります)
APIはキープアライブでNginxを使用し、PHPサイトはAPIリクエストを行うためにCURLを使用します。
30のサイトのうちの1つへの訪問者はAPI呼び出しを生成し、APIへの接続は、HTMLが訪問者に配信されるとすぐにApache/PHPによって閉じられます。
私が探しているのは、APIへの接続を維持できる、APIへのローカルプロキシのようなものです。これにより、PHPサイトはキープアライブから利益を得ることができます。
とにかくこれを達成するのですか?
リバースプロキシ として構成された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
またはDNSリゾルバーの構成で、リモートホスト名がローカルマシンを指すようにすることで、移行をシームレスにすることができます。この場合、Nginxの構成のプール定義でホスト名ではなく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ベースのホストの追加構成が必要になる場合があることに注意してください。
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スクリプトを記述して、キープアライブ機能を使用することをお勧めします。このスクリプトは、メッセージングキューを使用してAPIを提供する必要があります(beanstalkd/rabbitmqを確認してください)。キューに新しいメッセージがあるとすぐに、スクリプトは外部APIにリクエストを送信し、結果をメッセージングキューにプッシュバックする必要があります。または、ソケットを使用してAPIを提供します(ただし、マルチスレッドである必要があるため、これは非常に難しい場合があります。PHPはフォークを使用して実現される可能性があり、カールの処理方法がわかりません。一度に複数のサブプロセスで使用しようとすると動作します)。これを使用するとパフォーマンスが低下する可能性があるため、ユーザーが多い場合は、同時に実行する複数のデーモンを作成する必要があります。