0%

go-micro 入门(一)——安装运行HelloWorld

Update
go-micro作者表示不再维护go-micro而仅专心开发micro(原因之一应该是micro v3变成商业版可以赚钱吧。。)

本文是v3的教程,但兼容v2。不过我跑通v3后发现用不了gin退回v2了。

———-update分割线———-

go-micro是Go的常见微服务之一,不过它的官方文档和别人的教程甚至代码的repo都十分混乱,初入门的我直接下载最新的版本被教程搞得一头雾水,这里记录一下以及希望有朋友不要一起踩坑啦(如果作者又搞事情我也无话可说)

题外话:悲催的我刚跑通v2.9第二天打开GitHub发现更新到了v3.01😓

环境

  • OS: Win10
  • Go: 1.15.6(1.14以上应该都可以,v2建议用1.14不要1.15)
  • go-micro: 3.0.1(本文含v2.9的基础安装)
  • protoc: 3.14.0
  • consul: 1.9.1(Docker)
  • GoLand: 2020.3.1

安装

go-micro

官方Github

go-micro的repo其实有些混乱,以及除了go-micro之外,还有一个micro的repo,两者之间的关系我暂时还没搞懂(似乎micro可安装后对go-micro进行查看)

安装go-micro的v3版本,其实之前有段时间好像叫nitro来着,但最后正式版还是回归了go-micro

1
go get -u github.com/asim/go-micro/v3

如果出问题记得设置

1
go env -w GO111MODULE=on

go-micro的v1和v2都是github.com/micro/go-micro/[v2],不知道为什么反而v3变回了个人的repo路径

go-micro plugins

go-micro在v1和v2采用go-plugins的一个单独repo Github,但在v3的时候又重新回到了go-micro/plugins下面Github

没有成功获得插件正确安装方法,只会傻傻得一个个安装。。

v2的安装命令,注意替换需要的插件的路径

1
go get -u github.com/micro/go-plugins/registry/consul/v2

v3

1
go get -u github.com/asim/go-micro/plugins/registry/consul/v3

protobuf

安装protobuf

protobuf介绍自行搜索,类似json但占用更小的空间
官方Github里的release下载最新的包,选择对应的os,比如我下载的是protoc-3.14.0-win64.zip(不懂为什么一群人教程下32位)

放到想要的安装目录下,比如我的C:\Program Files\Protobuf,把bin目录加入环境变量

命令行

1
2
>protoc --version
libprotoc 3.14.0

安装protoc-gen-go

protobuf默认是不支持go的编译的,因此需要安装protoc-gen-go来支持编译为go文件

1
go get -u github.com/golang/protobuf/protoc-gen-go

安装protoc-gen-micro

protoc-gen-micro是用于生成针对micro可用的文件 Github

1
go get -u github.com/asim/go-micro/cmd/protoc-gen-micro/v3

测试安装成功

首先创建一个文件greeter.proto

1
2
3
4
5
6
7
8
9
10
11
12
13
syntax = "proto3";

service Greeter {
rpc Hello(Request) returns (Response) {}
}

message Request {
string name = 1;
}

message Response {
string msg = 1;
}

运行以下命令

1
protoc --micro_out=. --go_out=. greeter.proto

如果能生成greeter.pb.gogreeter.pb.micro.go那就证明安装成功了。
上面的文件会出现一些提示要求specify go package的路径,但暂时不影响

consul

这里我偷懒了以下,下了一个docker镜像包,因为本身也准备用docker,安装在电脑上似乎没那么必要

1
2
docker pull consul
docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul agent -server -bootstrap-expect=1 -ui -bind=0.0.0.0 -client=0.0.0.0

浏览器localhost:8500,可以看到当前已注册的服务

创建第一个micro服务

这里只是简单的运行micro这个服务

main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"github.com/asim/go-micro/v3"
)

func main() {
service := micro.NewService(
micro.Name("helloworld"),
)

service.Init()

service.Run()
}

采用consul作为注册中心

go-micro v2和v3都是采用mdns作为注册中心的,但是consul有更多的功能以及UI(另外常用的还有etcd和zookeeper)

而更加坑的是不知道什么问题,我电脑明明可运行mdns,采用mdns的时候micro的服务无被发现(可能win10的锅,也有说法防火墙的锅,我ubuntu运行正常,有人win10也运行正常)

首先需要运行consul,走默认端口8500

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
"github.com/asim/go-micro/plugins/registry/consul/v3"
"github.com/asim/go-micro/v3"
"github.com/asim/go-micro/v3/registry"
)

var consulReg registry.Registry

func init() {
consulReg = consul.NewRegistry(registry.Addrs(":8500")) // 告知consul的端口号,如果走默认可以不填写
// 冒号前面可填ip地址,默认localhost
}

func main() {
service := micro.NewService(
micro.Name("helloworld"),
micro.Address(":18001"), // 设置端口18001
micro.Registry(consulReg),
)

service.Init()

service.Run()
}

在consul的ui中可以看到有一个叫做helloworld的服务

HelloWorld微服务

这里我们创建一个service和一个client,模拟最简单的微服务的交互场景(代码改编于go-micro/example/service)

目录结构

文件夹go-micro-test

1
2
3
4
5
6
7
8
9
│  client.go
│ go.mod
│ go.sum
│ greeter.go

└─proto
greeter.pb.go
greeter.pb.micro.go
greeter.proto

定义proto

如果采用GoLand开发的话推荐安装插件Protocol Buffer Editor,网上看到推荐Protobuf Support已经被deprecated了

greeter.proto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
syntax = "proto3";

package proto;
option go_package = "/proto";

service Greeter {
rpc Hello(Request) returns (Response) {}
}

message Request {
string name = 1;
}

message Response {
string greeting = 1;
}

这里定义了一个叫做Greeter的调用方法(client对service的rpc),其中Request就是请求的数据内容,Response就是service返回的内容
package是生成的文件的包名,go_package是总的包路径

生成对应go文件:

1
protoc --micro_out=. --go_out=. proto/greeter.proto

获得greeter.pb.gogreeter.pb.micro.go

编写service

这里叫做greeter.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (
"context"
"github.com/asim/go-micro/plugins/registry/consul/v3"
"github.com/asim/go-micro/v3"
"github.com/asim/go-micro/v3/registry"
proto "go-micro-test/proto"
"log"
)

type Greeter struct{}

func (g *Greeter) Hello(ctx context.Context, req *proto.Request, rsp *proto.Response) error {
rsp.Greeting = "Hello " + req.Name
return nil
}

func main() {
consulReg := consul.NewRegistry(registry.Addrs(":8500"))

service := micro.NewService(
micro.Name("greeter"),
micro.Registry(consulReg),
)

service.Init()

proto.RegisterGreeterHandler(service.Server(), new(Greeter))

if err := service.Run(); err != nil {
log.Fatal(err)
}
}

这里Greeter和它的方法Hello是用来实现我们在proto中定义的调用

编写client

文件client.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
"context"
"fmt"
"github.com/asim/go-micro/plugins/registry/consul/v3"
"github.com/asim/go-micro/v3"
"github.com/asim/go-micro/v3/registry"
proto "go-micro-test/proto"
)

func main() {
consulReg := consul.NewRegistry(registry.Addrs(":8500"))

service := micro.NewService(
micro.Name("greeter.client"),
micro.Registry(consulReg),
)

service.Init()

greeter := proto.NewGreeterService("greeter", service.Client())

rsp, err := greeter.Hello(context.TODO(), &proto.Request{Name: "World"})
if err != nil {
fmt.Println(err)
return
}

fmt.Println(rsp.Greeting)
}

运行

首先启动ervice

1
go run greeter.go

其次启动client

1
go run client.go

如无意外可以看到client这边显示Hello World

采用mdns注册中心

直接把注册consul的删掉就好,但是我在win10下运行会返回500,ubuntu下正常
搜到的相关issue,开发者说windows不支持,但的确看到有人win10可以跑

而且mdns也的确不适合作为大型服务的注册中心,还是推荐consul或者etcd