1,引入外部框架gin生成web API
go版本為1.14
go-micro升級到1.14之后的一些變動和安裝方式,確保你開啟了go module模式
先裝 go get github.com/micro/go-micro 然后裝plugins go get github.com/micro/go-plugins
1,如果出現
請參考 這個帖子: https://github.com/golang/go/issues/34394
解決方法:在go.mod里加入 replace github.com/gogo/protobuf v0.0.0-20190410021324-65acae22fc9 => github.com/gogo/protobuf v0.0.0-20190723190241-65acae22fc9d 然后再執行安裝:go get github.com/micro/go-plugins
2,如果出現
則可以這樣: 首先安裝 (注意后面的@master) go get github.com/lucas-clemente/quic-go@master 然后在go.mod里面找到 版本號 譬如是 github.com/lucas-clemente/quic-go v0.7.1-0.20191025234737-672328ca3059 然后 在go.mod里加入 replace github.com/lucas-clemente/quic-go => github.com/lucas-clemente/quic-go v0.7.1-0.20191025234737-672328ca3059
此時可以再次執行go get github.com/micro/go-micro (注意不要加-u)
有可能你會發現 go-plugins 木有consul相關內容;
那就只能這樣了: go get github.com/micro/go-plugins@master
Github地址: https://github.com/micro/go-micro
本課程一律使用go module的方式 安裝
package main import ( "github.com/gin-gonic/gin" "github.com/micro/go-micro/web" ) func main(){ 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") }) server:=web.NewService( web.Address(":8001"), web.Handler(ginRouter), ) server.Run() }
2,服務注冊:快速把服務注冊到etcd中
package main import ( "github.com/gin-gonic/gin" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/etcd" "github.com/micro/go-micro/web" ) func main(){ etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) 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") }) server:=web.NewService( web.Name("api.jtthink.com.prodservice"), web.Address(":8001"), web.Handler(ginRouter), web.Registry(etcdReg), ) server.Run() }
web.bat
set MICRO_REGISTRY=etcd set MICRO_REGISTRY_ADDRESS=localhost:2379 set MICRO_API_NAMESPACE=api.jtthink.com micro web
3,模擬運行API(主站API、商品API) 服務注冊 服務發現
服務注冊
首選編寫服務端 服務注冊到go-micro中

package ProdService import "strconv" type ProdModel struct { ProdID int ProdName string } func NewProd(id int,pname string ) *ProdModel { return &ProdModel{ProdName:pname,ProdID:id} } func NewProdList(n int) []*ProdModel { ret:=make([]*ProdModel,0) for i:=0;i<n;i++{ ret=append(ret,NewProd(100+i,"prodname"+strconv.Itoa(100+i))) } return ret }
package main import ( "github.com/gin-gonic/gin" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/etcd" "github.com/micro/go-micro/web" "gomicro.jtthink.com/ProdService" ) func main(){ etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) ginRouter:=gin.Default() v1Group:=ginRouter.Group("/v1") { v1Group.Handle("GET","/prods", func(context *gin.Context) { context.JSON(200,ProdService.NewProdList(5)) }) } server:=web.NewService( web.Name("prodservice"), web.Address(":8001"), web.Handler(ginRouter), web.Registry(etcdReg), ) server.Run() }
go run ./prod_main.go
服務發現
獲取consul服務列表、selector隨機選擇
test.go
package main import ( "fmt" "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/etcd" "log" ) func main() { etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) getService,err:=etcdReg.GetService("prodservice") if err!=nil{ log.Fatal(err) } next:=selector.Random(getService) node,err:=next() if err!=nil{ log.Fatal(err) } fmt.Println(node.Id,node.Address,node.Metadata) }
D:\gocode1.14.3\gocode\go-micro>go run test.go 6925a735-58c3-4148-92fa-d560d80d3bb7 192.168.1.101:8001 map[]
4,使用內置命令參數啟動,注冊多個服務
Go-micro 內置了 一些參數,可以在啟動時 指定,這樣就不用寫死了
譬如地址: 我們可以 這樣運行 go run prod_main.go --server_address :8001 別忘了,加上 server.Init()
server:=web.NewService( web.Name("prodservice"), //web.Address(":8001"), web.Handler(ginRouter), web.Registry(etcdReg), ) server.Init() server.Run()
開啟多個服務,用輪訓方式獲取服務
服務端:
package main import ( "github.com/gin-gonic/gin" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/etcd" "github.com/micro/go-micro/web" "gomicro.jtthink.com/ProdService" ) func main(){ etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) ginRouter:=gin.Default() v1Group:=ginRouter.Group("/v1") { v1Group.Handle("GET","/prods", func(context *gin.Context) { context.JSON(200,ProdService.NewProdList(5)) }) } server:=web.NewService( web.Name("prodservice"), //web.Address(":8001"), web.Handler(ginRouter), web.Registry(etcdReg), ) server.Init() server.Run() }
啟動服務 並注冊服務
go run prod_main.go --server_address :8001
go run prod_main.go --server_address :8002
go run prod_main.go --server_address :8003
客戶端:
用輪訓方式調用服務
package main import ( "fmt" "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/etcd" "log" "time" ) func main() { //etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) //getService,err:=etcdReg.GetService("prodservice") //if err!=nil{ // log.Fatal(err) //} //next:=selector.Random(getService) //node,err:=next() //if err!=nil{ // log.Fatal(err) //} //fmt.Println(node.Id,node.Address,node.Metadata) for { etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) getService,err:=etcdReg.GetService("prodservice") if err!=nil{ log.Fatal(err) } next:=selector.RoundRobin(getService) node,err:=next() if err!=nil{ log.Fatal(err) } fmt.Println( node.Address) time.Sleep(time.Second*1) } }
D:\gocode1.14.3\gocode\go-micro>go run test.go 192.168.1.101:8002 192.168.1.101:8001 192.168.1.101:8003 192.168.1.101:8002 192.168.1.101:8001 192.168.1.101:8003
啟動web管理界面:
web.bat
set MICRO_REGISTRY=etcd set MICRO_REGISTRY_ADDRESS=localhost:2379 set MICRO_API_NAMESPACE=prodservice micro web
5,服務調用:基本方式調用 Api(http api)
package main import ( "fmt" "github.com/micro/go-micro/v2/client/selector" "github.com/micro/go-micro/v2/registry/etcd" "github.com/micro/go-micro/v2/registry" "io/ioutil" "log" "net/http" ) func callAPI(addr string,path string,method string) (string,error) { req,_:=http.NewRequest(method,"http://"+addr+path,nil) client:=http.DefaultClient res,err:=client.Do(req) if err!=nil{ return "",err } defer res.Body.Close() buf,_:= ioutil.ReadAll(res.Body) return string(buf),nil } func main() { etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) getService,err:=etcdReg.GetService("prodservice") if err!=nil{ log.Fatal(err) } next:=selector.Random(getService) node,err:=next() if err!=nil{ log.Fatal(err) } fmt.Println(node.Id,node.Address,node.Metadata) callRes,err:=callAPI(node.Address,"/v1/prods","GET") if err!=nil{ log.Fatal(err) } fmt.Println(callRes) //for { // etcdReg := etcd.NewRegistry(registry.Addrs("127.0.0.1:2379")) // getService,err:=etcdReg.GetService("prodservice") // if err!=nil{ // log.Fatal(err) // } // next:=selector.RoundRobin(getService) // node,err:=next() // if err!=nil{ // log.Fatal(err) // } // fmt.Println( node.Address) // time.Sleep(time.Second*1) //} }
返回結果:
D:\gocode1.14.3\gocode\go-micro>go run test.go 0b93cd42-ba4d-4dcc-afee-73eb00e87547 192.168.1.101:8002 map[] [{"ProdID":100,"ProdName":"prodname100"},{"ProdID":101,"ProdName":"prodname101"},{"ProdID":102,"ProdName":"prodname102"},
{"ProdID":103,"ProdName":"prodna me103"},{"ProdID":104,"ProdName":"prodname104"}]
服務調用_ 使用插件、調用http api的正規姿勢(初步)
使用插件
https://github.com/micro/go-plugins 這里面包含了很多go-micro可選插件。譬如服務注冊中心要選擇etcd、eureka等,就需要使用到插件(當然,手工玩耍也行) 安裝go get github.com/micro/go-plugins 這個不多說了
http 包
對應的http調用包: import myhttp "github.com/micro/go-plugins/client/http " 此包除了有 http client基本功能,還支持Selector參數,
自動選取服務,並支持json、protobuf等數據格式