Golang GRPC Practice serial seven HTTP protocol conversion

Source: Internet
Author: User
Tags readfile
This is a creation in Article, where the information may have evolved or changed.

GRPC HTTP protocol Conversion

Just when there is a need, we see this implementation posture. A blog from CoreOS, reprinted to the GRPC official blog Grpc with REST and Open APIs.

ETCD3 switch to GRPC to be compatible with the original API, but also to provide Http/json way of the API, in order to meet this need, either develop two sets of APIs, or implement a conversion mechanism, they chose the latter, and we choose to follow their footsteps.

They implemented a gateway to the protocol transformation that corresponds to the project Grpc-gateway on GitHub, which is responsible for receiving client requests and then deciding to go directly to the GRPC service or to the HTTP service, and of course the HTTP service needs to request the GRPC service to get a response. It then transitions to the JSON response to the client. Structure

Let's go straight to the actual combat. Based on the HELLO-TLS project extension, client churn is small and the server and proto changes are large.

Installing Grpc-gateway

go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway

Project structure:

$GOPATH/src/grpc-go-practice/example/|—— hello-http-2/    |—— client/        |—— main.go   // 客户端    |—— server/        |—— main.go   // 服务端|—— keys/                 // 证书目录    |—— server.key    |—— server.pem|—— proto/    |—— google       // googleApi http-proto定义        |—— api            |—— annotations.proto            |—— annotations.pb.go            |—— http.proto            |—— http.pb.go    |—— hello_http.proto   // proto描述文件    |—— hello_http.pb.go   // proto编译后文件    |—— hello_http_pb.gw.go // gateway编译后文件

The two proto profiles in Google's official API are used here, and the direct copy is not modified, which defines the HTTP option for the protocol buffer extension, providing support for GRPC HTTP conversion.

Sample code

Proto/hello_http.proto

syntax = "proto3";  // 指定proto版本package proto;     // 指定包名import "google/api/annotations.proto";// 定义Hello服务service HelloHttp {    // 定义SayHello方法    rpc SayHello(HelloHttpRequest) returns (HelloHttpReply) {        // http option        option (google.api.http) = {            post: "/example/echo"            body: "*"        };    }}// HelloRequest 请求结构message HelloHttpRequest {    string name = 1;}// HelloReply 响应结构message HelloHttpReply {    string message = 1;}

This SayHello adds the HTTP option to the original method definition, the Post method, and the route to "/example/echo".

Compiling proto

cd $GOPATH/src/grpc-go-practice/example/hello-http-2/proto# 编译google.apiprotoc -I . --go_out=plugins=grpc,Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor:. google/api/*.proto# 编译hello_http.protoprotoc -I . --go_out=plugins=grpc,Mgoogle/api/annotations.proto=git.vodjk.com/go-grpc/example/proto/google/api:. ./*.proto# 编译hello_http.proto gatewayprotoc --grpc-gateway_out=logtostderr=true:. ./hello_http.proto

Note that it is necessary to compile the two proto files in the Google/api, and specify the introduction package name when compiling Hello_http.proto, and finally use Grpc-gateway to compile the generated hello_http_pb.gw.go file, which is used for the protocol conversion, View the file to see the generated HTTP handler, handle the route defined above "Example/echo" to receive the post parameters, call the Hellohttp Service client Request GRPC service and respond to the results.

Server/main.go

Package Mainimport ("Crypto/tls" "FMT" "Io/ioutil" "Log" "Net" "Net/http" "Strings" "github.com/g Rpc-ecosystem/grpc-gateway/runtime "Golang.org/x/net/context" "Google.golang.org/grpc" PB "Git.vodjk.com/go-grpc /example/proto "" Google.golang.org/grpc/credentials "" Google.golang.org/grpc/grpclog ")// Define Hellohttpservice and implement the agreed interface type Hellohttpservice struct{}//hellohttpservice ... var hellohttpservice = Hellohttpservice{}func (H hellohttpservice) SayHello (CTX context. Context, in *PB. Hellohttprequest) (*PB. Hellohttpreply, error) {resp: = new (Pb). hellohttpreply) resp. Message = "Hello" + in.    Name + "." Return resp, nil}//Grpchandlerfunc examines the request protocol and returns the HTTP Handlerfunc grpchandlerfunc (grpcserver *grpc. Server, Otherhandler http. Handler) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http.        Request) {//TODO (Tamird): Point to merged grpc code rather than a PR. This is a partial recreation of GRPC ' s internal checks https://github.com/grpc/grpc-go/pull/514/files#diff-95e9a25b738459a2d3030e1e6fa2a718R61 if r.protomajor = = 2 &amp ;& strings.            Contains (R.header.get ("Content-type"), "Application/grpc") {grpcserver.servehttp (W, R)} else { Otherhandler.servehttp (W, R)})}func main () {endpoint: = "127.0.0.1:50052"//instantiation standard GRPC Server C Reds, err: = credentials. Newservertlsfromfile (".. /.. /keys/server.pem ",". /.. /keys/server.key ") if err! = Nil {grpclog. Fatalf ("Failed to generate credentials%v", err)} conn, _: = Net. Listen ("TCP", endpoint) Grpcserver: = Grpc. NewServer (GRPC. Creds (creds)) PB. Registerhellohttpserver (Grpcserver, Hellohttpservice)//HTTP-GRPC Gateway CTX: = context. Background () ctx, Cancel: = context. Withcancel (CTX) defer cancel () dcreds, err: = credentials. Newclienttlsfromfile (".. /.. /keys/server.pem "," server name ") If err! = Nil {grpclog. Fatalf ("Failed to create TLS credentials%V ", Err)} dopts: = []grpc. Dialoption{grpc. Withtransportcredentials (Dcreds)} Gwmux: = Runtime. Newservemux () Err = PB. Registerhellohttphandlerfromendpoint (CTX, Gwmux, endpoint, dopts) if err! = Nil {fmt. Printf ("Serve:%v\n", err) return} MUX: = http. Newservemux () Mux. Handle ("/", Gwmux) if err! = Nil {panic (ERR)}//Turn on HTTP Service cert, _: = Ioutil. ReadFile (".. /.. /keys/server.pem ") Key, _: = Ioutil. ReadFile (".. /.. /keys/server.key ") var demokeypair *tls. Certificate pair, Err: = TLS. X509keypair (cert, key) if err! = Nil {panic (err)} Demokeypair = &pair srv: = &http. server{Addr:endpoint, Handler:grpchandlerfunc (Grpcserver, MUX), Tlsconfig: &tls. config{certificates: []tls. Certificate{*demokeypair},},} FMT. Printf ("Grpc and HTTPS on port:%d\n", 50052) Err = srv. Serve (TLS. Newlistener (conn, srv. Tlsconfig)) If err! = Nil {log. Fatal ("LIstenandserve: ", Err)} return} 

All right, that's a big lump. The core is to open an HTTP server, check whether the request is GRPC or HTTP after receiving the request, and then decide whether it is handled directly by the GRPC service or forwarded to the gateway. The grpcHandlerFunc function is responsible for processing the decision with which handler to process the request, this method is directly copied to use, the original note that they also copy from elsewhere. Thanks to the contributors.

Basic Flow:

    • Instantiating standard GRPC Server

    • Registering GRPC server with the gateway

    • Turn on HTTP service, handler assign to Grpchandlerfunc method

Note: HTTPS must be turned on

Run results

Open service:

# hello-http-2/servergo run main.go> grpc and https on port: 50052    

Call the GRPC client:

# hello-http-2/clientgo run main.go> Hello gRPC.

Request https:

curl -X POST -k https://localhost:50052/example/echo -d '{"name": "gRPC-HTTP is working!"}'> {"message":"Hello gRPC-HTTP is working!."}

Why is hello-http-2, because 1 is an incomplete implementation posture, can not use HTTPS, but need to open GRPC Service and HTTP service separately, here do not explain.

Reference

Sample code for this series

    • Go-grpc-example

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.