上上篇我們講了如何搞etcd的服務註冊中心功能,程式碼還會比較臃腫的,因為剛開始寫麻,後期絕對會進行封裝的,昨晚的時間進行了一次簡單的封裝
上上篇當中的server.go裡面的程式碼替換為:
更名為serverone.go:
package main
import (
"flag"
"fmt"
"google.golang.org/grpc"
demo "grpclb/rpcfile"
"grpclb/rpcserver"
"grpclb/rpcserverimpl"
)
var (
port1 = flag.Int("pp",50002,"server port1")
)
const (
key1 string = "vector_rpc_server1"
)
func main() {
//解析標籤
flag.Parse()
//etcd服務註冊中心需要用到的配置
config := &rpcserver.RpcServiceConfig{
//etcd當中key的字首
Key: key1,
//rpc監聽的地址和埠號
ServerAddress: fmt.Sprintf("127.0.0.1:%d", *port1),
//etcd叢集地址
Endpoints: []string{"127.0.0.1:2379"},
}
//註冊etcd中心以及grpc服務
if server, err := rpcserver.NewRpcService(config, func(server1 *grpc.Server) {
demo.RegisterDemoServiceServer(server1, &rpcserverimpl.DemoServiceServerImpl{})
});err == nil {
if err := server.Run();err != nil {
panic(err)
}
}
}
重點是這裡的rpcserver.go 建立一個新檔案,封裝的東東都在這裡面哦:
package rpcserver
import (
"go.etcd.io/etcd/clientv3"
"google.golang.org/grpc"
"grpclb/register"
"log"
"net"
"os"
"os/signal"
"syscall"
)
type (
//函式作為值來傳遞 型別是自定義的型別RpcServiceFunc 傳入的值是grpc.NewServer()指標型別*grpc.Server
RpcServiceFunc func(server *grpc.Server)
//定義一個結構體來承裝register和註冊中心和傳遞過來的函式 這個函式是幹嘛的往下看
RpcService struct{
//register註冊中心
register *register.Register
//作為值傳遞過來的函式
//demo.RegisterDemoServiceServer(server1, &rpcserverimpl.DemoServiceServerImpl{})
//上邊RegisterDemoServiceServer是形成的 pb.go檔案裡面的哦 註冊服務 第二個引數是你實現介面的struct結構體
//總的來說是為了實現註冊rpc服務的一部分
rpcServiceFunc RpcServiceFunc
}
//將一些配置搞到裡面去 etcd服務註冊中心用到的比如key的字首 rpc服務地址 etcd叢集地址配置
RpcServiceConfig struct {
Key string
ServerAddress string
Endpoints []string
}
)
//例項化各類操作
func NewRpcService(conf *RpcServiceConfig,rpcServiceFun RpcServiceFunc) (*RpcService,error){
//連結etcd服務
client3,err := clientv3.New(
clientv3.Config{
Endpoints: conf.Endpoints,//etcd叢集地址配置
//你還可以設定更過的引數 如果開啟了auth驗證 也可以配置username和password
},
)
if err != nil {
return nil,err
}
//返回的結構體當中有 註冊好的Register註冊中心結構體
return &RpcService{
//例項化服務註冊中心 方便接下來的呼叫
register:register.NewRegister(conf.Key, client3, conf.ServerAddress),
//返回函式
rpcServiceFunc:rpcServiceFun,
},nil
}
//執行etcd服務註冊中心和監聽rpc服務
func(s *RpcService) Run() error {
//監聽rpc服務
listen, err := net.Listen("tcp", s.register.GetServiceAddress())
if err != nil {
return err
}
log.Printf("Rpc server listen at:%s:",s.register.GetServiceAddress())
//etcd服務註冊中心 這裡真正的調起服務註冊中心的reg()註冊方法
s.register.Reg()
//etcd的善後工作
//我們的rpc服務有沒有掛掉 伺服器有沒有當機......
//所以我們需要建立一個通道 告訴etcd我的服務掛掉了 伺服器當機了...... 趕緊把我的合同解約刪掉key 好讓接下里的請求不再調取我的rpc服務
//所以 我們要接收來自系統的訊號
s.deadNotify()
//grpc 例項化grpc服務 返回的是 *grpc.Server
server := grpc.NewServer()
//grpc s.rpcServiceFunc()其實就是在呼叫傳遞進來的函式 函式要求傳入的是 *grpc.Server 所以就把grpc.NewServer()傳遞進去就可以啦
//這樣就真的將我們實現的DemoServiceServerImpl註冊進到了grpc服務當中 就等著下邊啟動就完事了
s.rpcServiceFunc(server)
//server.Serve(listen) 啟動grpc服務 進行實時監聽 程式不會中斷!
if err := server.Serve(listen);err != nil {
return err
}
return nil
}
//etcd的善後工作
//我們的rpc服務有沒有掛掉 伺服器有沒有當機......
//所以我們需要建立一個通道 告訴etcd我的服務掛掉了 伺服器當機了...... 趕緊把我的合同解約刪掉key 好讓接下里的請求不再調取我的rpc服務
//所以 我們要接收來自系統的訊號
func (s *RpcService) deadNotify() error {
ch := make(chan os.Signal,1)
//接收系統訊號寫到ch管道當中去
signal.Notify(ch,syscall.SIGTERM,syscall.SIGINT,syscall.SIGKILL,syscall.SIGHUP,syscall.SIGQUIT)
go func() {
sign := <-ch
log.Printf("signal.notify %v",sign)
//服務停掉之後 刪除掉註冊進etcd中心的key 我的服務都停了還留著你幹啥用呢!
s.register.UnReg()
}()
return nil
}
其他的涉及到的檔案跟上上篇保持一致即可!
這樣就實現了完美的一次封裝!
每次呼叫也不用寫這麼臃腫的程式碼去呼叫了!
如果看著費勁 那就請把上上篇的程式碼和今天的程式碼貼到你本地 一點一點實現 只要想實現就一定能實現!
本作品採用《CC 協議》,轉載必須註明作者和本文連結