当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > Go语言micro之快速搭建微服务

Go语言micro之快速搭建微服务

2020年03月28日  | 移动技术网IT编程  | 我要评论

背景

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网