在go的微服務(wù)架構(gòu)中
type Reg struct { Host string Port int Client consul.Client } func MakeReg (host string , port int) (*Reg , error) { reg := api.DefaultConfig() reg.Address = host + ":" + strconv.Itoa(port) apiclient , err = api.NewClient(reg) if err != nil { return nil , err } client := consul.NewClient(apiclient) return Reg{Host : host , Port : port ,Client : client} , nil } func (r Reg) Resiter (servicename , tag , host , seviceid ,checkinter ,healthcheckhttp ,deregisterafter string , port int) bool { congig := api.AgentServiceRegistration{ Port : port , Address : host , Name := servicename, ID := serviceid, Ckeck : api.AgentServiceCheck{ Interval : checkinter, HTTP : "http://" + host + ":" + healthcheckhttp , DeregisterCriticalServiceAfter : deregisterafter, } } if err := r.Client.Register(config) ; err != nil { fmt.Println(err) return false } return true } func (r Reg) Deregister (serviceid string) bool { dreg := api.AgentServiceRegistration{ID : serviceid} if err != r.Client.Deregister(config) ; err != nil { fmt.Println(err) return false } return true } func (r Reg) discover (servicename , tag string ,passingonly bool) ( []*api.ServiceEntry ,error ) { if entries ,_ ,err := r.Client.Service(servicename , tag , passingonly , nil) ;err != nil { return nil ,err }else{ return entries , nil } }
補(bǔ)充:go-kit 與 grpc 結(jié)合實(shí)現(xiàn)注冊(cè)發(fā)現(xiàn)與負(fù)載均衡
grpc提供了簡(jiǎn)單的負(fù)載均衡,需要自己實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)resolve。我們既然要使用go-kit來(lái)治理微服務(wù),那么我們就使用go-kit的注冊(cè)發(fā)現(xiàn)、負(fù)載均衡機(jī)制。
go-kit官方【stringsvc3】例子中使用的負(fù)載均衡方案是通過(guò)服務(wù)端轉(zhuǎn)發(fā)進(jìn)行,翻找下源碼go-kit的服務(wù)注冊(cè)發(fā)現(xiàn)、負(fù)載均衡在【sd】包中。下面我們介紹怎么通過(guò)go-kit進(jìn)行客戶端負(fù)載均衡。
1、 etcd
2、 consul
3、 eureka
4、 zookeeper
1、 random[隨機(jī)]
2、 roundRobin[輪詢]
只需實(shí)現(xiàn)Balancer接口,我們可以很容易的增加其它負(fù)載均衡機(jī)制
type Balancer interface { Endpoint() (endpoint.Endpoint, error) }
etcd和zookeeper類似是一個(gè)高可用、強(qiáng)一致性的存儲(chǔ)倉(cāng)庫(kù),擁有服務(wù)發(fā)現(xiàn)功能。 我們就通過(guò)go-kit提供的etcd包來(lái)實(shí)現(xiàn)服務(wù)注冊(cè)發(fā)現(xiàn)
1、連接注冊(cè)中心
2、注冊(cè)當(dāng)前服務(wù)
var ( //etcd服務(wù)地址 etcdServer = "127.0.0.1:2379" //服務(wù)的信息目錄 prefix = "/services/book/" //當(dāng)前啟動(dòng)服務(wù)實(shí)例的地址 instance = "127.0.0.1:50052" //服務(wù)實(shí)例注冊(cè)的路徑 key = prefix + instance //服務(wù)實(shí)例注冊(cè)的val value = instance ctx = context.Background() //服務(wù)監(jiān)聽地址 serviceAddress = ":50052" ) //etcd的連接參數(shù) options := etcdv3.ClientOptions{ DialTimeout: time.Second * 3, DialKeepAlive: time.Second * 3, } //創(chuàng)建etcd連接 client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options) if err != nil { panic(err) } // 創(chuàng)建注冊(cè)器 registrar := etcdv3.NewRegistrar(client, etcdv3.Service{ Key: key, Value: value, }, log.NewNopLogger()) // 注冊(cè)器啟動(dòng)注冊(cè) registrar.Register()
package main import ( "grpc-test/pb" "context" grpc_transport "github.com/go-kit/kit/transport/grpc" "github.com/go-kit/kit/endpoint" "google.golang.org/grpc" "net" "github.com/go-kit/kit/sd/etcdv3" "github.com/go-kit/kit/log" "time" ) type BookServer struct { bookListHandler grpc_transport.Handler bookInfoHandler grpc_transport.Handler } //通過(guò)grpc調(diào)用GetBookInfo時(shí),GetBookInfo只做數(shù)據(jù)透?jìng)? 調(diào)用BookServer中對(duì)應(yīng)Handler.ServeGRPC轉(zhuǎn)交給go-kit處理 func (s *BookServer) GetBookInfo(ctx context.Context, in *book.BookInfoParams) (*book.BookInfo, error) { _, rsp, err := s.bookInfoHandler.ServeGRPC(ctx, in) if err != nil { return nil, err } return rsp.(*book.BookInfo),err } //通過(guò)grpc調(diào)用GetBookList時(shí),GetBookList只做數(shù)據(jù)透?jìng)? 調(diào)用BookServer中對(duì)應(yīng)Handler.ServeGRPC轉(zhuǎn)交給go-kit處理 func (s *BookServer) GetBookList(ctx context.Context, in *book.BookListParams) (*book.BookList, error) { _, rsp, err := s.bookListHandler.ServeGRPC(ctx, in) if err != nil { return nil, err } return rsp.(*book.BookList),err } //創(chuàng)建bookList的EndPoint func makeGetBookListEndpoint() endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { //請(qǐng)求列表時(shí)返回 書籍列表 bl := new(book.BookList) bl.BookList = append(bl.BookList, book.BookInfo{BookId:1,BookName:"21天精通php"}) bl.BookList = append(bl.BookList, book.BookInfo{BookId:2,BookName:"21天精通java"}) return bl,nil } } //創(chuàng)建bookInfo的EndPoint func makeGetBookInfoEndpoint() endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { //請(qǐng)求詳情時(shí)返回 書籍信息 req := request.(*book.BookInfoParams) b := new(book.BookInfo) b.BookId = req.BookId b.BookName = "21天精通php" return b,nil } } func decodeRequest(_ context.Context, req interface{}) (interface{}, error) { return req, nil } func encodeResponse(_ context.Context, rsp interface{}) (interface{}, error) { return rsp, nil } func main() { var ( //etcd服務(wù)地址 etcdServer = "127.0.0.1:2379" //服務(wù)的信息目錄 prefix = "/services/book/" //當(dāng)前啟動(dòng)服務(wù)實(shí)例的地址 instance = "127.0.0.1:50052" //服務(wù)實(shí)例注冊(cè)的路徑 key = prefix + instance //服務(wù)實(shí)例注冊(cè)的val value = instance ctx = context.Background() //服務(wù)監(jiān)聽地址 serviceAddress = ":50052" ) //etcd的連接參數(shù) options := etcdv3.ClientOptions{ DialTimeout: time.Second * 3, DialKeepAlive: time.Second * 3, } //創(chuàng)建etcd連接 client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options) if err != nil { panic(err) } // 創(chuàng)建注冊(cè)器 registrar := etcdv3.NewRegistrar(client, etcdv3.Service{ Key: key, Value: value, }, log.NewNopLogger()) // 注冊(cè)器啟動(dòng)注冊(cè) registrar.Register() bookServer := new(BookServer) bookListHandler := grpc_transport.NewServer( makeGetBookListEndpoint(), decodeRequest, encodeResponse, ) bookServer.bookListHandler = bookListHandler bookInfoHandler := grpc_transport.NewServer( makeGetBookInfoEndpoint(), decodeRequest, encodeResponse, ) bookServer.bookInfoHandler = bookInfoHandler ls, _ := net.Listen("tcp", serviceAddress) gs := grpc.NewServer(grpc.UnaryInterceptor(grpc_transport.Interceptor)) book.RegisterBookServiceServer(gs, bookServer) gs.Serve(ls) }
1、 連接注冊(cè)中心
2、 獲取提供的服務(wù)
3、 監(jiān)聽服務(wù)目錄變化,目錄變化更新本地緩存
4、 創(chuàng)建負(fù)載均衡器
5、 獲取請(qǐng)求的 endPoint
package main import ( "context" "github.com/go-kit/kit/sd/etcdv3" "time" "github.com/go-kit/kit/sd" "github.com/go-kit/kit/log" "github.com/go-kit/kit/endpoint" "io" "github.com/go-kit/kit/sd/lb" "grpc-test/pb" "fmt" "google.golang.org/grpc" ) func main() { var ( //注冊(cè)中心地址 etcdServer = "127.0.0.1:2379" //監(jiān)聽的服務(wù)前綴 prefix = "/services/book/" ctx = context.Background() ) options := etcdv3.ClientOptions{ DialTimeout: time.Second * 3, DialKeepAlive: time.Second * 3, } //連接注冊(cè)中心 client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options) if err != nil { panic(err) } logger := log.NewNopLogger() //創(chuàng)建實(shí)例管理器, 此管理器會(huì)Watch監(jiān)聽etc中prefix的目錄變化更新緩存的服務(wù)實(shí)例數(shù)據(jù) instancer, err := etcdv3.NewInstancer(client, prefix, logger) if err != nil { panic(err) } //創(chuàng)建端點(diǎn)管理器, 此管理器根據(jù)Factory和監(jiān)聽的到實(shí)例創(chuàng)建endPoint并訂閱instancer的變化動(dòng)態(tài)更新Factory創(chuàng)建的endPoint endpointer := sd.NewEndpointer(instancer, reqFactory, logger) //創(chuàng)建負(fù)載均衡器 balancer := lb.NewRoundRobin(endpointer) /** 我們可以通過(guò)負(fù)載均衡器直接獲取請(qǐng)求的endPoint,發(fā)起請(qǐng)求 reqEndPoint,_ := balancer.Endpoint() */ /** 也可以通過(guò)retry定義嘗試次數(shù)進(jìn)行請(qǐng)求 */ reqEndPoint := lb.Retry(3, 3*time.Second, balancer) //現(xiàn)在我們可以通過(guò) endPoint 發(fā)起請(qǐng)求了 req := struct{}{} if _, err = reqEndPoint(ctx, req); err != nil { panic(err) } } //通過(guò)傳入的 實(shí)例地址 創(chuàng)建對(duì)應(yīng)的請(qǐng)求endPoint func reqFactory(instanceAddr string) (endpoint.Endpoint, io.Closer, error) { return func(ctx context.Context, request interface{}) (interface{}, error) { fmt.Println("請(qǐng)求服務(wù): ", instanceAddr) conn, err := grpc.Dial(instanceAddr, grpc.WithInsecure()) if err != nil { fmt.Println(err) panic("connect error") } defer conn.Close() bookClient := book.NewBookServiceClient(conn) bi,_:=bookClient.GetBookInfo(context.Background(),book.BookInfoParams{BookId:1}) fmt.Println("獲取書籍詳情") fmt.Println("bookId: 1", " => ", "bookName:", bi.BookName) bl,_ := bookClient.GetBookList(context.Background(), book.BookListParams{Page:1, Limit:10}) fmt.Println("獲取書籍列表") for _,b := range bl.BookList { fmt.Println("bookId:", b.BookId, " => ", "bookName:", b.BookName) } return nil,nil },nil,nil }
請(qǐng)求服務(wù): 127.0.0.1:50052 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java
1、 修改server的注冊(cè)監(jiān)聽端口,啟動(dòng)多個(gè)server
instance = "127.0.0.1:50052" serviceAddress = ":50052"
2、client發(fā)起多次請(qǐng)求
req := struct{}{} for i := 1; i = 8; i++ { if _, err = reqEndPoint(ctx, req); err != nil { panic(err) } }
通過(guò)返回結(jié)果中記錄的請(qǐng)求地址,我們可以看到已經(jīng)按照輪詢的方式請(qǐng)求不同的微服務(wù)實(shí)例。
請(qǐng)求服務(wù): 127.0.0.1:50051 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java 請(qǐng)求服務(wù): 127.0.0.1:50052 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java 請(qǐng)求服務(wù): 127.0.0.1:50051 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java 請(qǐng)求服務(wù): 127.0.0.1:50052 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java 請(qǐng)求服務(wù): 127.0.0.1:50051 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java 請(qǐng)求服務(wù): 127.0.0.1:50052 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java 請(qǐng)求服務(wù): 127.0.0.1:50051 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java 請(qǐng)求服務(wù): 127.0.0.1:50052 獲取書籍詳情 bookId: 1 => bookName: 21天精通php 獲取書籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java Process finished with exit code 0
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
標(biāo)簽:梅河口 銅川 重慶 汕頭 欽州 雞西 吐魯番 蘭州
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《利用go-kit組件進(jìn)行服務(wù)注冊(cè)與發(fā)現(xiàn)和健康檢查的操作》,本文關(guān)鍵詞 利用,go-kit,組件,進(jìn)行,服務(wù),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。