26

go micro实战01:快速搭建服务

 4 years ago
source link: http://www.cnblogs.com/enochzzg/p/12582646.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

背景

go-micro给我们提供了一个非常便捷的方式来快速搭建微服务,而且并不需要提前系统了解micro,下面用一个简单的示例来快速实现一个服务。

创建Proto文件

因为我们要做微服务,那么就一定有服务端和客户端,这两个端通过什么格式进行内容传输,就涉及到了序列化,比较主流的序列化协议就是JSON和Protobuf,因为Protobuf是以二进制传输的,体积比较小,所以传输速度也相对较快,今天就以protobuf来进行演示。

下面使用Proto3的语法在protos目录创建文件 greeter.proto ,该文件定义一个名为 Greeter 的服务,以及对应的入参和出参。

syntax = "proto3";
package protos;

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

message Request {
    string name = 1;
}

message Response {
    string greeting = 2;
}

生成Go文件

生成Go文件之前,要先确保本机安装了protobuf,如果在终端输入 protoc 没有打印出帮助文档,那么就是未安装。

$ protoc
Usage: protoc [OPTION] PROTO_FILES
Parse PROTO_FILES and generate output based on the options given:
  -IPATH, --proto_path=PATH   Specify the directory in which to search for
                              imports.  May be specified multiple times;
                              directories will be searched in order.  If not
                              ……

可以通过官方文档提示的命令进行安装。

go get github.com/micro/protoc-gen-micro/v2

安装成功之后,通过protoc命令将 greeter.proto 文件生成出对应的Go文件。

protoc --proto_path=./protos --micro_out=./protos --go_out=./protos ./protos/greeter.proto
  • --proto_path 是greeter.proto文件所在的路径

  • --micro_out 是生成 .go 文件的所在目录,该文件被用于创建服务

  • --go_out 是生成 .go 文件的所在目录,该文件被用于做数据序列化传输

可以根据需求自定义输出目录,我这边输出到了protos目录,现在可以看到protos目录中生成了两个文件。

greeter.pb.go
greeter.pb.micro.go

实现服务

因为刚才已经通过protobuf定义了服务的接口,所以接下来需要实现对应的服务。

第一步,实现定义的服务接口

在生成的 greeter.pb.micro.go 文件中,可以看到我们 greeter.proto 文件中一个名为 GreeterHandler 的接口。

type GreeterHandler interface {
	Hello(context.Context, *Request, *Response) error
}

我们需要先实现该接口,接下来创建server.go文件,定义结构体Greeter,并实现Hello方法。

type Greeter struct {
}

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

Hello方法的后两个参数刚好就是我们前面所生成的 greeter.bp.go 文件中定义的Request和Response结构体。在方法内部,将请求参数的Name前面拼接上了 Hello 字符串,并且赋值给了Response的Greeting变量。

第二步,初始化服务

我们创建一个名为 greeter 的服务。

func main() {
	service := micro.NewService(
		micro.Name("greeter"),
	)
	service.Init()
}

调用 micro.NewService 方法来创建一个新的服务,该方法的参数是可变参数,可以通过micro中的一系列方法来设置服务的参数,本次示例中只配置服务的名称,记得在创建完服务后执行 service.Init 方法来初始化,micro版本建议使用v2。

第三步,注册服务到handler

func main() {
	service := micro.NewService(
		micro.Name("greeter"),
	)
	service.Init()
	err := protos.RegisterGreeterHandler(service.Server(), new(Greeter))
	if err != nil {
		fmt.Println(err)
	}
}

第四步,将服务跑起来

if err := service.Run(); err != nil {
		fmt.Println(err)
	}

完整代码如下

package main

import (
	"context"
	"fmt"

	"github.com/micro/go-micro/v2"
)

type Greeter struct {
}

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

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

	err := protos.RegisterGreeterHandler(service.Server(), new(Greeter))
	if err != nil {
		fmt.Println(err)
	}

	if err := service.Run(); err != nil {
		fmt.Println(err)
	}
}

现在将服务端跑起来。

$ go run server.go
2020-03-27 11:28:20 Starting [service] greeter
2020-03-27 11:28:20 Server [grpc] Listening on [::]:63763
2020-03-27 11:28:20 Registry [mdns] Registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c

实现客户端

创建 client.go 文件

func main() {
	service := micro.NewService(micro.Name("greeter.client"))
	service.Init()

	greeter := protos.NewGreeterService("greeter", service.Client())
	rsp, err := greeter.Hello(context.TODO(), &protos.Request{Name: "pingye"})
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(rsp.Greeting)
}

执行客户端文件,输出 Hello pingye ,执行成功。

$ go run client.go
Hello pingye

服务注册到了哪里?

在启动服务端的时候从终端输出的信息可以看出,有一个名为 greeter 的服务注册到了 Registry

2020-03-27 11:28:20 Starting [service] greeter
2020-03-27 11:28:20 Server [grpc] Listening on [::]:63763
2020-03-27 11:28:20 Registry [mdns] Registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c

Registry是go-micro的注册模块,作用是将服务注册到某个介质,以方便客户端使用。注册模块默认支持cache、consul、etcd、k8s、mdns、memory等多种介质,默认使用的是mdns。

var (
	DefaultRegistry = NewRegistry()

	// Not found error when GetService is called
	ErrNotFound = errors.New("service not found")
	// Watcher stopped error when watcher is stopped
	ErrWatcherStopped = errors.New("watcher stopped")
)

mdns主要用于在没有传统DNS服务器的情况下,在局域网中实现主机之间的发现与通讯,它遵从DNS协议。

Go语言组件示例开源库,欢迎star

https://github.com/EnochZg/golang-examples

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK