我有一个放着很多测试程序的资料夹,每次要用新的套件或测试逻辑的时候, 为了要排除其他影响因素, 我会开一个最精简的main.go来测试, 这样可以先掌握好主要的项目, 然後再移到开发框架里面使用。
昨天定好了grpc spec, 今天就示范写一个最简短的gRPC server的样子。
首先, 开好main.go之後把spec import进来 coconut "[spec路径]/coconut/pb"
package main
import (
"context"
"fmt"
"net"
"os"
"os/signal"
"syscall"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
coconut "[spec路径]/coconut/pb"
)
在func main
注册 grpc server, 要先指定服务的port, net.Listen("tcp", ":8800")
带入port时要用:
+port
的方式带入
func main() {
var (
err error
shutdownObserver = make(chan os.Signal, 1)
)
sv := &server{}
// 监听指定port,服务会在该port执行
apiListener, err := net.Listen("tcp", ":8800")
if err != nil {
panic(err)
}
gs := grpc.NewServer(grpc.MaxRecvMsgSize(1024 * 1024 * 8))
coconut.RegisterCoconutServer(gs, sv)
// 在 gRPC 服务器上注册反射服务。
reflection.Register(gs)
go func(gs *grpc.Server, c chan<- os.Signal) {
err := gs.Serve(apiListener)
if err != nil {
shutdownObserver <- syscall.SIGINT
}
}(gs, shutdownObserver)
/** 监听信号
SIGHUP 终端控制进程结束(终端连接断开)
SIGINT 用户发送INTR字符(Ctrl+C)触发
SIGQUIT 用户发送QUIT字符(Ctrl+/)触发
SIGTERM 结束程序(可以被捕获、阻塞或忽略)
**/
signal.Notify(shutdownObserver, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
//阻塞直到有信号传入
s := <-shutdownObserver
fmt.Println(`Receive signal:`, s)
// 优雅停止GRPC服务
gs.GracefulStop()
}
grpc server如果只有注册服务是没有办法go build
成功的, 它需要先把gRPC各个接口依照spec开好
func (s *server) Ping(ctx context.Context, in *coconut.PingRequest) (r *coconut.Pong, err error) {
r = &coconut.Pong{
Pong: "Pong",
}
return r, err
}
func (s *server) UpdatePoints(ctx context.Context, in *coconut.PointsRequest) (r *coconut.RetPoints, err error) {
r = &coconut.RetPoints{}
return
}
func (s *server) GetPoints(ctx context.Context, in *coconut.GetPointsRequest) (r *coconut.RetPoints, err error) {
r = &coconut.RetPoints{}
return
}
接着执行 go build
之後, 启动 ./coconut
就可以透过 grpcurl
打到server
-> % grpcurl -plaintext -d '{}' localhost:8800 coconut.Coconut/Ping
{
"pong": "Pong"
}
这是最简短的grpc server, 有时候我要使用的grpc服务还没实作的时候我也会这样做一个简单的mock程序, protobuf的好处是有spec就可以自己mock, 这样不仅可以同步开发, 也可以在测试时排除外部服务的影响。
实际上开发的专案档案结构会复杂得多, 档案结构的部分就明天分享罗。
>>: Day15 - 动态 新增/删除 Collection 项目(三) - Tag Helper
有了建置 Image 的流程,和前後端分离的机制,接着我们就可以设定 CICD 的流水线来进行服务自...
前言 这是 Obsidian 使用教学 — 插件篇的第 1 篇文章,从这个章节开始要进入到进阶的主题...
接着来讲讲try catch 部分.... 一般来说是要避免程序因为出现错误讯息挂掉的处理方式......
在特定时间开放抢票的网站,常常会有流量爆炸的问题。这时候可以透过服务器的异步处理来解决。 让买票处理...
MyBatis 可以简单的使用注解或XML 的方式进行配置和对映,通过将引数对映到配置的SQL 形成...