server.go
package main import ( "github.com/gin-gonic/gin" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/web" "github.com/micro/go-micro/registry/consul" "time" ) func main() { consulReg := consul.NewRegistry( //新建一個consul注冊的地址,也就是我們consul服務啟動的機器ip+端口 registry.Addrs("127.0.0.1:8500"), ) ginRouter := gin.Default() ginRouter.Handle("GET", "/user", func(context *gin.Context) { context.String(200, "user api") }) ginRouter.Handle("GET", "/news", func(context *gin.Context) { context.String(200, "news api") }) v1Group := ginRouter.Group("/v1") { v1Group.Handle("POST", "/prods", func(context *gin.Context) { //rq := Helper.NewRequest() //context.bind(rq) //使用自定義的結構體解析post表單 context.JSON( 200, gin.H{ "data":2, }, ) }) } //其實下面這段代碼的意義就是啟動服務的同時把服務注冊進consul中,做的是服務發現 server := web.NewService( //go-micro很靈性的實現了注冊和反注冊,我們啟動后直接ctrl+c退出這個server,它會自動幫我們實現反注冊 web.Name("httpprodservice"), //注冊進consul服務中的service名字 web.Address(":8088"), //注冊進consul服務中的端口,也是這里我們gin的server地址 web.Handler(ginRouter), //web.Handler()返回一個Option,我們直接把ginRouter穿進去,就可以和gin完美的結合 web.Registry(consulReg), //注冊到哪個服務器傷的consul中 ) server.Init() //加了這句就可以使用命令行的形式去設置我們一些啟動的配置 server.Run() }
client.go
package main import ( "context" "github.com/micro/go-micro/client" "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/consul" myhttp "github.com/micro/go-plugins/client/http" "log" ) func callAPI(s selector.Selector) { myCli := myhttp.NewClient( client.Selector(s), client.ContentType("application/json"), //因為我們要調用的/v1/prods這個api返回的是json,要先規定好數據格式json(很重要,如果是其他的會報錯) ) //下面這句代碼封裝了一個請求(未發送) req := myCli.NewRequest("httpprodservice", "/v1/prods", map[string]string{})//這里最后一個參數是body,一般用於post請求的參數,因為我們這個api沒有參數,所以我隨便寫了map[string]string{} //從之前的圖可以看到我們的返回值是一個json,key-val為"data":[],所以我們的response要構建一個相同結構的,方便go-micro幫我們返回響應結構體map[string]int{"Size": 4},這里的key大小寫都可以,只要和request結構體該字段字母一樣就行入 abcd:3 Abcd:3 ABCD:3都可以 var resp map[string]interface{} log.Println("===req===") log.Println(req) log.Println("===context====") log.Println(context.Background()) err := myCli.Call(context.Background(), req, &resp) //發起請求調用,並返回結果 if err != nil { log.Fatal(err) } log.Println(resp) } func main() { consulReg:=consul.NewRegistry(func(options *registry.Options) { options.Addrs=[]string{ "127.0.0.1:8500", } }) mySelector := selector.NewSelector( selector.Registry(consulReg), selector.SetStrategy(selector.Random), //設置查詢策略,這里是輪詢 ) log.Println("===sel===") log.Println(mySelector) callAPI(mySelector) }
go run server.go --server_address :8001
go run client.go
結果客戶端報
{"id":"go.micro.client","code":500,"detail":"none available","status":"Internal Server Error"}
將consul換成etcd,發現也是報
{"id":"go.micro.client","code":500,"detail":"none available","status":"Internal Server Error"}
后來通過查看源碼 pkg\mod\github.com\micro\go-plugins\client\http@v0.0.0-20200119172437-4fe21aa238fd\http.go
大概在63行左右
// only get the things that are of mucp protocol selectOptions := append(opts.SelectOptions, selector.WithFilter( selector.FilterLabel("protocol", "http"), ))
會添加過濾器 pkg\mod\github.com\micro\go-micro@v1.8.1\client\selector\default.go 的
Select() 大概在56行
// apply the filters for _, filter := range sopts.Filters { services = filter(services) }
里面的進行過濾
查看 pkg\mod\github.com\micro\go-micro@v1.8.1\client\selector\filter.go
func FilterLabel(key, val string) 方法, key是protocol val是http
// FilterLabel is a label based Select Filter which will // only return services with the label specified. func FilterLabel(key, val string) Filter { return func(old []*registry.Service) []*registry.Service { var services []*registry.Service for _, service := range old { serv := new(registry.Service) var nodes []*registry.Node for _, node := range service.Nodes { if node.Metadata == nil { continue } if node.Metadata[key] == val { nodes = append(nodes, node) } } // only add service if there's some nodes if len(nodes) > 0 { // copy *serv = *service serv.Nodes = nodes services = append(services, serv) } } return services } }
發現是
node.Metadata[key] == val
解決方法在server.go 的web服務注冊添加Metadata信息
如
//其實下面這段代碼的意義就是啟動服務的同時把服務注冊進consul中,做的是服務發現 server := web.NewService( //go-micro很靈性的實現了注冊和反注冊,我們啟動后直接ctrl+c退出這個server,它會自動幫我們實現反注冊 web.Name("httpprodservice"), //注冊進consul服務中的service名字 web.Address(":8088"), //注冊進consul服務中的端口,也是這里我們gin的server地址 web.Handler(ginRouter), //web.Handler()返回一個Option,我們直接把ginRouter穿進去,就可以和gin完美的結合 web.Metadata(map[string]string{"protocol" : "http"}), web.Registry(consulReg), //注冊到哪個服務器傷的consul中 web.RegisterTTL(time.Second*30), web.RegisterInterval(time.Second*15), )