At Fulcrum we had a similar case.
We also built a product completely on microservices architecture and decided to use gRPC framework. We then immediately faced the problem of how to load balance traffic using the Application Load Balancer (Layer 7). As it turned out – AWS does not support HTTP 2.0 yet.
Why we used Envoy
As the commenter above pointed out, Envoy is a great option here. It's been developed at Lyft and it's great. It's very lightweight compared to the alternatives and it's easy to incorporate into a microservices architecture.
Basically, we used the standard Frontend Envoy load balancer. Besides, there're also load balancers called sidecars. Each of them is placed just near each instance of service. They work specifically with the service nearby & they are also connected with each other.
As a result, Frontend proxy always has a connection or it can create one when needed. It uses a 'round-robin' model for sending requests.
Here's a complete description of our experience with load balancing gRPC > https://fulcrum.rocks/blog/load-balancer-grpc-aws
We also created a very simple service that you can download from our GitHub and launch the playground on your own machine: https://github.com/fulcrum-rocks/grpc-load-balancing-playground
Here's how we configured Frontend Proxy
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: $LISTEN_PORT
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: http2
stat_prefix: ingress_grpc
http2_protocol_options: {}
route_config:
name: service_route
virtual_hosts:
- name: service_host
domains:
- "*"
routes:
- match:
prefix: "/"
grpc: {}
route:
cluster: service_cluster
timeout:
seconds: 0
nanos: 0
http_filters:
- name: envoy.router
config: {}
clusters:
- name: service_cluster
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
http2_protocol_options: {}
hosts:
- socket_address:
address: $SERVICE_DISCOVERY_ADDRESS
port_value: $SERVICE_DISCOVERY_PORT
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 80