go grpc demo

 

1.安装相关包

下载protoc,查看 protoc 版本
protoc --version 

设置代理
set GOPROXY=https://goproxy.cn

安装protobuf工具包

go get google.golang.org/protobuf

安装 goalng 的proto编译支持

go install google.golang.org/protobuf/cmd/protoc-gen-go

安装grpc

go get google.golang.org/grpc

go get -d google.golang.org/grpc/cmd/protoc-gen-go-grpc

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc

2.创建项目

模拟微服务开发,在某个空文件夹下建立两个文件夹
分别为 client 和 server

 

 

 

3.创建 proto 文件

proto 文件是微服务交互的基本
proto的语法见官方:https://developers.google.com/protocol-buffers/docs/proto3?hl=zh-cn
这里简单写一个示例(spider.proto)

syntax = "proto3";  // 协议为proto3

package spider; // 包名

option go_package ="./spider";
//protoc --go_out=./ ./spider.proto
//protoc --go_out=plugins=grpc:./ ./spider.proto

// 发送请求
message SendAddress {
// 发送的参数字段
// 参数类型 参数名 标识号(不可重复)
string address = 1; // 要请求的地址
string method = 2; // 请求方式
}

// 返回响应
message GetResponse {
// 接收的参数字段
// 参数类型 参数名 标识号
int32 httpCode = 1; // http状态码
string response = 2; // 返回体
}

// 定义服务,可定义多个服务,每个服务可多个接口
service Spider {
// rpc请求 请求的函数 (发送请求参数) returns (返回响应的参数)
rpc GetAddressResponse (SendAddress) returns (GetResponse);
}

4.生成 .bp.go 文件

protoc --go_out=./ ./spider.proto
protoc --go_out=plugins=grpc:./ ./spider.proto

运行后会在spider目录下生成 spider.pb.go 文件
该文件是 server 和 client 的通信协议,勿动

5.编写 server 端

编写 main.go 文件

package main

import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"io/ioutil"
"net"
"net/http"
"testgrpc/grpc/spider"
)
const (
// Address 监听地址
Address string = "localhost:8080"
// Method 通信方法
Method string = "tcp"
)

type server struct{
spider.UnimplementedSpiderServer
}

// 接收client端的请求,函数名需保持一致
// ctx参数必传
// 参数二为自定义的参数,需从pb文件导入,因此pb文件必须可导入,文件放哪里随意
// 返回值同参数二,为pb文件的返回结构体指针
func (s *server) GetAddressResponse(ctx context.Context, a *spider.SendAddress) (*spider.GetResponse, error) {
// 逻辑写在这里
switch a.Method {
case "get", "Get", "GET":
// 演示微服务用,故只写get示例
status, body, err := get(a.Address)
if err != nil {
return nil, err
}
res := spider.GetResponse{
HttpCode: int32(status),
Response: body,
}
return &res, nil
}
return nil, nil
}

func get(address string) (s int, r string, err error) {
// get请求
resp, err := http.Get(address)
if err != nil {
return
}
defer resp.Body.Close()
s = resp.StatusCode
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
r = string(body)
return
}

func main() {
// 监听本地端口
listener, err := net.Listen(Method, Address)
if err != nil {
return
}
s := grpc.NewServer() // 创建GRPC
spider.RegisterSpiderServer(s, &server{}) // 在GRPC服务端注册服务

reflection.Register(s) // 在GRPC服务器注册服务器反射服务
// Serve方法接收监听的端口,每到一个连接创建一个ServerTransport和server的grroutine
// 这个goroutine读取GRPC请求,调用已注册的处理程序进行响应
err = s.Serve(listener)
if err != nil {
return
}
}

6.编写 client 端

package main

import (
"context"
"google.golang.org/grpc"
"testgrpc/grpc/spider"
)

import "fmt"

const (
// Address server端地址
Address string = "localhost:8080"
)

func main() {
// 连接服务器
conn, err := grpc.Dial(Address, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()

// 连接GRPC
c := spider.NewSpiderClient(conn)
// 创建要发送的结构体
req := spider.SendAddress{
Address: "http://www.baidu.com",
Method: "get",
}
// 调用server的注册方法
r, err := c.GetAddressResponse(context.Background(), &req)
if err != nil {
fmt.Println(err)
return
}
// 打印返回值
fmt.Println(r)
}

7.运行

需要先启动 server 端监听端口,再启动 client 端向端口发送请求
我们运行后可看到结果已经正常返回并打印

posted @ 2021-07-27 16:45  selfim写博客  阅读(233)  评论(0编辑  收藏  举报