注意
:本文使用的Go版本为 go1.17.6
使用 1.18.x
版本或其他版本在操作时总是碰到各种问题,比如依赖下载异常、版本不一致等问题。当然也可能是我电脑的问题。
参考文档:go 微服务之go-micro v3+gin
在使用Etcd作为注册中心前需要先有Etcd节点或者Etcd集群,Etcd集群的安装配置及启动,详见:Etcd教程 — 第四章 Etcd集群安全配置。
注意
:2.3到 2.6 步骤执行完同时会在 ${GOPATH}\bin
下生成exe文件。
本文创建的项目名称为 go-micro-demo
go mod init go-micro-demo
go get github.com/golang/protobuf/protoc-gen-go
注意
:是安装 asim
下的而不是micro
下的,因为micro
下的始终下载不了,这个也是go micro 3.0 框架。
go get github.com/asim/go-micro/cmd/protoc-gen-micro/v3
go install github.com/micro/micro/v3@latest
go get github.com/asim/go-micro/v3
go get -u github.com/gin-gonic/gin
web
模块在 go-micro-demo
下创建web
文件夹
web
文件夹创建main.go
文件
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
const addr = ":9000"
func Index(c *gin.Context) {
c.JSON(http.StatusOK, map[string]interface{}{
"message": "Gin访问成功",
})
}
func main() {
r := gin.Default()
r.Handle("GET", "/", Index)
if err := r.Run(addr); err != nil {
fmt.Println("err")
}
}
然后执行 go run .
或者在Goland中执行main函数,启动web服务。
启动成功后,在浏览器访问 http://127.0.0.1:9000, 得到如下响应:
// 20220704141435
// http://127.0.0.1:9000/
{
"message": "Gin访问成功"
}
在 go-micro-demo\services
下执行micro new test
命令,创建后端测试
服务模块。
H:\Goland\go-micro-demo\services>micro new test
Creating service test
.
├── micro.mu
├── main.go
├── generate.go
├── handler
│ └── test.go
├── proto
│ └── test.proto
├── Dockerfile
├── Makefile
├── README.md
├── .gitignore
└── go.mod
download protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install:
visit https://github.com/protocolbuffers/protobuf/releases
compile the proto file test.proto:
cd test
make init
go mod vendor
make proto
删除services\test
模块下的go.mod
文件,统一使用go-micro-demo
下的go.mod
。
test.proto
主要是修改go_package
指定生成pb文件的路经,这里是将 ./改为 ../
即可。
syntax = "proto3";
package test;
//option go_package = "./proto;test";
//将 ./改为 ../
option go_package = "../proto;test";
service Test {
rpc Call(Request) returns (Response) {}
rpc Stream(StreamingRequest) returns (stream StreamingResponse) {}
rpc PingPong(stream Ping) returns (stream Pong) {}
}
message Message {
string say = 1;
}
message Request {
string name = 1;
}
message Response {
string msg = 1;
}
message StreamingRequest {
int64 count = 1;
}
message StreamingResponse {
int64 count = 1;
}
message Ping {
int64 stroke = 1;
}
message Pong {
int64 stroke = 1;
}
进入到 go-micro-demo\services\test\proto
。执行生成命令:
protoc --proto_path=. --micro_out=. --go_out=. *.proto
执行完后可以在go-micro-demo\services\test\proto
看到生成的test.pb.go
和test.pb.micro.go
文件。
修改 micro-demo\services\test\handler
下的 test.go
主要是修改引入的 pb文件位置。
import (
"context"
log "github.com/micro/micro/v3/service/logger"
test "go-micro-demo/services/test/proto"//test "test/proto"
)
micro
下的包替换成asim
下的。package main
import (
//修改 1
"go-micro-demo/services/test/handler" //"test/handler"
pb "go-micro-demo/services/test/proto" //pb "test/proto"
//修改 2 替换micro为asim
service "github.com/asim/go-micro/v3" //"github.com/micro/micro/v3/service"
"github.com/asim/go-micro/v3/logger" //"github.com/micro/micro/v3/service/logger"
)
func main() {
//修改 3
srv := service.NewService( // service.New
service.Name("test"),
service.Version("latest"),
)
// Register handler
//修改 4
_ = pb.RegisterTestHandler(srv.Server(), new(handler.Test))
// Run service
if err := srv.Run(); err != nil {
logger.Fatal(err)
}
}
然后执行 go run .
或者在Goland中执行main函数,启动名为test
的服务。
如果启动时报:
handler\test.go:6:2: no required module provides package github.com/micro/micro/v3/service/logger; to add it:
go get github.com/micro/micro/v3/service/logger
执行go mod tidy
后重启。
启动成功后,控制台显示内容:
API server listening at: 127.0.0.1:58596
2022-07-04 14:50:44 file=v3@v3.7.1/service.go:206 level=info Starting [service] test
2022-07-04 14:50:44 file=server/rpc_server.go:820 level=info Transport [http] Listening on [::]:58603
2022-07-04 14:50:44 file=server/rpc_server.go:840 level=info Broker [http] Connected to 127.0.0.1:58604
2022-07-04 14:50:45 file=server/rpc_server.go:654 level=info Registry [mdns] Registering node: test-69072bf3-9123-4177-88cb-9d898a8219e5
web/handler/testHandler.go
文件package handler
import (
"github.com/asim/go-micro/v3"
"github.com/gin-gonic/gin"
testpb "go-micro-demo/services/test/proto"
"net/http"
)
func Index(c *gin.Context) {
c.JSON(http.StatusOK, map[string]interface{}{
"message": "index",
})
}
func ServiceOne(c *gin.Context) {
service := micro.NewService()
service.Init()
// 创建微服务客户端
client := testpb.NewTestService("test", service.Client())
// 调用服务
rsp, err := client.Call(c, &testpb.Request{
Name: c.Query("key"),
})
if err != nil {
c.JSON(200, gin.H{"code": 500, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 200, "msg": rsp.Msg})
}
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"go-micro-demo/web/handler"
"net/http"
)
const addr = ":9000"
func Index(c *gin.Context) {
c.JSON(http.StatusOK, map[string]interface{}{
"message": "Gin访问成功",
})
}
func main() {
r := gin.Default()
r.Handle("GET", "/", Index)
r.Handle("GET", "/test-req", handler.ServiceOne)
if err := r.Run(addr); err != nil {
fmt.Println("err")
}
}
然后执行 go run .
或者在Goland中执行main函数,重新启动web服务。
启动结果:
[GIN-debug] GET / --> main.Index (3 handlers)
[GIN-debug] GET /test-req --> go-micro-demo/web/handler.ServiceOne (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :9000
浏览器访问http://127.0.0.1:9000/test-req?key=哈哈
,得到如下响应:
// 20220704150031
// http://127.0.0.1:9000/test-req?key=%E5%93%88%E5%93%88
{
"code": 200,
"msg": "Hello 哈哈"
}
注意
:使用consul作为注册中心注册服务这块尚未实践,可能会有问题。
首选需要安装配置consul服务,独立安装,或者使用docker安装均可。
启动consul后,使用浏览器访问http://192.168.1.224:8500
go get -u github.com/asim/go-micro/plugins/registry/consul/v3
主要修改或加入的地方 consul 1
、consul 2
、consul 3
package main
import (
//修改 1
"go-micro-demo/services/test/handler" //"test/handler"
pb "go-micro-demo/services/test/proto" //pb "test/proto"
//修改 2 替换micro为asim
service "github.com/asim/go-micro/v3" //"github.com/micro/micro/v3/service"
"github.com/asim/go-micro/v3/logger" //"github.com/micro/micro/v3/service/logger"
//consul 1
"github.com/asim/go-micro/plugins/registry/consul/v3"
"github.com/asim/go-micro/v3/registry"
)
//consul 2
const (
ServerName = "test"
ConsulAddr = "192.168.1.224:8500"
)
func main() {
// consul 3
consulReg := consul.NewRegistry(
registry.Addrs(ConsulAddr),
)
srv := service.NewService(
service.Name(ServerName), // 服务名字
service.Registry(consulReg),// 注册中心
)
// Register handler
//修改 4
_ = pb.RegisterTestHandler(srv.Server(), new(handler.Test))
// Run service
if err := srv.Run(); err != nil {
logger.Fatal(err)
}
}
执行go run .,重新启动services/test模块的名为test的服务。
主要修改或加入的地方 consul 1
、consul 2
package handler
import (
"github.com/asim/go-micro/v3"
"github.com/gin-gonic/gin"
servicepb "micro-demo/services/proto"
"net/http"
//consul 1
"github.com/asim/go-micro/plugins/registry/consul/v3"
"github.com/asim/go-micro/v3/registry
)
func Index(c *gin.Context) {
c.JSON(http.StatusOK, map[string]interface{}{
"message": "index",
})
}
func ServiceOne(c *gin.Context) {
//consul 2
consulReg := consul.NewRegistry(
registry.Addrs("192.168.1.224:8500"),
)
service := micro.NewService(
micro.Registry(consulReg), //设置注册中心
)
service.Init()
// 创建微服务客户端
client := servicepb.NewServicesService("services01", service.Client())
// 调用服务
rsp, err := client.Call(c, &servicepb.Request{
Name: c.Query("key"),
})
if err != nil {
c.JSON(200, gin.H{"code": 500, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 200, "msg": rsp.Msg})
}
执行go run .,重启web。
go get -u "github.com/asim/go-micro/plugins/registry/etcd/v3"
package main
import (
"micro-demo/services/handler"
pb "micro-demo/services/proto"
service "github.com/asim/go-micro/v3"
"github.com/asim/go-micro/v3/logger"
//etcd 1
"github.com/asim/go-micro/plugins/registry/etcd/v3"
"github.com/asim/go-micro/v3/registry"
)
//etcd 2
const (
ServerName = "services01"
EtcdAddr = "192.168.1.221:2379"
)
func main() {
//etcd 3
etcdReg := etcd.NewRegistry(
registry.Addrs(EtcdAddr),
)
srv := service.NewService(
service.Name(ServerName), // 服务名字
service.Registry(etcdReg), // 注册中心
)
// Register handler
_ = pb.RegisterServicesHandler(srv.Server(), new(handler.Services))
// Run service
if err := srv.Run(); err != nil {
logger.Fatal(err)
}
}
package handler
import (
"github.com/asim/go-micro/v3"
"github.com/gin-gonic/gin"
servicepb "micro-demo/services/proto"
"net/http"
//etcd 1
"github.com/asim/go-micro/plugins/registry/etcd/v3"
"github.com/asim/go-micro/v3/registry"
)
func Index(c *gin.Context) {
c.JSON(http.StatusOK, map[string]interface{}{
"message": "index",
})
}
func ServiceOne(c *gin.Context) {
// etcd 2
etcdReg := etcd.NewRegistry(
registry.Addrs("192.168.1.221:2379"),
)
service := micro.NewService(
micro.Registry(etcdReg), //设置注册中心
)
service.Init()
// 创建微服务客户端
client := servicepb.NewServicesService("services01", service.Client())
// 调用服务
rsp, err := client.Call(c, &servicepb.Request{
Name: c.Query("key"),
})
if err != nil {
c.JSON(200, gin.H{"code": 500, "msg": err.Error()})
return
}
c.JSON(200, gin.H{"code": 200, "msg": rsp.Msg})
}
执行go run .,重启web,然后再发送 http://127.0.0.1:8080/service-req?key=哈哈
,返回结果:
// 20220704132910
// http://127.0.0.1:8080/service-req?key=%E5%93%88%E5%93%88
{
"code": 200,
"msg": "Hello 哈哈"
}