go-micro学习

Olivia的小跟班 Lv3

题记

本文主要记录微服务框架go-micro的学习笔记。

1、什么是go-micro

go-micro是一个开源的微服务框架,旨在简化分布式系统的开发。 它基于 Go 语言构建,提供了一组组件和工具,帮助开发人员构建可伸缩、可维护的微服务应用程序。

GitHub项目地址:Go Micro

整体架构设计:

go架构 yearning go micro 架构图_go架构 yearning

2、go-micro的构成组件

Go Micro

  • 用于在Go中编写微服务的插件式RPC框架。它提供了用于服务发现、客户端负载平衡、编码、同步和异步通信库
  • 这是我们学习go-micro最重要的库,我们开发微服务的重点也是编写RPC服务。

API

  • 提供并将HTTP请求路由到对应微服务的API网关。它充当单个入口点,可以用作反向代理或将HTTP请求转换为RPC。
  • 我们开发微服务项目,说到底是编写RPC服务,如何让外部请求可以访问到RPC服务呢?就是通过API

Sidecar

  • 一种对语言透明的RPC代理(也就是和语言无关),具有go-micro作为HTTP端点的所有功能。虽然Go是构建微服务的优选语言,但商业项目中也经常使用其他语言一起开发微服务。因此Sidecar提供了一种将其他语言应用程序集成到Micro世界的方法。
  • Sidecar又被称为服务网格,其作用是:第一,微服务治理与业务逻辑的解耦。第二,异构系统的统一治理。

Web

  • 用于Micro Web应用程序的仪表板和反向代理。官方认为基于微服务建立web应用是通用场景,因此Web被视为微服务领域的一等公民。它的行为非常像API反向代理,另外也包括对web sockets的支持。
  • 我们可以通过仪表盘直观的观察到微服务项目的运行情况,后面会重点介绍。

CLI

  • 提供命令行界面让我们和微服务进行交互。CLI还可以使我们利用Sidecar作为代理。
  • CLI是microservices toolkit micro的命令行界面,包括获取服务、查看服务、查询服务健康状态等功能;我们还可以通过Sidecar代理CLI。

Bot

  • Hubot风格的bot。在我们的微服务平台中,可以通过Slack,HipChat,XMPP等进行交互。它通过消息传递提供CLI的功能。可以添加其他命令来自动执行常见的操作任务。
  • 微型机器人Bot是一个位于微服务环境中的机器人,机器人是如何工作的呢?
  • Bot使用它的命名空间监视服务注册中心的服务。默认名称空间是go.micro.bot。该名称空间内的任何服务都将自动添加到可用命令列表中。执行命令时,机器人将使用Command.Exec方法调用该服务。

3、go-micro的组件架构

Go Micro框架的核心模块:

image.png

  • 最顶层是service,代表一个微服务
  • 服务下面是两个端:客户端和服务端。(注意区分Service和Server,我在刚接触的时候混淆了这两个概念,service指的是服务;server服务端包含在service中,和client客户端一起作为service的底层支撑)
    • 服务端Server:用于构建微服务的接口,提供用于RPC请求的方法。
    • 客户端Client:提供RPC查询方法,它结合了注册表,选择器,代理和传输。它还提供重试机制,超时机制,使用上下文等。

架构图中最底层的组件对于初学微服务的同学肯定不熟悉,下面来重点介绍一下:

Registry

注册中心提供可插入的服务发现库,来查找正在运行的服务。默认的实现方式是consul。

我们也可以很方便的修改为etcd,Kubernetes等。毕竟可插拔是go-micro重要特性。

Selector

selector是一个负载均衡组件,支持随机、轮训等负载均衡算法,客户端在通过Register组件拿到多个服务端地址的时候,通过Selector组件的负载均衡算法,选择一个服务端进行通信。

Broker

消息队列的抽象,支持基于消息的事件处理,方便我们处理异步任务,可以根据需要选择各种消息队列,例如:RabbitMQ

Transport

负责客户端和服务端的通信,例如:使用http、websocket协议通信。

Codec

消息编码和解码的组件,客户端和服务端在处理消息的时候都需要codec组件,对消息进行编码或者解码,例如对protobuf格式的消息进行编码和解码。

提示:Go Micro框架核心模块不包括Go Runtime的应用组件,这些应用组件需要单独安装。

4、go-micro编写hello world

首先安装go-micro

1
go get go-micro.dev/v4

然后安装protoc-gen-goprotoc-gen-micro(This is protobuf code generation for go-micro. We use protoc-gen-micro to reduce boilerplate code.)

1
2
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install github.com/go-micro/generator/cmd/protoc-gen-micro@latest

安装完成之后你可以在GOPATH/bin目录下看见这两个exe文件

image-20240220214410872

最后安装CLI,同理你可以在GOPATH/bin目录下看见go-micro.exe文件(暂时不用)

1
go install github.com/go-micro/cli/cmd/go-micro@latest

接下来正式开始编写微服务hello world。首先在项目下编写对应的proto文件:

image-20240220215830087

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
syntax = "proto3";

package hello;

option go_package="/hello";

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

message Request {
string name = 1;
}

message Response {
string greeting = 2;
}

然后使用命令生成对应的*.pb.go和 *.pb.micro.go文件

1
2
protoc   --go_out=.  hello/hello.proto
protoc --micro_out=. hello/hello.proto

image-20240220220036476

编写对应的微服务:

image-20240221022549950

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package service

import (
"context"
HelloPb "micro_example_project/idl/hello"
"sync"
)

type HelloSrv struct {
}

var HelloSrvIns *HelloSrv
var HelloSrvOnce sync.Once

func GetHelloSrv() *HelloSrv {
HelloSrvOnce.Do(func() {
HelloSrvIns = &HelloSrv{}
})
return HelloSrvIns
}

func (h *HelloSrv) Hello(ctx context.Context, in *HelloPb.Request, out *HelloPb.Response) error {
out.Greeting = "Hello " + in.Name
return nil
}

启动微服务的main函数,把该微服务注册到etcd

image-20240221022858361

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main

import (
"fmt"
"github.com/go-micro/plugins/v4/registry/etcd"
"go-micro.dev/v4"
"go-micro.dev/v4/registry"
hello "micro_example_project/app/hello/service"
"micro_example_project/config"
HelloPb "micro_example_project/idl/hello"
)

func main() {
config.Init()

//etcd注册件
etcdReg := etcd.NewRegistry(
registry.Addrs(fmt.Sprintf("%s:%s", config.EtcdHost, config.EtcdPort)),
)

//定义服务
service := micro.NewService(
micro.Name("HelloService"),
micro.Address(config.HelloServiceAddress),
micro.Registry(etcdReg),
)

//服务初始化
service.Init()

// 注册handler
err := HelloPb.RegisterGreeterHandler(service.Server(), hello.GetHelloSrv())
if err != nil {
return
}

//启动服务
if err := service.Run(); err != nil {
fmt.Println(err)
}
}

最后编写Micro web(用于反向代理),简单来说就是你启动Micro web之后,app的http请求打到这里,通过调用对应路由的处理器函数,把它以rpc的形式转发给具体的微服务实例去处理请求

image-20240221023136391

image-20240221023159594

image-20240221023210148

image-20240221023237066

image-20240221023246134

最后就是启动Micro web,发送http请求(注意两点:etcd要开启,微服务名字别写的不一样)

image-20240221023413570

最后尝试发送请求,查看返回值

image-20240221023437740

image-20240221023513061

完整代码请访问:zhouxing9454/micro_example_project

5、小结

go-micro的入门学习就到这里了,关于go-micro的一些插件的使用和具体例子,可以参考Go Micro examples Go Micro plugins and integrations 这两个仓库。

  • 标题: go-micro学习
  • 作者: Olivia的小跟班
  • 创建于 : 2024-02-20 18:38:13
  • 更新于 : 2024-02-21 03:15:28
  • 链接: https://www.youandgentleness.cn/2024/02/20/go-microѧϰ/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论