Proxy para manter a conexão com a API viva

3

Em um servidor eu tenho cerca de 30 sites PHP em execução no Apache. Todos esses sites usam a mesma API (HTTP) para buscar alguns dados. A API está hospedada em outro lugar (sob meu controle)

A API usa o Nginx com o keep-alive e os sites PHP usam o CURL para fazer as solicitações da API.

Um visitante de 1 dos 30 sites geraria uma chamada de API, e a conexão com a API seria fechada pelo apache / PHP assim que o HTML fosse entregue ao visitante.

O que eu estou procurando é algo como um proxy local para a API que é capaz de manter a conexão com ele para que os sites PHP possam lucrar com o keepalive.

De qualquer forma, para realizar isso?

    
por Ivor 10.10.2012 / 19:30

3 respostas

1

O Nginx configurado como um proxy reverso pode fazer isso facilmente:

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
  }
 }
}

Agora você pode apontar seus scripts para o servidor local em vez do remoto, aqui está uma demonstração com 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"
}

Como você pode ver, até mesmo o cabeçalho do host é transmitido como está.

Ou você pode tornar a transição perfeita, fazendo com que o nome do host remoto aponte para a sua máquina local, seja em /etc/hosts ou na configuração do seu resolvedor de DNS. Nesse caso, certifique-se de usar apenas endereços IP em vez de nomes de host na definição do conjunto na configuração do Nginx, caso contrário, o proxy também fará o loop de volta para si mesmo e isso causará um pouco de desastre.

Quando o arquivo hosts for alterado, o proxy será perfeito:

$ 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"
}

Como você pode ver, nosso servidor local se comporta exatamente como o remoto e qualquer programa que tente acessar o nome do host remoto se conectará ao nosso servidor local.

Observe que isso pode exigir configuração adicional para hosts baseados em HTTPS.

    
por 15.03.2015 / 01:45
0

funções de soquete do PHP podem ser a abordagem mais fácil. O Socket_create tratará das conexões IPv4, IPv6 e UNIX. Um exemplo rápido

$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);

Mais exemplos em php.net: Exemplos de sockets

    
por 10.10.2012 / 20:40
0

Você pode escrever um script php que seria iniciado a partir da linha de comando e demonizaria, abriria um manipulador de curl e o reutilizaria para cada solicitação subseqüente, portanto, usando o recurso keep-alive. Esse script deve fornecer uma API usando filas de mensagens (confira beanstalkd / rabbitmq). Assim que houver uma nova mensagem na fila, o script deverá fazer uma solicitação à API externa e enviar o resultado de volta à fila do sistema de mensagens. Alternativamente, fornecer uma API usando sockets (mas isso pode ser muito complicado, pois deve ser multi-threaded, multi-multithreading no PHP pode ser alcançado usando bifurcação e não tenho certeza como o identificador de curl se comportaria se você tentasse usá-lo em vários subprocessos de cada vez). Também pode haver um impacto no desempenho para usar isso, portanto, se você tiver muitos usuários, provavelmente deverá criar vários daemons que sejam executados ao mesmo tempo.

    
por 15.03.2015 / 00:50