1. 概述
前言: 微型入门指南
1.1. 什么是 Micro
Micro 是一个用于构建和管理分布式系统的系统.
Micro 的主要组件如下:
- 运行时: 用于管理服务包括 auth, config, discovery, networking 的运行时环境.
- 框架: 用于编写要在运行时运行的服务的 Go 框架.
- 客户端: 多语言客户端, 使其他程序能够访问微服务.
1.2. 安装
使用 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"
1.3. 运行服务
在深入了解编写服务之前, 让我们运行一个现有的服务, 因为它只是几个命令!
首先, 我们必须开始. 执行此操作的命令是:
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
因此, 由于我们的服务运行的很好, 让我们尝试调用它! 这就是该服务存在的原因.
1.4. 调用服务
我们有几个选项可以调用我们在运行的服务 micro server
1.4.1. 通过 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 以查看实时信息.
1.5. 使用 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 服务!
1.6. 从其他语言
在 客户端仓库 中, 有用于各种语言和框架的 micro 客户端. 它们旨在轻松连接到实时 micro 环境或本地环境, 但稍后将提供更多有关环境.
1.7. 编写服务
要建立新服务的脚手架, 可以使用该命令 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 (请参阅上一节调用服务).
现在, 我们知道如何编写服务, 运行服务以及调用其他服务. 我们的一切都触手可及, 但仍有一些缺失的部件来编写应用程序. 其中一部分是存储接口, 它有助于持久数据存储, 即使没有数据库.
1.8. 存储
在许多其他有用的内置服务中, Micro 包括用于存储数据的持久存储服务.
1.8.1. 接口作为构建基块
快速侧记. Micro(server/CLI)和 Go Micro (框架) 以强定义的接口为中心, 这些接口是可插入的, 并为底层分布式系统概念提供了抽象. 这是什么意思?
让我们以我们目前的 存储接口 为例. 它旨在启用具有几个不同实现的服务编写器数据存储:
- 在内存中
- 文件存储(micro server 运行时默认存储实现)
- cockroachdb
同样, 允许您以完全运行时无关的方式运行服务的 运行时 接口具有一些实现:
- 本地, 只是运行实际流程 - 旨在本地发展
- kubernetes - 以高可用和分布式方式运行容器
这是跨 Micro 接口的反复出现的主题. micro server
运行时, 让我们看一下默认的存储.
1.9. 使用存储
1.9.1. 将存储与 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
在此之后, 我们可以列出两个键 key1
和 key2
键, 因为它们都共享通用前缀:
$ micro store read --prefix --verbose key
KEY VALUE EXPIRY
key1 val1 None
key2 val2 None
存储里还有更多的东西, 但是这些知识已经让我们很危险了!
1.9.2. 将存储与 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)
}
我们快完成了! 但首先, 我们必须学习如何更新服务.
1.10. 更新和终止服务
现在, 由于示例服务正在运行 (可以通过 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
好! 示例服务从存储中成功读取值.
1.11. 客户端
除此之外, 我们还在多语言客户端上工作, 您可以在 github.com/micro/clients 在 github 上找到这些客户端并作出贡献. 我们很想进一步讨论这个问题, 但还没有完全准备好.
1.12. 进一步阅读
这只是一个简短的入门指南, 用于快速启动和运行 Micro. 当本指南不断升级时, 不时回来了解更多信息. 如果您有兴趣学习更多 micro 魔法, 请查看以下内容: