概述

前言: 微型入门指南

什么是 Micro

Micro 是一个用于构建和管理分布式系统的系统.

Micro 的主要组件如下:

  • 运行时: 用于管理服务包括 auth, config, discovery, networking 的运行时环境.
  • 框架: 用于编写要在运行时运行的服务的 Go 框架.
  • 客户端: 多语言客户端, 使其他程序能够访问微服务.

安装

使用 Go:

go install github.com/micro/micro/v2

或者通过下载二进制文件

# MacOS

curl -fsSL https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh | /bin/bash

# Linux
wget -q  https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh -O - | /bin/bash

# Windows
powershell -Command "iwr -useb https://raw.githubusercontent.com/micro/micro/master/scripts/install.ps1 | iex"

运行服务

在深入了解编写服务之前, 让我们运行一个现有的服务, 因为它只是几个命令!

首先, 我们必须开始. 执行此操作的命令是:

micro server

如果一切顺利, 您将看到各种服务初始化的日志输出; 此终端将继续输出日志, 因为我们通过本教程的其余部分, 所以保持它运行.

要与此服务器交互, 我们只需告诉 Micro CLI 解决我们的服务器问题, 而不是使用默认实现 - micro 也可以在没有服务器的情况下工作, 但稍后将对此进行更多介绍.

以下命令告诉 CLI 与我们的服务器交互:

micro env set server

非常好! 我们继续. 只是为了验证一切是否井然有序, 让我们看看正在运行的服务:

$ micro list services
go.micro.api
go.micro.auth
go.micro.bot
go.micro.broker
go.micro.config
go.micro.debug
go.micro.network
go.micro.proxy
go.micro.registry
go.micro.router
go.micro.runtime
go.micro.server
go.micro.web

所有这些服务都是由我们的启动的. 这很酷, 但它仍然不是我们这节要说的重点! 让我们开始一个服务, 我们实际上可以信任的存在. 如果我们去 github.com/micro/services, 我们看到一堆由 mirco 作者编写的服务. 其中之一是 helloworld. 让我们来试试, 好吗?

运行服务的命令是 micro run. 此命令可能需要一段时间才能从 GitHub 检出存储库. (@todo这实际上当前失败, 修复)

micro run github.com/micro/services/helloworld

如果我们查看下正在运行的 micro server, 我们应该看到类似如下内容

Creating service helloworld version latest source /tmp/github.com-micro-services/helloworld
Processing create event helloworld:latest

我们还可以查看服务的日志, 以验证其正在运行.

$ micro logs helloworld
Starting [service] go.micro.service.helloworld
Server [grpc] Listening on [::]:36577
Registry [service] Registering node: go.micro.service.helloworld-213b807a-15c2-496f-93ac-7949ad38aadf

因此, 由于我们的服务运行的很好, 让我们尝试调用它! 这就是该服务存在的原因.

调用服务

我们有几个选项可以调用我们在运行的服务 micro server

通过 CLI 调用服务

最简单的可能是通过 CLI:

$ micro call go.micro.service.helloworld Helloworld.Call '{"name":"Jane"}'
{
    "msg": "Hello Jane"
}

成功了! 如果我们想知道服务具有哪些终结点, 我们可以运行以下命令:

micro get service go.micro.service.helloworld

否则, 最好的地方看是 proto 定义. 您还可以在 http://localhost:8082 浏览 UI 以查看实时信息.

使用 Go Micro 调用服务

让我们编写一个小客户端, 我们可以用它来调用 helloworld 服务. 通常, 您将在另一个服务内进行服务调用, 因此这只是您可以编写的函数的示例. 我们将学习如何尽快编写一份全面的服务.

让我们采用以下文件和代码:

package main

import (
    "context"
    "fmt"

    "github.com/micro/go-micro/v2"
    proto "github.com/micro/services/helloworld/proto"
)

func main() {
    // create and initialise a new service
    service := micro.NewService()
    service.Init()

    // create the proto client for helloworld
    client := proto.NewHelloworldService("go.micro.service.helloworld", service.Client())

    // call an endpoint on the service
    rsp, err := client.Call(context.Background(), &proto.Request{
        Name: "John",
    })
    if err != nil {
        fmt.Println("Error calling helloworld: ", err)
        return
    }

    // print the response
    fmt.Println("Response: ", rsp.Msg)

    // let's delay the process for exiting for reasons you'll see below
    time.Sleep(time.Second * 5)
}

在本地保存示例. 为了便于遵循本指南, 可以命名文件夹为 example-service. 执行 example-service && go mod init examplemicro run 命令后, 我们准备使用 micro run 命令运行此服务:

micro run .

另一个有用的命令, 以查看正在运行的内容, 是 micro status. 此时, 我们应该有两个服务正在运行:

$ micro status
NAME            VERSION    SOURCE                                        STATUS        BUILD    UPDATED        METADATA
example-service    latest    /home/username/example-service                starting    n/a        4s ago        owner=n/a,group=n/a
helloworld        latest    /tmp/github.com-micro-services/helloworld    running        n/a        6m5s ago    owner=n/a,group=n/a

现在, 由于我们的示例服务客户端也在运行, 我们应该能够看到它的日志:

$ micro logs example-service
# some go build output here
Response:  Hello John

非常好! 这种响应内容直接来自我们之前开始的 helloworld 服务!

从其他语言

客户端仓库 中, 有用于各种语言和框架的 micro 客户端. 它们旨在轻松连接到实时 micro 环境或本地环境, 但稍后将提供更多有关环境.

编写服务

要建立新服务的脚手架, 可以使用该命令 micro new. 它应会输出类似如下的内容:

$ micro new foobar
Creating service go.micro.service.foobar in foobar

.
├── main.go
├── generate.go
├── plugin.go
├── handler
│   └── foobar.go
├── subscriber
│   └── foobar.go
├── proto/foobar
│   └── foobar.proto
├── Dockerfile
├── Makefile
├── README.md
├── .gitignore
└── go.mod


download protobuf for micro:

brew install protobuf
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
go get github.com/micro/micro/v2/cmd/protoc-gen-micro@master

compile the proto file foobar.proto:

cd foobar
protoc --proto_path=.:$GOPATH/src --go_out=. --micro_out=. proto/foobar/foobar.proto

从上面的输出可以看出, 在构建第一个服务之前, 必须安装以下工具:

它们都需要将原文件转换为实际的 Go 代码. Protos 的存在是为了提供一种与语言无关的方法来描述服务终结点, 其输入和输出类型, 并具有高效的序列化格式.

目前, Micro 是 Go 重点 (除了前面提到的客户端), 但这种情况很快就会改变.

因此, 一旦安装了所有工具, 位于服务根中, 我们可以发出以下命令, 从 protos 生成 Go 代码:

protoc --proto_path=.:$GOPATH/src --go_out=. --micro_out=. proto/foobar/foobar.proto

生成的代码必须提交到源代码管理, 以使其他服务在进行服务调用时导入 proto (请参阅上一节调用服务).

现在, 我们知道如何编写服务, 运行服务以及调用其他服务. 我们的一切都触手可及, 但仍有一些缺失的部件来编写应用程序. 其中一部分是存储接口, 它有助于持久数据存储, 即使没有数据库.

存储

在许多其他有用的内置服务中, Micro 包括用于存储数据的持久存储服务.

接口作为构建基块

快速侧记. Micro(server/CLI)和 Go Micro (框架) 以强定义的接口为中心, 这些接口是可插入的, 并为底层分布式系统概念提供了抽象. 这是什么意思?

让我们以我们目前的 存储接口 为例. 它旨在启用具有几个不同实现的服务编写器数据存储:

  • 在内存中
  • 文件存储(micro server 运行时默认存储实现)
  • cockroachdb

同样, 允许您以完全运行时无关的方式运行服务的 运行时 接口具有一些实现:

  • 本地, 只是运行实际流程 - 旨在本地发展
  • kubernetes - 以高可用和分布式方式运行容器

这是跨 Micro 接口的反复出现的主题. micro server 运行时, 让我们看一下默认的存储.

使用存储

将存储与 CLI 一起使用

首先, 让我们来介绍一下最基本的存储 CLI 命令.

要保存值, 我们使用写入命令:

micro store write key1 value1

UNIX 风格中没有输出意味着它被愉快地保存. 读它怎么样?

$ micro store read key1
val1

或者, 为了以更奇特的方式显示它, 我们可以使用 --verbose-v 标志:

KEY    VALUE   EXPIRY
key1   val1    None

当我们使用 --prefix-p 标志时, 此显示特别有用, 它允许我们搜索具有某些前缀的键的条目.

为了演示首先让我们保存一个其他值:

micro store write key2 val2

在此之后, 我们可以列出两个键 key1key2 键, 因为它们都共享通用前缀:

$ micro store read --prefix --verbose key
KEY    VALUE   EXPIRY
key1   val1    None
key2   val2    None

存储里还有更多的东西, 但是这些知识已经让我们很危险了!

将存储与 Go-Micro 一起使用

从 Go Micro 服务访问我们刚刚操作的相同数据不会更容易. 首先, 让我们创建一个条目, 我们的服务可以读取. 这次我们也用 micro store write 指定该命令的表, 因为每个服务在存储中都有自己的表:

micro store write --table go.micro.service.example mykey "Hi there"

让我们修改我们以前编写的示例服务, 以便它不是调用服务, 而是从存储中读取上述值.

package main

import (
    "fmt"
    "time"

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

func main() {
    service := micro.NewService()

    service.Init(micro.Name("go.micro.service.example"))

    records, err := service.Options().Store.Read("mykey")
    if err != nil {
        fmt.Println("Error reading from store: ", err)
    }

    if len(records) == 0 {
        fmt.Println("No records")
    }
    for _, record := range records {
        fmt.Printf("key: %v, value: %v\n", record.Key, string(record.Value))
    }

    time.Sleep(1 * time.Hour)
}

我们快完成了! 但首先, 我们必须学习如何更新服务.

更新和终止服务

现在, 由于示例服务正在运行 (可以通过 micro status 轻松验证), 我们不应该使用 micro run, 而应该部署它.

我们可以简单地发出更新命令 (记住先切换回示例服务的根目录)

micro update .

并验证两者与微服务器输出:

Updating service example-service version latest source /home/username/example-service
Processing update event example-service:latest in namespace default

和微状态:

$ micro status example-service
NAME            VERSION    SOURCE                            STATUS        BUILD    UPDATED        METADATA
example-service    latest    /home/username/example-service    starting    n/a        10s ago        owner=n/a,group=n/a

服务将被更新.

如果由于某种原因的事情进展不太顺利, 我们可以尝试时间测试 “关闭并重新打开” 解决方案, 并完成:

micro kill .
micro run .

从干净的状态重新开始.

因此, 一旦我们更新了示例服务, 我们就应在日志中看到以下内容:

$ micro logs example-service
key: mykey, value: Hi there

好! 示例服务从存储中成功读取值.

客户端

除此之外, 我们还在多语言客户端上工作, 您可以在 github.com/micro/clients 在 github 上找到这些客户端并作出贡献. 我们很想进一步讨论这个问题, 但还没有完全准备好.

进一步阅读

这只是一个简短的入门指南, 用于快速启动和运行 Micro. 当本指南不断升级时, 不时回来了解更多信息. 如果您有兴趣学习更多 micro 魔法, 请查看以下内容:

文档更新时间: 2020-05-30 16:42   作者:kuteng