Go语言中文网,致力于每日分享编码、开源等知识,欢迎关注我,会有意想不到的收获!
这节将开始编写一个复杂的Hello World,涉及到许多的知识,建议大家认真思考其中的概念
需求
由于本实践偏向Grpc+Grpc Gateway的方面,我们的需求是同一个服务端支持Rpc和Restful Api,那么就意味着http2、TLS等等的应用,功能方面就是一个服务端能够接受来自grpc和Restful Api的请求并响应
一、初始化目录
我们先在$GOPATH中新建grpc-hello-world文件夹,我们项目的初始目录目录如下:
grpc-hello-world/├── certs├── client├── cmd├── pkg├── proto│ ├── google│ │ └── api└── server
- certs:证书凭证
- client:客户端
- cmd:命令行
- pkg:第三方公共模块
- proto:protobuf的一些相关文件(含.proto、pb.go、.pb.gw.go),google/api中用于存放annotations.proto、http.proto
- server:服务端
二、制作证书
在服务端支持Rpc和Restful Api,需要用到TLS,因此我们要先制作证书
进入certs目录,生成TLS所需的公钥密钥文件
私钥
openssl genrsa -out server.key 2048openssl ecparam -genkey -name secp384r1 -out server.key
- openssl genrsa:生成RSA私钥,命令的最后一个参数,将指定生成密钥的位数,如果没有指定,默认512
- openssl ecparam:生成ECC私钥,命令为椭圆曲线密钥参数生成及操作,本文中ECC曲线选择的是secp384r1
自签名公钥
openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650
- openssl req:生成自签名证书,-new指生成证书请求、-sha256指使用sha256加密、-key指定私钥文件、-x509指输出证书、-days 3650为有效期,此后则输入证书拥有者信息
填写信息
Country Name (2 letter code) [XX]:State or Province Name (full name) []:Locality Name (eg, city) [Default City]:Organization Name (eg, company) [Default Company Ltd]:Organizational Unit Name (eg, section) []:Common Name (eg, your name or your server's hostname) []:grpc server nameEmail Address []:
三、proto
编写
1、 google.api
我们看到proto目录中有google/api目录,它用到了google官方提供的两个api描述文件,主要是针对grpc-gateway的http转换提供支持,定义了Protocol Buffer所扩展的HTTP Option
annotations.proto文件:
http.proto文件:
- hello.proto
这一小节将编写Demo的.proto文件,我们在proto目录下新建hello.proto文件,写入文件内容:
在hello.proto文件中,引用了google/api/annotations.proto,达到支持HTTP Option的效果
- 定义了一个serviceRPC服务HelloWorld,在其内部定义了一个HTTP Option的POST方法,HTTP响应路径为/hello_world
- 定义message类型HelloWorldRequest、HelloWorldResponse,用于响应请求和返回结果
编译
在编写完.proto文件后,我们需要对其进行编译,就能够在server中使用
进入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.proto为hello_http.pb.protoprotoc -I . --go_out=plugins=grpc,Mgoogle/api/annotations.proto=grpc-hello-world/proto/google/api:. ./hello.proto#编译hello_http.proto为hello_http.pb.gw.protoprotoc --grpc-gateway_out=logtostderr=true:. ./hello.proto
执行完毕后将生成hello.pb.go和hello.gw.pb.go,分别针对grpc和grpc-gateway的功能支持
四、命令行模块 cmd
介绍
这一小节我们编写命令行模块,为什么要独立出来呢,是为了将cmd和server两者解耦,避免混淆在一起。
我们采用 Cobra 来完成这项功能,Cobra既是创建强大的现代CLI应用程序的库,也是生成应用程序和命令文件的程序。提供了以下功能:
- 简易的子命令行模式
- 完全兼容posix的命令行模式(包括短和长版本)
- 嵌套的子命令
- 全局、本地和级联flags
- 使用Cobra很容易的生成应用程序和命令,使用cobra create appname和cobra add cmdname
- 智能提示
- 自动生成commands和flags的帮助信息
- 自动生成详细的help信息-h,--help等等
- 自动生成的bash自动完成功能
- 为应用程序自动生成手册
- 命令别名
- 定义您自己的帮助、用法等的灵活性。
- 可选与viper紧密集成的apps
编写server
在编写cmd时需要先用server进行测试关联,因此这一步我们先写server.go用于测试
在server模块下 新建server.go文件,写入测试内容:
编写cmd
在cmd模块下 新建root.go文件,写入内容:
新建server.go文件,写入内容:
package cmdimport ( "log" "github.com/spf13/cobra" "grpc-hello-world/server")var serverCmd = &cobra.Command{ Use: "server