基于 Go Micro 框架构建一个简单的微服务接口
友情提示:由于 Go Micro 已经将 Consul 从开箱支持调整为插件支持,所以本篇教程对于新手已经不再适用,最新版本教程在这里:https://laravel.geekai.co/post/21585。
今天,学院君将通过一个简单的 HelloWorld 示例给大家演示下如果基于 Go-Micro 框架进行微服务开发。学院君的本地开发环境和工具是 Mac + GoLand,如果你本地还没有安装 Go 语言开发环境,请参考这篇教程安装设置。
0、创建新项目
打开 GoLand,创建一个新项目 hello
:
创建成功后,进入该项目,设置项目 GOPATH
路径:
1、安装 Protobuf
打开 GoLand 自带的 Terminal,运行如下命令安装 protoc-gen-micro,该工具可以帮助我们快速生成微服务模板代码:
该工具依赖 protoc 和 protoc-gen-go,所以要使用 protoc-gen-micro
还要安装它们。
可以从这里 https://github.com/protocolbuffers/protobuf/releases 下载最新版的 protoc:
选择与自己系统相匹配的压缩包,比如我的是 Mac 系统,则选择 osx 64 位下载,解压,然后将其移动到指定位置(可选),并将 protoc
二进制可执行文件所在的 bin
目录放到系统路径中:
mv ~/Downloads/protoc-3.8.0-osx-x86_64 ~/go/tools
vi ~/.zshrc
export PATH="/Users/sunqiang/go/tools/protoc-3.8.0-osx-x86_64/bin:$PATH"
source ~/.zshrc
运行 protoc --version
检测是否可以在任意位置调用 protoc
命令:
然后在 hello
项目根目录下安装 protoc-gen-go
(还是在 GoLand 的 Terminal 中执行):
go get -u github.com/golang/protobuf/protoc-gen-go
安装完成后,可以看到 protoc-gen-go
可执行文件会被安装到项目根目录下的 bin
目录下:
表明安装成功。
2、服务发现
接下来,我们设置基于 Consul 进行服务发现,为此,需要在系统中安装 Consul,可以从 Consul 下载页面 选择与自己系统匹配的下载包下载(比如这里学院君选择的是 macOS 64-bit):
下载完成后,解压到本地,是一个二进制可执行文件,将其移动到指定位置(可选):
mv ~/Downloads/consul ~/go/tools/
然后和 protoc
一样,将 consul
添加到系统路径中,并设置一个新的系统环境变量 MICRO_REGISTRY
以便被 Go Micro 使用:
vi ~/.zshrc
export PATH="/Users/sunqiang/go/tools:$PATH"
export MICRO_REGISTRY=consul
source ~/.zshrc
接下来,运行 consul
命令验证是否安装成功:
3、编写服务
至此,微服务所依赖的基本工具都已经安装设置好了,下面我们来编写一个微服务接口。
创建服务接口原型
在 ~/go/hello/src
目录下新建一个 hello
子目录,并在该 hello
子目录下创建一个 proto
目录,然后在 proto
目录下创建一个服务接口原型文件 greeter.proto
,我们通过 protobuf 定义服务接口如下:
syntax = "proto3";
service Greeter {
rpc Hello(HelloRequest) returns (HelloResponse) {}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string greeting = 2;
}
如上述代码所示,我们定义了一个名为 Greeter
的服务,该服务中包含一个 Hello
方法,该方法接收一个 HelloRequest 对象,然后返回一个 HelloResponse 对象,这两个对象都只包含一个参数。
通过接口原型生成代码
接下来,我们就可以借助第 1 步安装的 protoc
工具通过接口原型生成相应的服务代码(在 GoLand的 Terminal 窗口中执行):
cd ~/go/hello/src/hello
protoc --proto_path=. --micro_out=. --go_out=. proto/greeter.proto
执行成功的话,会在 proto
目录下生成两个新的 Go 文件:
其中 greeter.pb.go
由 protoc-gen-go
生成,包含了 HelloRequest
和 HelloResponse
类代码;greeter.micro.go
由 protoc-gen-micro
生成,包含了 Greeter
服务相关的实现代码。
编写服务端代码
接下来,我们在 ~/go/hello/src/hello
创建一个 main.go
用作服务端入口:
package main
import (
"context"
"fmt"
proto "hello/proto"
micro "github.com/micro/go-micro"
)
type Greeter struct{}
func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error {
rsp.Greeting = " 你好, " + req.Name
return nil
}
func main() {
// 创建新的服务
service := micro.NewService(
micro.Name("Greeter"),
)
// 初始化,会解析命令行参数
service.Init()
// 注册处理器,调用 Greeter 服务接口处理请求
proto.RegisterGreeterHandler(service.Server(), new(Greeter))
// 启动服务
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
启动服务端
由于我们在代码中引入了远程的包,所以在启动服务端之前,需要先安装这个依赖:
go get github.com/micro/go-micro
然后启动 Consul 代理,以便服务端启动时可以将服务注册到 Consul 中,从而被客户端调用:
这样,我们就可以运行 main.go
来启动服务端了:
go run main.go
在命令行中,可以看到使用的通信协议以及服务注册到注册中心的信息:
此时,在浏览器中访问 http://localhost:8500
,也可以看到 Greeter
服务已经注册成功了:
接下来,就可以通过客户端调用这个远程服务了,我们来编写一段简单的客户端测试代码。
4、编写客户端
在 ~/go/hello/src/hello
目录下创建一个 client.go
用于客户端测试:
package main
import (
"context"
"fmt"
"github.com/micro/go-micro"
proto "hello/proto"
)
func main() {
// 创建一个新的服务
service := micro.NewService(micro.Name("Greeter.Client"))
// 初始化
service.Init()
// 创建 Greeter 客户端
greeter := proto.NewGreeterService("Greeter", service.Client())
// 远程调用 Greeter 服务的 Hello 方法
rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{Name: "学院君"})
if err != nil {
fmt.Println(err)
}
// Print response
fmt.Println(rsp.Greeting)
}
运行这段 Go 代码,就可以在命令行打印如下信息,表示客户端调用远程服务成功:
至此,我们就基于 Go Micro 框架创建了第一个微服务接口,关于里面涉及到的底层实现原理,我们后面会详细介绍,下一篇,学院君将演示如何从 PHP 项目中(即以 PHP 项目作为客户端)调用基于 Go 实现的微服务接口。
65 Comments
我在非GOPATH目录下建的项目,运行go run main.go就会出现以上问题,在GOPATH下就是好的,这个问题怎么解决呢?
必须在 GOPATH 目录下运行
踩完坑才来看评论,,亏大了
go 1.13 也要在 GOPATH目录下吗?
按照 go get 方式下载管理包的话是需要的
这些依赖搞了一天还没有搞完整
1.13 使用go mod 管理就可以
go.mod文件
consul:
使用consul 注册中心,遇到一个问题,在mac下执行
go run client.go
的时候,报错service go.micro.network: not found
。但是 在windows平台下运行是正常的请问下,可能是什么问题呢?
我用go mod管理依赖,运行服务端出现以下问题:
go.mod 文件:
consul ui 中看不到注册的服务, 但是服务调用成功,consul 的问题?