How to connect to deployed grpc-server by ip address and host - go

I want to connect to deployed grpc server
by given ipaddress and host like 192.168.0.1:50032
i tried many stuff but as i checked grpc recommendation to
have grpc client but i want to try how to post via postman or any
by grpc interfaces server. Any suggestion?

conn, err := grpc.Dial("192.168.0.1:50032")
if err != nil {
...
}
Here's a basic tutorial you should follow

Basically you're not able to post GRPC request via Postman, because GRPC messages are binary (protobuf-serialized), while Postman is designed to work only with plain HTTP requests. You'll have to deploy some kind of proxy in front of your service in order to use Postman.
From my point of view, it's much easier just to write your client that fits your needs. The greatest part of job is already done by protoc-gen-grpc, because it generates client API, and you need just to build request and send it.

You cant use http client to send requests against http2 server, but you can do it with any of available h2 client tools.. For example https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md.

#Eli Bendersky : Setting up the client side answer my question also
this code I used
conn, err := grpc.Dial("192.168.0.1:50032", grpc.WithInsecure)
Thank you for your help.

Related

Google Cloud HTTP(S) load balancer does not cancel connection with backend

I have a Google Kubernetes Engine cluster, inside several pods with NodePorts, and all is exposed via an Ingress, which creates an HTTP load balancer (LB). I am using custom domain with Google managed SSL certificate for the LB.
My backend is an HTTP server written in Go, using its "net/http" package. It is using self-signed certificate for mTLS with LB (Google's HTTP LB accepts any certificate for mTLS).
Everything works fine, except for one case, and that is when a client creates an HTTP 1.1 connection with the LB and then cancels the request. This cancels the connection between the client and the LB, but LB holds an open connection with my backend until server's timeout.
My use-case requires requests to be opened even for hours, so my server has huge timeout values. Business logic inside the request is correctly using the request's Context and takes into account if the request is canceled by the client.
Everything works as expected if the client makes an HTTP2 request and cancels it i.e. the whole connection down to my backend is canceled.
Here is an example Go handler that simulates a cancelable long-running task:
func handleLongRunningTask(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
t := time.Now()
select {
case <-ctx.Done():
log.Println("request canceled")
case <-time.After(30 * time.Second):
log.Println("request finished")
}
log.Printf("here after: %v\n", time.Since(t))
w.WriteHeader(http.StatusOK)
}
The case <-ctx.Done(): is never called for canceled HTTP 1.1 requests.
For easy testing I am using curl and Ctrl+C; this works:
curl -v --http2 'https://example.com/long_running_task'
and this does not:
curl -v --http1.1 'https://example.com/long_running_task'
It does not matter if the NodePort is HTTPS or HTTP2, the LB has exactly the same behaviour regarding requests canceled by clients.
I tried compiling the server with Go 1.14.4 and 1.13.12 and the results are the same.
Is this a bug in Kubernetes, Ingress, Google Kubernetes Engine, Google's HTTP Load Balancer, Go's HTTP server? Or is it something with HTTP 1.1 that I am missing? What can be wrong and how can I fix this?
...it is not possible to know the HTTP version in the backend, so I could reject all HTTP 1.1 requests. LB is always using the same HTTP version when communicating with its backends, no matter the client's HTTP version.
From your description it looks like the issue might be between the GFE and the backends, since GFE might hold the connections for reuse.
My take is that you're seeing this variation between protocol version because how both handle connection persistence.
For HTTP2, the connection will be open until one of the parties send a termination signal and the earliest takes preference. But for HTTP1.1, it might be prolonged until an explicit connection header is sent, specifying the termination:
An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to maintain a persistent connection unless a Connection header including the connection-token "close" was sent in the request. If the server chooses to close the connection immediately after sending the response, it SHOULD send a Connection header including the connection-token close.
This might explain why HTTP1.1 follows the same timeout configuration as the LB and HTTP2 doesn't.
I'd recommend trying to actively send termination headers whenever you want to terminate a connection. An example taken from Github:
func (m *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Printf("HTTP request from %s", r.RemoteAddr)
// Add this header to force to close the connection after serving the request.
w.Header().Add("Connection", "close")
fmt.Fprintf(w, "%s", m.hostname)
}
Additionally, there seem to be some success stories switching your cluster to be VPC Native, as it takes out of the equation the kube-proxy connection management.
Finally, it might be that you're in a very specific situation that is worth being evaluated separately. You might want to try to send some replication steps to the GKE team using Issue Tracker.
I hope this helps.

how to make golang grpc clients follow redirects

I have a server that redirects to server:443 when connecting to server:80. I have a grpc client that is connecting to server:80 with
clientConn, err = grpc.Dial("server:80", grpc.WithTransportCredentials(credentials.NewTLS(config)))
Its throwing a "tls: first record does not look like a TLS handshake" error. Is there a way to make the client follow the redirects?
gRPC client does not handle 302 redirects. See this https://github.com/grpc/grpc-java/issues/5330 - this is for Java but also applies to Golang.

How to get the gRPC server IP from Go client

I use docker-compose or kubernetes to deploy my gRPC servers, and want to get the server IP address in the go client. Does the gRPC library provides the get server-side IP method?
BTW, the scenario here is that i want to log the server ip to check whether nginx, envoy and other L7 load balancers make correct routing decisions.
It's an interesting question, as you already have knowledge about the gRPC server address prior to a client creation
conn, err := grpc.Dial(*serverAddr)
if err != nil {
...
}
defer conn.Close()
client := pb.NewRouteGuideClient(conn)
I don't believe there is a method for getting server IP in the standard gRPC library. If you use external load balancers/proxies (e.g. Nginx or Envoy) you can add the end server IP to the metadata on the server side
md := metadata.Pairs(
"serverIP", "127.0.0.1",
)
The LB distributes the RPC call to one
of the available backend servers that implement the actual logic for
serving the call. The LB keeps track of load on each backend and
implements algorithms for distributing load fairly. The clients
themselves do not know about the backend servers.
read more https://grpc.io/blog/loadbalancing
Remote Procedure Call (RPC) is a higher level abstraction, you shouldn't deal with networking using RPC.
If you're trying to implement client side load balancing you should consider load balancing within gRPC (https://github.com/grpc/grpc/blob/master/doc/load-balancing.md), which is a special protocol you have to implement.
you can define a custom picker, like round-robin 1.
The struct map[balancer.SubConn]SubConnInfo can be used when you pick an address, allowing you to get SubConnInfo.

Netty Websockets, is it possible to have the server wait for client response

I am stuck trying to figure out how to implement a request-response going from netty websocket server to client, and then having the server handle the response maybe using channel future or something else in java.
I saw how to do the same using the client sending a request to server, and handling the response - but not the other way round.
Any help would be appreciated.
Well,
You need to make a connection to the client, and create a new handler, in that handler when it starts, you will write to the specific ip, you will need the ip of the client.
Quick recap:
1) Make a connection to the server (with the client).
2) Let the server create a handler for the client, (TIP: Try to set the ip as a parameter (Type: String))
3) Let the server write something first.
4) Let the client interact with it.
5) (Optional)See if the client needs to write something back.
6) (Optional)Let the server respond.
Good luck with your project.

Apply WSO2 WSF/C++ into client based on Https Protocol

I establish a server using WCF based on Https protocol, now i want to create a client using WSO2 WSF/C++(and the client code is generated by Code Generator Tool), however, i can't communicate with server, because the client is based on Http, not Https. And i do not know how to code my client, also there is little sample or code for reference, almost of them are based on http. Now, how can i code my client to implement Https protocol.Does any one know how should i use the API? Thanks!
Since WSF/C++ uses Axis2/C, the HTTPS configurations are same for both WSF/C++ and Axis2/C. You can find HTTPS configuration here.

Resources