项目地址:https://github.com/yakaa/grpcx
grpc官网使用案例参考案例结合本框架分析:
func main() {
lis, err := net.Listen("tcp",fmt.Sprintf(":%d",9000))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
log.Println("UserService to listen:9000 success")
grpcServer := grpc.NewServer()
protoFiles_hello.RegisterUserServiceServer(grpcServer,&impl.UserService{})
grpcServer.Serve(lis)
}
主要函数, conf是一个配置文件 Endpoints是etcd的服务器地址,如果有多个集群可以使用,往后面追加地址
func Server(count int) {
conf := &config.ServiceConf{
EtcdAuth: config.EtcdAuth{},
Schema: "www.vector.com",
ServerName: "knowing",
Endpoints: []string{"127.0.0.1:2379"},
ServerAddress: ":20001",
}
demo := &RegionHandlerServer{ServerAddress: conf.ServerAddress}
rpcServer, err := grpcx.MustNewGrpcxServer(conf, func(server *grpc.Server) {
proto.RegisterRegionHandlerServer(server, demo)
})
if err != nil {
panic(err)
}
log.Fatal(rpcServer.Run())
}
grpc.MustNewGrpcxsServer函数
func(server *grpc.Server) { proto.RegisterRegionHandlerServer(server, demo) }
register: register.NewRegister( conf.Schema, //www.vector.com conf.ServerName, //knowing conf.ServerAddress, //192.168.1.2:20001 client3, //etcd3的client )
register参数的配置
func NewRegister(
schema string,
serverName string,
serverAddress string,
client3 *clientv3.Client,
) *Register {
return &Register{
schema: schema, //www.vector.com
serverName: serverName, //knowing
serverAddress: serverAddress, //192.168.1.2:20001
client3: client3,
interval: 3 * time.Second,
leaseTime: 6, //续租间隔
stop: make(chan bool, 1),
fullAddress: fmt.Sprintf("%s/%s/%x", schema, serverName, md5.Sum([]byte(serverAddress))), //www.vector.com/knowing/md5(192.168.1.2:20001)
}
}
func MustNewGrpcxServer(conf *config.ServiceConf, rpcServiceFunc GrpcxServiceFunc) (*GrpcxServer, error) {
client3, err := clientv3.New(
clientv3.Config{
Endpoints: conf.Endpoints,
Username: conf.UserName,
Password: conf.PassWord,
DialTimeout: config.GrpcxDialTimeout,
})
if nil != err {
return nil, err
}
address := strings.Split(conf.ServerAddress, colon)
if len(address) == 1 {
return nil, errors.New("ServerAddress must container :")
}
if strings.TrimSpace(address[0]) == "" {
address[0] = FindLocalAddress()
}
conf.ServerAddress = strings.Join(address, colon)
return &GrpcxServer{
register: register.NewRegister(
conf.Schema,
conf.ServerName,
conf.ServerAddress,
client3,
),
rpcServiceFunc: rpcServiceFunc,
}, nil
}
run函数就是常规的启动grpc服务器
og4g.InfoFormat是打印出ectd的key和 name 和rpc的服务器监听端口信息
s.register.Register看下面介绍
gprc.NewServer ,然后执行s.rpcServiceFunc函数,s.rpcServiceFunc实际就是proto.RegisterRegionHandlerServer(server, &RegionHandlerServer{ServerAddress: conf.ServerAddress}) 进行了常规的 rpc服务器启动操作
s.deadNotify看下面介绍
func (s *GrpcxServer) Run(serverOptions ...grpc.ServerOption) error {
listen, err := net.Listen("tcp", s.register.GetServerAddress())
if nil != err {
return err
}
log4g.InfoFormat(
"serverAddress [%s] of %s Rpc server has started and full key [%s]",
s.register.GetServerAddress(),
s.register.GetServerName(),
s.register.GetFullAddress(),
)
if err := s.register.Register(); err != nil {
return err
}
server := grpc.NewServer(serverOptions...)
s.rpcServiceFunc(server)
s.deadNotify()
if err := server.Serve(listen); nil != err {
return err
}
return nil
}
s.register.Register()函数 (主要作用就是把rpc服务器节点信息写入到etcd服务器中)
func (r *Register) Register() error {
ticker := time.NewTicker(r.interval)
go func() {
for {
//这里的if实际是 err != nil 的判断,首先先从etcd中获取r.fullAddress的节点信息
//如果获取不到就去包活
if getResp, err := r.client3.Get(context.Background(), r.fullAddress); err != nil {
log4g.Error(err)
} else if getResp.Count == 0 {
if err = r.withAlive(); err != nil {
log4g.Error(err)
}
}
//这个select是阻塞退出循环的作用 意思是3秒执行一次
select {
case <-ticker.C:
case <-r.stop:
return
}
}
}()
return nil
}
func (s *GrpcxServer) deadNotify() {
ch := make(chan os.Signal, 1) //
signal.Notify(ch, deadSignal...)
go func() {
log4g.InfoFormat(
"serverAddress [%s] of %s Rpc server has existed with got signal [%v] and full key [%s]",
s.register.GetServerAddress(),
s.register.GetServerName(),
<-ch,
s.register.GetFullAddress(),
)
if err := s.register.UnRegister(); err != nil {
log4g.InfoFormat(
"serverAddress [%s] of %s Rpc server UnRegister fail and err %+v and full key [%s]",
s.register.GetServerAddress(),
s.register.GetServerName(),
s.register.GetFullAddress(),
err,
s.register.GetFullAddress(),
)
}
os.Exit(1) //
}()
return
}
到这里整个server就正常运行起来了