微服务架构系列 - 框架篇:基于 Go Micro 框架创建第一个微服务接口

- 4 mins

微服务架构系列(六)

今天将通过一个简单的 HelloWorld 示例给大家演示下如果基于 Go-Micro 框架进行微服务开发。

0、创建新项目

打开 GoLand,创建一个新项目 hello

img

创建成功后,进入该项目,设置项目 GOPATH 路径:

img

1、安装 Protobuf

打开 GoLand 自带的 Terminal,运行如下命令安装 protoc-gen-micro,该工具可以帮助我们快速生成微服务模板代码:

img

该工具依赖 protocprotoc-gen-go,所以要使用 protoc-gen-micro 还要安装它们。

可以从这里 https://github.com/protocolbuffers/protobuf/releases 下载最新版的 protoc:

img

选择与自己系统相匹配的压缩包,比如我的是 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 命令:

img

然后在 hello 项目根目录下安装 protoc-gen-go(还是在 GoLand 的 Terminal 中执行):

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

安装完成后,可以看到 protoc-gen-go 可执行文件会被安装到项目根目录下的 bin 目录下:

img

表明安装成功。

2、服务发现

接下来,我们设置基于 Consul 进行服务发现,为此,需要在系统中安装 Consul,可以从 Consul 下载页面选择与自己系统匹配的下载包下载(比如这里学院君选择的是 macOS 64-bit):

img

下载完成后,解压到本地,是一个二进制可执行文件,将其移动到指定位置(可选):

    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 命令验证是否安装成功:

img

3、编写服务

至此,微服务所依赖的基本工具都已经安装设置好了,下面我们来编写一个微服务接口。

1)创建服务接口原型

~/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 对象,这两个对象都只包含一个参数。

2)通过接口原型生成代码

接下来,我们就可以借助第 1 步安装的 protoc 工具通过接口原型生成相应的服务代码(在 GoLand的 Terminal 窗口中执行):

    cd ~/go/hello/src/hello
    protoc --proto_path=. --micro_out=. --go_out=. proto/greeter.proto

执行成功的话,会在 proto 目录下生成两个新的 Go 文件:

img

其中 greeter.pb.goprotoc-gen-go 生成,包含了 HelloRequestHelloResponse 类代码;greeter.micro.goprotoc-gen-micro 生成,包含了 Greeter 服务相关的实现代码。

3)编写服务端代码

接下来,我们在 ~/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)
        }
    }

4)启动服务端

由于我们在代码中引入了远程的包,所以在启动服务端之前,需要先安装这个依赖:

    go get github.com/micro/go-micro

然后启动 Consul 代理,以便服务端启动时可以将服务注册到 Consul 中,从而被客户端调用:

img

这样,我们就可以运行 main.go 来启动服务端了:

    go run main.go

在命令行中,可以看到使用的通信协议以及服务注册到注册中心的信息:

img

此时,在浏览器中访问 http://localhost:8500,也可以看到 Greeter 服务已经注册成功了:

img

接下来,就可以通过客户端调用这个远程服务了,我们来编写一段简单的客户端测试代码。

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: "Hello"})
        if err != nil {
            fmt.Println(err)
        }
    
        // Print response
        fmt.Println(rsp.Greeting)
    }

运行这段 Go 代码,就可以在命令行打印如下信息,表示客户端调用远程服务成功。

至此,我们就基于 Go Micro 框架创建了第一个简单的微服务接口,关于里面涉及到的底层实现原理,我们后面会详细介绍,下一篇,学院君将演示如何从 PHP 项目中(即以 PHP 项目作为客户端)调用基于 Go 实现的这个微服务接口。

rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora