He intentado que el equilibrio de carga de GRPC funcione en mi aplicación Java implementada en un clúster de Kubernetes, pero no he tenido demasiado éxito. No parece haber demasiada documentación sobre esto, pero a partir de ejemplos en línea puedo ver que ahora debería poder usar '.defaultLoadBalancingPolicy("round_robin")' al configurar ManagedChannel (en versiones posteriores de GRPC Java lib) .
Para ser más específico, estoy usando la versión 1.34.1 de las bibliotecas GRPC Java. Creé dos aplicaciones Spring Boot (v2.3.4), una llamada grpc-sender y otra llamada grpc-receiver.
grpc-sender actúa como un cliente GRPC y define un ManagedChannel (Netty) como:
@Bean public ManagedChannel greetingServiceManagedChannel() { String host = "grpc-receiver"; int port = 6565; return NettyChannelBuilder.forAddress(host, port) .defaultLoadBalancingPolicy("round_robin") .usePlaintext().build(); }Entonces grpc-receiver actúa como el servidor GRPC:
Server server = ServerBuilder.forPort(6565) .addService(new GreetingServiceImpl()).build();Estoy implementando estas aplicaciones en un clúster de Kubernetes (que se ejecuta localmente en minikube por el momento) y he creado un servicio para la aplicación grpc-receiver como un servicio sin cabeza, de modo que se pueda lograr el equilibrio de carga de GRPC.
Para probar las solicitudes fallidas, hago dos cosas:
Con los dos anteriores, puedo obtener una proporción de las solicitudes durante una ejecución de prueba para fallar. Ahora lo que estoy tratando de hacer que funcione el mecanismo de reintento de GRPC. Al leer la escasa documentación, estoy haciendo lo siguiente:
return NettyChannelBuilder.forAddress(host, port) .defaultLoadBalancingPolicy("round_robin") .enableRetry() .maxRetryAttempts(10) .usePlaintext().build();Sin embargo, esto parece no tener ningún efecto y no puedo ver que las solicitudes fallidas se vuelvan a intentar.
Veo que esto todavía está marcado como una característica de @ExperimentalApi, entonces, ¿debería funcionar como se esperaba y se ha implementado?
Si es así, ¿hay algo obvio que me estoy perdiendo? ¿Algo más que deba hacer para que los reintentos funcionen?
¿Alguna documentación que explique cómo hacer esto con más detalle?
Muchas gracias de antemano...
ManagedChannelBuilder.enableRetry().maxRetryAttempts(10) no es suficiente para que se produzca el reintento. El reintento necesita una configuración de servicio con RetryPolicy definida. Una forma es establecer una configuración de servicio predeterminada con RetryPolicy, consulte el ejemplo de reintento en https://github.com/grpc/grpc-java/tree/v1.35.0/examples
Ha habido cierta confusión en el javadoc de maxRetryAttempts(), y se aclara en https://github.com/grpc/grpc-java/pull/7803
¡Muchas gracias @user675693! Eso funcionó perfectamente :)
El funcionamiento de maxRetryAttempts() es ciertamente un poco confuso.
De la documentación puedo ver que:
"maxAttempts DEBE especificarse y DEBE ser un valor entero JSON superior a 1. Los valores superiores a 5 se tratan como 5 sin que se consideren un error de validación".
Refiriéndose a maxAttempts en la configuración del servicio. Si queremos más de 5 intentos, puedo configurarlo como maxRetryAttempts(10), por ejemplo, en mi configuración de ManagedChannel:
return NettyChannelBuilder.forAddress(host, port) .defaultLoadBalancingPolicy("round_robin") .defaultServiceConfig(config) .enableRetry() .maxRetryAttempts(10) .usePlaintext().build();Pero para que esa configuración se use correctamente, necesito configurarla como 10 en la configuración del servicio Y el código de configuración de ManagedChannel; de lo contrario, solo se realizan 5 reintentos. No está claro en el Javadoc o en la documentación, pero eso es lo que parece suceder en mis pruebas.
Además, esta funcionalidad de reintento está marcada como @ExperimentalApi. ¿Qué tan maduro es, es adecuado para ser utilizado en la producción? ¿Es probable que cambie drásticamente?