一、go 语言编写 grpc 微服务实例

694 阅读2分钟
原文链接: hacpai.com

grpc

grpc跨平台微服务框架,但是缺少服务治理的功能,服务发现给出了架子需要自己实现。

go 包下载

go get -u google.golang.org/grpc

proto 工具下载

1、下载 idl 代码生成工具

repo1.maven.org/maven2/com/… protoc 放在环境变量的 path 中

2、下载生成 go 代码插件

go get -u github.com/golang/protobuf/protoc-gen-go

从 GoBin 目录中拷贝出来 protoc-gen-go,放在环境变量 path 中

IDL

IDL 语法,详细的请查看 Protobuf3 语言指南


例子

代码脚手架

1、编写 book.proto 文件

syntax = "proto3";  
  
// 请求书详情的参数结构  book_id 32 位整形  
message BookInfoParams {  
    int32 book_id = 1;  
}  

// 书详情信息的结构   book_name 字符串类型 
message BookInfo {  
    int32 book_id = 1;  
    string  book_name = 2;  
}  
  
// 请求书列表的参数结构  page、limit   32 位整形
message BookListParams {  
    int32 page = 1;  
    int32 limit = 2;  
}  

// 书列表的结构    BookInfo 结构数组
message BookList {  
    repeated BookInfo book_list = 1;  
}  
// 定义 获取书详情  和 书列表服务   入参出参分别为上面所定义的结构  
service BookService {  
    rpc GetBookInfo (BookInfoParams) returns (BookInfo) {}  
    rpc GetBookList (BookListParams) returns (BookList) {}}

2、生成对应语言 proto 代码

protoc --go_out=plugins=grpc:. book.proto

当前文件夹下会生成 book.pb.go 文件,也可以生成其它语言的代码

protoc --php_out=. book.proto

3、解决小冲突 gol 的 grpc 插件指定 context 路径 contextPkgPath = “golang.org/x/net/conte…"可能会与我们代码中的 context 冲突 把 book.proto 中 import"golang.org/x/net/conte…” 更改为 “context”

服务端代码

package main  
  
import (  
   "grpc-test/pb"  
   "net" "context" "google.golang.org/grpc"
)  
  
/**  
创建 BookServer 结构 实现 BookServiceServer 接口  
type BookServiceServer interface {GetBookInfo(context.Context, *BookInfoParams) (*BookInfo, error)
   GetBookList(context.Context, *BookListParams) (*BookList, error)
}  
*/
type BookServer struct {}  
func (s *BookServer) GetBookInfo(ctx context.Context, in *book.BookInfoParams) (*book.BookInfo, error) {  
   // 请求详情时返回 书籍信息  
   b := new(book.BookInfo)  
   b.BookId = in.BookId  
   b.BookName = "21 天精通 php"  
   return b,nil  
}  
  
func (s *BookServer) GetBookList(ctx context.Context, in *book.BookListParams) (*book.BookList, error) {  
   // 请求列表时返回 书籍列表  
   bl := new(book.BookList)  
   bl.BookList = append(bl.BookList, &book.BookInfo{BookId:1,BookName:"21 天精通 php"})  
   bl.BookList = append(bl.BookList, &book.BookInfo{BookId:2,BookName:"21 天精通 java"})  
   return bl,nil  
}  
  
func main() {  
   serviceAddress := ":50052"  
   bookServer := new(BookServer)  
   // 创建 tcp 监听  
   ls, _ := net.Listen("tcp", serviceAddress)  
   // 创建 grpc 服务  
   gs := grpc.NewServer()  
   // 注册 bookServer  
   book.RegisterBookServiceServer(gs, bookServer)  
   // 启动服务  
   gs.Serve(ls)  
}

客户端代码

package main  
  
import (  
   "fmt"  
   "grpc-test/pb" "google.golang.org/grpc" 
   "context"
)  
  
func main() {  
   serviceAddress := "127.0.0.1:50052"  
   conn, err := grpc.Dial(serviceAddress, grpc.WithInsecure())  
   if err != nil {  
      panic("connect error")  
   }  
   defer conn.Close()  
   bookClient := book.NewBookServiceClient(conn)  
   bi,_:=bookClient.GetBookInfo(context.Background(),&book.BookInfoParams{BookId:1})  
   fmt.Println("获取书籍详情")  
   fmt.Println("bookId: 1", "=>", "bookName:", bi.BookName)  
  
   bl,_ := bookClient.GetBookList(context.Background(), &book.BookListParams{Page:1, Limit:10})  
   fmt.Println("获取书籍列表")  
   for _,b := range bl.BookList {  
      fmt.Println("bookId:", b.BookId, "=>", "bookName:", b.BookName)  
   }  
}

启动测试

启动 server,client

GOROOT=D:\Go #gosetup
GOPATH=D:\go\gopath #gosetup
D:\Go\bin\go.exe build -i -o C:\Users\Administrator\AppData\Local\Temp\___17110go_build_main_go.exe D:/go/gopath/src/grpc-test/client/main.go #gosetup
D:\软件\GoLand\bin\runnerw.exe C:\Users\Administrator\AppData\Local\Temp\___17110go_build_main_go.exe #gosetup
获取书籍详情
bookId: 1  =>  bookName: 21天精通php
获取书籍列表
bookId: 1  =>  bookName: 21天精通php
bookId: 2  =>  bookName: 21天精通java

Process finished with exit code 0