zoukankan      html  css  js  c++  java
  • Go语言micro之快速搭建微服务

    背景

    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

  • 相关阅读:
    Druid 使用 Kafka 将数据载入到 Kafka
    Druid 使用 Kafka 数据加载教程——下载和启动 Kafka
    Druid 集群方式部署 —— 启动服务
    Druid 集群方式部署 —— 端口调整
    Druid 集群方式部署 —— 配置调整
    Druid 集群方式部署 —— 配置 Zookeeper 连接
    Druid 集群方式部署 —— 元数据和深度存储
    Druid 集群方式部署 —— 从独立服务器部署上合并到集群的硬件配置
    Druid 集群方式部署 —— 选择硬件
    Druid 独立服务器方式部署文档
  • 原文地址:https://www.cnblogs.com/pingyeaa/p/12582646.html
Copyright © 2011-2022 走看看