Proxy inverso en Azure Service Fabric

El servidor proxy inverso creado en Azure Service Fabric ayuda a que los microservicios que se ejecutan en un clúster de Service Fabric detecten otros servicios que tienen puntos de conexión HTTP y se comuniquen con estos servicios.

Modelo de comunicación de microservicios

Los microservicios de Service Fabric se ejecutan en un subconjunto de nodos del clúster y se pueden migrar entre los nodos por varias razones. Como resultado, los puntos de conexión de los microservicios pueden cambiar dinámicamente. Para detectar otros servicios y comunicarse con ellos en el clúster, el microservicio debe pasar por los siguientes pasos:

  1. Resuelva la ubicación del servicio mediante el servicio de nombres.
  2. Conéctese al servicio.
  3. Ajuste los pasos anteriores en un bucle que implemente la solución de servicio y vuelva a intentar que se apliquen directivas con los errores de conexión

Para más información, consulte Conexión y comunicación con los servicios.

Comunicación mediante el proxy inverso

El servidor proxy inverso es un servicio que se ejecuta en cada nodo y gestiona la resolución de puntos de conexión, el reintento automático y otros errores de conexión en nombre de los servicios para clientes. Se puede configurar para la aplicación de varias directivas cuando gestiona las solicitudes desde los servicios para clientes. El uso de un proxy inverso permite al servicio cliente usar las bibliotecas de comunicación HTTP del lado cliente y no requiere una resolución especial ni una lógica de reintento en el servicio.

El servidor proxy inverso expone uno o varios puntos de conexión en el nodo local de los servicios para clientes para su uso en el envío de solicitudes a otros servicios.

Comunicación interna

Nota

Plataformas compatibles

El servidor proxy inverso de Service Fabric admite actualmente las siguientes plataformas

  • Clúster Windows: Windows 8 y posterior o Windows Server 2012 y posterior
  • Clúster de Linux: el proxy inverso no está disponible actualmente para clústeres de Linux

Comunicación externa con los microservicios a través del clúster

El modelo de comunicación externo predeterminado para microservicios es un modelo de participación en el que no se puede acceder a cada servicio directamente desde clientes externos. Azure Load Balancer actúa como límite de red entre los microservicios y los clientes externos. Además, realiza la traducción de direcciones de red y reenvía las solicitudes externas a los puntos de conexión IP:port internos. Para hacer que los clientes externos puedan acceder directamente al punto de conexión de un microservicio, primero debe configurar Load Balancer para que reenvíe el tráfico a cada puerto que utilice el servicio del clúster. Sin embargo, la mayoría de los microservicios, especialmente los microservicios con estado, no se encuentran en todos los nodos del clúster. Los microservicios se pueden mover entre nodos durante la conmutación por error. En tales casos, Load Balancer no puede determinar eficazmente la ubicación del nodo de destino de las réplicas a las que debe reenviar el tráfico.

Comunicación externa con los microservicios a través del clúster mediante el proxy inverso

En lugar de configurar el puerto de un servicio individual de Load Balancer, puede configurar solo el puerto del proxy inverso de Load Balancer. Esta configuración permite a los clientes externos al clúster comunicarse con los servicios internos de este a través del proxy inverso sin realizar más ajustes en la configuración.

Comunicación externa

Advertencia

Al configurar el puerto del proxy inverso de Load Balancer, se podrá acceder de manera externa a todos los microservicios del clúster que exponen un punto de conexión HTTP. Esto significa que un usuario malintencionado determinado podría detectar microservicios destinados a ser internos. Potencialmente, implica vulnerabilidades graves que podrían aprovecharse, como, por ejemplo:

  • Un usuario malintencionado puede iniciar un ataque por denegación de servicio llamando repetidamente a un servicio interno que no tiene una superficie de ataque suficientemente protegida.
  • Un usuario malintencionado puede entregar paquetes con formato incorrecto a un servicio interno y provocar un comportamiento no deseado.
  • Un servicio destinado a ser interno podría devolver información privada o confidencial que no se pretende exponer a servicios fuera del clúster, y ponerla así a disposición de un usuario malintencionado.

Asegúrese de entender completamente y de mitigar las posibles repercusiones para la seguridad del clúster y las aplicaciones que se ejecutan en este, antes de hacer público el puerto de proxy inverso.

Formato del URI para comunicarse con los servicios mediante el proxy inverso

El proxy inverso utiliza un formato de identificador uniforme de recursos (URI) específico para identificar a qué partición de servicio se debe reenviar la solicitud entrante:

http(s)://<Cluster FQDN | internal IP>:Port/<ServiceInstanceName>/<Suffix path>?PartitionKey=<key>&PartitionKind=<partitionkind>&ListenerName=<listenerName>&TargetReplicaSelector=<targetReplicaSelector>&Timeout=<timeout_in_seconds>
  • http(s) : el proxy inverso puede configurarse para que acepte tráfico HTTP o HTTPS. Para el reenvío HTTPS, vea Connect to a secure service with the reverse proxy (Conectar a un servicio seguro con el proxy inverso) después de configurar el proxy inverso para que escuche en HTTPS.

  • Cluster fully qualified domain name (FQDN) | internal IP: para clientes externos, se puede configurar el proxy inverso para que sea accesible a través del dominio del clúster (por ejemplo, micluster.eastus.cloudapp.azure.com). De forma predeterminada, el proxy inverso se ejecuta en todos los nodos. Para el tráfico interno se puede acceder al proxy inverso en el host local o en cualquier dirección IP del nodo interno (por ejemplo, 10.0.0.1).

  • Port: el puerto especificado para el proxy inverso. Por ejemplo, el puerto 19081.

  • ServiceInstanceName: se trata del nombre completo de la instancia de servicio implementada con la que está tratando de comunicarse (sin el esquema "fabric:/"). Por ejemplo, para establecer conexión con el servicio fabric:/miAplicación/miServicio/, podría usar miaplicación/miservicio.

    El nombre de instancia del servicio distingue mayúsculas de minúsculas. Un uso de mayúsculas y minúsculas diferente para el nombre de instancia del servicio en la dirección URL hace que se produzca el error 404 (No encontrado) en las solicitudes.

  • Suffix path: se trata de la ruta de acceso URL real del servicio con el que quiere conectarse. Por ejemplo, myapi/values/add/3.

  • PartitionKey: en un servicio particionado, corresponde a la clave de partición calculada de la partición con la que quiere conectarse. Tenga en cuenta que esto no es el GUID del identificador de partición. Este parámetro no es necesario para los servicios que usan el esquema de partición singleton.

  • PartitionKind: es el esquema de particiones singleton. El valor puede ser Int64Range o Con nombre. Este parámetro no es necesario para los servicios que usan el esquema de partición singleton.

  • ListenerName: los puntos de conexión del servicio presentan la forma {"Endpoints":{"Listener1":"Endpoint1","Listener2":"Endpoint2" ...}}. Cuando el servicio expone varios puntos de conexión, esto identifica a qué puntos de conexión se debe reenviar la solicitud del cliente. Esto se puede omitir si el servicio tiene solo un agente de escucha.

  • TargetReplicaSelector: especifica cómo se debe seleccionar la instancia o la réplica de destino.

    • Cuando el servicio de destino tiene estado, el valor de TargetReplicaSelector puede ser uno de los siguientes: "PrimaryReplica", "RandomSecondaryReplica" o "RandomReplica". Cuando no se especifica este parámetro, el valor predeterminado es "PrimaryReplica".
    • Cuando el servicio de destino no tiene estado, el proxy inverso elige una instancia aleatoria de la partición de servicio a la que reenviar la solicitud.
  • Timeout: especifica el tiempo de espera de la solicitud HTTP que crea el proxy inverso para conectarse al servicio en nombre de la solicitud de cliente. El valor predeterminado es 120 segundos. Se trata de un parámetro opcional.

Ejemplo de uso

A modo de ejemplo, veamos el servicio fabric:/miAplicación/miServicio que abre un agente de escucha HTTP en la siguiente dirección URL:

http://10.0.0.5:10592/3f0d39ad-924b-4233-b4a7-02617c6308a6-130834621071472715/

Los recursos para el servicio son los siguientes:

  • /index.html
  • /api/users/<userId>

Si el servicio utiliza el esquema de particiones de singleton, no se requieren los parámetros de cadena de consulta PartitionKey y PartitionKind, y se podrá acceder a él mediante la puerta de enlace de las siguientes formas:

  • Externamente: http://mycluster.eastus.cloudapp.azure.com:19081/MyApp/MyService
  • Internamente: http://localhost:19081/MyApp/MyService

Si el servicio usa el esquema de particiones Int64 uniforme, deben utilizarse los parámetros de cadena de consulta PartitionKey y PartitionKind para comunicarse con una partición del servicio:

  • Externamente: http://mycluster.eastus.cloudapp.azure.com:19081/MyApp/MyService?PartitionKey=3&PartitionKind=Int64Range
  • Internamente: http://localhost:19081/MyApp/MyService?PartitionKey=3&PartitionKind=Int64Range

Para acceder a los recursos que expone el servicio, basta con colocar su ruta de acceso después del nombre del servicio en la URL:

  • Externamente: http://mycluster.eastus.cloudapp.azure.com:19081/MyApp/MyService/index.html?PartitionKey=3&PartitionKind=Int64Range
  • Internamente: http://localhost:19081/MyApp/MyService/api/users/6?PartitionKey=3&PartitionKind=Int64Range

Después, la puerta de enlace reenviará estas solicitudes a la URL del servicio:

  • http://10.0.0.5:10592/3f0d39ad-924b-4233-b4a7-02617c6308a6-130834621071472715/index.html
  • http://10.0.0.5:10592/3f0d39ad-924b-4233-b4a7-02617c6308a6-130834621071472715/api/users/6

Control especial de los servicios de uso compartido de puertos

El proxy inverso de Service Fabric intenta resolver una dirección de servicio de nuevo y vuelve a intentar la solicitud cuando no se puede acceder a un servicio. Por lo general, cuando no se puede acceder a un servicio, la instancia de servicio o réplica se ha movido a un nodo diferente como parte de su ciclo de vida normal. Cuando esto sucede, es posible que el proxy inverso reciba un error de conexión de red que indica que un punto de conexión ya no está abierto en la dirección resuelta originalmente.

Sin embargo, las instancias del servicio o las réplicas pueden compartir un proceso de host y un puerto cuando un servidor web basado en http.sys las hospeda; por ejemplo:

En este caso, es probable que el servidor web esté disponible en el proceso de host y que responda a las solicitudes, pero no la instancia del servicio resuelta o la réplica. Si esto ocurre, la puerta de enlace recibirá una respuesta HTTP 404 del servidor web. Por lo tanto, una respuesta HTTP 404 puede tener dos significados distintos:

  • Caso 1: la dirección del servicio es correcta, pero el recurso solicitado por el usuario no existe.
  • Caso 2: la dirección de servicio es incorrecta y puede que el recurso que ha solicitado el usuario exista en un nodo diferente.

En el primer caso, se trata de una respuesta HTTP 404 normal que se considera un error de usuario. Sin embargo, en el segundo caso, el usuario ha solicitado un recurso que ya existe. El proxy inverso no pudo encontrarlo porque se había movido el servicio. El proxy inverso debe resolver la dirección de nuevo y volver a intentar la solicitud.

Por tanto, el proxy inverso necesita una manera de diferenciar estos dos casos. Para que pueda hacerlo, necesita una indicación del servidor.

  • De manera predeterminada, el proxy inverso da por hecho que es el segundo caso y trata de volver a resolver y emitir la solicitud.

  • Para que sepa que se trata del primero, el servicio debe devolver el siguiente encabezado de respuesta HTTP:

    X-ServiceFabric : ResourceNotFound

Este encabezado de respuesta HTTP indica una situación HTTP 404 normal en la que el recurso solicitado no existe y el proxy inverso no intentará resolver de nuevo la dirección del servicio.

Control especial para los servicios que se ejecutan en contenedores

Para los servicios que se ejecutan en contenedores, puede usar la variable de entorno Fabric_NodeIPOrFQDN para construir la dirección URL del proxy inverso como se muestra en el código siguiente:

    var fqdn = Environment.GetEnvironmentVariable("Fabric_NodeIPOrFQDN");
    var serviceUrl = $"http://{fqdn}:19081/DockerSFApp/UserApiContainer";

Para el clúster local, Fabric_NodeIPOrFQDN está establecido en "localhost" de forma predeterminada. Inicie el clúster local con el parámetro -UseMachineName para asegurarse de que los contenedores pueden llegar al proxy inverso que se ejecuta en el nodo. Para más información, consulte Configuración del entorno de desarrollo para depurar contenedores.

Los servicios de Service Fabric que se ejecutan dentro de contenedores de Docker Compose requieren una configuración http: o https: especial para la sección de puertos del archivo docker-compose.yml. Para obtener más información, consulte Compatibilidad con la implementación de Docker Compose en Azure Service Fabric.

Pasos siguientes