一个简单的Golang RPC服务

一个简单的Golang RPC服务

远航
2022-11-24 / 0 评论 / 150 阅读 / 正在检测是否收录...
先创建一个带服务的.proto文件
syntax = "proto3"; //指定版本

package goProtocol; //指定包名
option go_package = "./;goProtocol";

// 该文件依赖于插件来生成服务代码。
option cc_generic_services = true;
option java_generic_services = true;
option py_generic_services = true;

/**
go 比较特殊
option go_package = "aaa;bbb";

aaa 表示生成的go文件的存放地址,会自动生成目录的。
bbb 表示生成的go文件所属的包名

*/

/**
   服务名: Speak,
   其中只有 名为“SayOk”的一个RPC服务,
   输入是 Request格式的数据流, 输出是 Response 格式的数据流
*/
service Speak {
  rpc SayOk(Request) returns (Response) {}
}

// 请求数据 Request格式定义
message Request {
  string input = 1;
}

// 响应数据Response格式定义
message Response {
  string output = 1;
}
生成对应服务和结构代码
// 生成数据结构
protoc --go_out=. *.proto
// 生成服务
protoc --go_out=plugins=grpc:. *.proto // 旧版
// 可能会报错
// --go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC

// See https://grpc.io/docs/languages/go/quickstart/#regenerate-grpc-code for more information.
// 因为版本更新了导致的,换
protoc --go-grpc_out=. *.proto // 新版
编写服务端代码
package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "log"
    "net"
    "换成你自己的包名/goProtocol"
)

func main() {
    StartServer()
}

func StartServer() {
    log.Println("启动服务端...")
    server := grpc.NewServer()
    // 注册 ToolBoxServer
    goProtocol.RegisterSpeakServer(server, &Speak{})
    // 监听3000端口
    address, err := net.Listen("tcp", ":3000")
    if err != nil {
        panic(err)
    }
    if err := server.Serve(address); err != nil {
        panic(err)
    }
}

// Speak 服务端
type Speak struct {
    goProtocol.UnimplementedSpeakServer
}

// SayOk 实现了 SpeakServer 接口中定义的 SayOk 方法
func (*Speak) SayOk(ctx context.Context, req *goProtocol.Request) (*goProtocol.Response, error) {
    fmt.Println("调用了SayOk")
    return &goProtocol.Response{
        Output: "调用了SayOk:" + req.Input,
    }, nil
}
编写客户端代码
package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "log"
    "net/http"
    "换成你自己的包名/goProtocol"
)


func main() {
    // 编写http请求处理函数
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        res := StartClient("127.0.0.1:3000")
        fmt.Println(res)
        // 返回一个字符串到网页
        w.Write([]byte(res))
    })
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
}

func StartClient(target string) string {
    // 创建连接
    conn, err := grpc.Dial(target, grpc.WithInsecure())
    if err != nil {
        log.Printf("连接失败: [%v] ", err)
        return ""
    }
    defer conn.Close()
    // 声明客户端
    client := goProtocol.NewSpeakClient(conn)
    // 声明 context
    ctx := context.Background()
    // 启动一个 goroutine 接收命令行输入的指令
    //var reply string // 接收返回值
    res, err := client.SayOk(ctx, &goProtocol.Request{Input: "调用传递参数:aa"})
    if err != nil {
        fmt.Println(err)
        return ""
    }
    fmt.Println(res)
    return res.Output
}

开启服务端
go run server.go
运行客户端端
go run client.go
服务端控制台输出结果
2022/11/24 17:51:39 启动服务端...
调用了SayOk
客户端API调试工具返回结果

iShot_2022-11-25_14.36.05.png

微服务相关文章

一个简单的微服务系统架构笔记

1

评论 (0)

取消