Encaminhar solicitações de rede de entrada para uma determinada porta para diferentes aplicativos

3

Eu tenho um aplicativo que ouve conexões em uma porta, mas ocasionalmente desisto de atualizações e coisas do tipo. Eu gostaria de uma maneira de configurar o sistema de tal forma que, se esse programa está sendo executado, os pedidos para essa porta são enviados para o aplicativo, mas se ele não estiver sendo executado, os pedidos serão direcionados para algum outro aplicativo (que pode retornar um "temporariamente indisponível") mensagem). Qual é a maneira mais fácil de conseguir isso?

Eu não tenho acesso root na máquina de destino, então prefiro evitar itens como iptables . Eu considerei um aplicativo auxiliar que não faz nada além de rotear conexões para os outros dois aplicativos, mas eu espero que haja uma maneira mais fácil

    
por Michael Mrozek 16.04.2012 / 22:15

1 resposta

6

Sua pergunta implica que ambos os programas seriam executados em alternância na mesma máquina, ligados à mesma porta. Esta é uma má ideia. Você vai encontrar o problema TIME_WAIT (a.k.a. 2MSL) se tentar isso. Este artigo descreve o problema. (É centrado no Windows, mas a maior parte do que está sendo dito se aplica a qualquer pilha TCP / IP.)

A API de sockets do BSD fornece uma maneira de derrotar essa proteção ( setsockopt(SO_REUSEADDR) ), mas esse não é um dos casos em que isso é justificado.

Em vez disso, resolva o problema da mesma maneira que os populares de alta disponibilidade: coloque um proxy reverso entre o mundo e seu servidor back-end "real".

No mundo HTTP, uma solução popular para esse problema é nginx . Você pode configurá-lo para que, enquanto o servidor back-end estiver inativo, ele forneça conteúdo estático aos clientes. Se o seu protocolo se parece com HTTP, IMAP ou POP, talvez você possa usar o nginx como está. Caso contrário, você poderia criar um servidor proxy personalizado.

Você provavelmente precisará de duas portas TCP para que isso funcione. O proxy é vinculado ao número da porta voltada para o público, no IP público. Seu servidor de backend se conecta a uma porta secundária, somente na interface de host local. Assim, o tráfego pode passar da rede pública para o servidor back-end somente por meio do proxy.

Você pode usar a ligação para a mesma porta se ambos os programas forem escritos para permitir isso. Por exemplo, se o seu IP público for 1.2.3.4 e sua porta de serviço público for 2345 , ambos os programas poderão associar à porta 2345 se o proxy reverso se vincular apenas ao IP 1.2.3.4 e o servidor "real" se vincular apenas a %código%. Se qualquer um deles for ligado a 127.0.0.1 (0.0.0.0), você precisará de portas diferentes.

Isso resolve o problema 2MSL porque seus clientes estão sempre conversando com o mesmo programa, o servidor proxy. A pilha de rede nunca ficará confusa sobre o que fazer com qualquer pacote perdido no tempo de 2MSL.

Uma variação no proxy reverso é o balanceador de carga e também pode funcionar aqui. Um balanceador de carga foi projetado para rotear o tráfego de maneira inteligente para diferentes máquinas. Esse tipo de proxy faria sentido se você achasse que seu aplicativo um dia precisaria ser dimensionado horizontalmente. Você selecionaria um balanceador de carga que saiba como enviar tráfego para um host "down service" especial quando todos os servidores de aplicativos normais estiverem inativos.

O principal problema da variante de solução de balanceador de carga é que um balanceador de carga genérico pode assumir cegamente que todos os serviços de back-end para os quais ele é proxy estão usando o mesmo número de porta, diferindo apenas no IP. Você pode conseguir um balanceador de carga mais flexível ou obter vários IPs para seu servidor compartilhado.

    
por 16.04.2012 / 23:55