elixir-grpc / grpc

An Elixir implementation of gRPC
https://hex.pm/packages/grpc
Apache License 2.0
1.39k stars 212 forks source link

How to Connect and Send Request when the GRPC Server Hostname and Ip is not known #303

Closed tclugao closed 1 year ago

tclugao commented 1 year ago

Describe the question Hello, I want to ask a question. Service A want to grpc call to Service B, but Service B is the in the ECS , in front of Service B, there exist a ALB (amazon load balancer), in genenal, all http requests are route to ALB fristly, then ALB forwards to request to Server B side's nigix, finally nigix proxy request to service B's app, so my questions is: if we don't know service B 's hostname and ip, how do the service A connect to service B's grpc server, I am a new comer in elixir-grpc, and as far as I know, elixir-grpc only provide the API "GRPC.Stub.connect("hostname_or_ip:port")" , this connection is need before service A want to rpc call to service B, so how do I solve this problem!

Versions:

sleipnir commented 1 year ago

Describe the question Hello, I want to ask a question. Service A want to grpc call to Service B, but Service B is the in the ECS , in front of Service B, there exist a ALB (amazon load balancer), in genenal, all http requests are route to ALB fristly, then ALB forwards to request to Server B side's nigix, finally nigix proxy request to service B's app, so my questions is: if we don't know service B 's hostname and ip, how do the service A connect to service B's grpc server, I am a new comer in elixir-grpc, and as far as I know, elixir-grpc only provide the API "GRPC.Stub.connect("hostname_or_ip:port")" , this connection is need before service A want to rpc call to service B, so how do I solve this problem!

Hello @tclugao, how are you?

At the end of the day it's all about IPs and Ports, you need an IP and Port addressing mechanism. For example, if you were running your services on Kubernetes it would be necessary to have a Service pointing to your Pods, it in turn would create endpoints which in turn are a table of IPs and Ports for each of your services. In summary what I am saying is that service discovery is part of the network infrastructure layer and is not within the scope of gRPC libraries. So you need to provide this upfront.

From what I understand of your topology, what you need is a DNS (or use the load balance IP) pointing to your load balancer. In turn, your NGINX that is behind the load balance needs to have gRPC support enabled. Doing this, a request to the load balancer should be enough for the routing to occur correctly.

It is worth remembering that most load balancers do not work at network layer 7 and therefore, in fact, their traffic would not be balanced. If you want this you need a proxy like Linkerd on Envoy in front of your services. But that's another story :D

Hope this helps.

polvalente commented 1 year ago

This is a more general question than just elixir-grpc. I'm closing this issue because the answer is related to how you would connect to any service through HTTP in your setup.

tclugao commented 1 year ago

@sleipnir thank you for your explanation, yes, base my understanding, do you mean that in actual prod env, grpc client just send a request(URI) to do the rpc call to another service, no need to call function "GRPC.Stub.connect("hostname_or_ip:port")" fristly?

sleipnir commented 1 year ago

@sleipnir thank you for your explanation, yes, base my understanding, do you mean that in actual prod env, grpc client just send a request(URI) to do the rpc call to another service, no need to call function "GRPC.Stub.connect("hostname_or_ip:port")" fristly?

You need to connect. You can pass a URI as a parameter, as long as your dns knows how to resolve the URI to the server and your reverse proxy knows how to map to the ip and port properly for your service you will be fine.

Maybe these links can help you, not related to elixir but the principles are the same for any grpc client:

https://www.nginx.com/blog/nginx-1-13-10-grpc/

https://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/patterns/deploy-a-grpc-based-application-on-an-amazon-eks-cluster-and-access-it-with-an-application-load-balancer.html

https://fulcrum.rocks/blog/load-balancer-grpc-aws

https://gist.github.com/bojand/6a604f7e369d7c7d8c39eb77878a42c2

tclugao commented 1 year ago

@sleipnir we upgrage our alb ,nigix, DNS to support grpc, but when I call function : iex(app_name@ip-10-150-3-85)5> GRPC.Stub.connect("https://api-auth-alb.int.env5.app.com/v1/app-service/grpc/") (ArgumentError) errors were found at the given arguments:

from A service to B service, it crashed, I also checked the implemention of GRPC.Stub.connect/1 function, it just suport format "hostname:ip", so pass a uri as parameter seem not work?

sleipnir commented 1 year ago

@sleipnir we upgrage our alb ,nigix, DNS to support grpc, but when I call function : iex(app_name@ip-10-150-3-85)5> GRPC.Stub.connect("https://api-auth-alb.int.env5.app.com/v1/app-service/grpc/") (ArgumentError) errors were found at the given arguments:

* 1st argument: not a textual representation of an integer
  :erlang.binary_to_integer("//api-auth-alb.int.env5.app.com/v1/care-provider-service/grpc/")**

from A service to B service, it crashed, I also checked the implemention of GRPC.Stub.connect/1 function, it just suport format "hostname:ip", so pass a uri as parameter seem not work?

Let's say your loadbalancer is configured with https on port 8443. Then use the host and port like this:

GRPC.Stub.connect("api-auth-alb.int.env5.app.com", 8443)

The gRPC library currently does not make any port assumptions based on the protocol, so you need to be explicit about this as it has no way of knowing your network configuration and therefore you need to pass the port

tclugao commented 1 year ago

@sleipnir Hi, thanks for your support! now we can connect, but also encounter another issue, our ALB listener is HTTPS, if we connect without tls, it reported error as follow: image

if I add tls opts on both client side and app grpc server side, it reported error as following: image

certificate files are copied from examples route guide.

so can you give me some insights how to solve these errors? thank you i am new comer for elixir and grpc?