微服务架构简介
第1部分(共10部分)
改编的Ewan Valentine文章。
这是一个由十部分组成的系列,我将尝试每月撰写一次有关在Golang上构建微服务的文章。 我将使用protobuf和gRPC作为主要的传输协议。
我使用的堆栈:golang,mongodb,grpc,docker,Google Cloud,Kubernetes,NATS,CircleCI,Terraform和go-micro。
我为什么需要这个? 由于花了我很长时间才弄清楚并解决累积的问题。 我还想与您分享我在Go和其他新技术上创建,测试和部署微服务的知识。
在这一部分中,我想展示构建微服务的基本概念和技术。 让我们编写一个简单的实现。 该项目将具有以下实体:

要走得更远,您需要安装Golang和必要的库,并创建一个git存储库。
理论
什么是微服务架构?
微服务将单独的功能隔离到服务中,就此服务执行的功能而言,它们是自给自足的。 为了与其他服务兼容,它具有一个众所周知的预定义接口。
微服务使用通过某些中间消息代理传输的消息相互通信。

由于微服务架构,该应用程序无法整体扩展,但可以部分扩展。 例如,如果授权服务比其他服务更频繁地“抽搐”,我们可以增加实例数量。 该概念总体上与云计算和容器化的概念一致。
为什么选择高朗
几乎所有语言都支持微服务,毕竟,微服务是一个概念,而不是特定的结构或工具。 但是,某些语言比其他语言更适合,并且对微服务也有更好的支持。 Golang是一种受支持的语言。
认识protobuf / gRPC
如前所述,微服务被划分为单独的代码库,与微服务相关的重要问题之一是通信。 如果您拥有整体,则可以直接从程序的另一个位置直接调用代码。
为了解决通信问题,我们可以使用传统的REST方法,并通过HTTP以JSON或XML格式传输数据。 但是这种方法有其缺点,例如,在发送消息之前,您必须先对数据进行编码,然后再将其解码回接收端。 这是开销,并且增加了代码的复杂性。
有解决办法! 这是gRPC协议-一种轻量级的,基于二进制的协议,消除了HTTP标头的传输,这将节省一些字节。 未来的HTTP2还暗示使用二进制数据,这再次代表了gRPC。 HTTP2允许双向通信,它很棒!
GRPC还允许您以友好的格式定义服务的接口-这是protobuf 。
练习
创建文件/project/consigment.proto。
Protobuf官方文档
调配协议//consigment.proto syntax = "proto3"; package go.micro.srv.consignment; service ShippingService { rpc CreateConsignment(Consignment) returns (Response) {} } message Consignment { string id = 1; string description = 2; int32 weight = 3; repeated Container containers = 4; string vessel_id = 5; } message Container { string id = 1; string customer_id = 2; string origin = 3; string user_id = 4; } message Response { bool created = 1; Consignment consignment = 2; }
这是一个简单的示例,其中包含要提供给其他服务的服务:service ShippingService,然后我们将定义消息。 Protobuf是一种静态类型的协议,我们可以创建自定义类型(类似于golang中的结构)。 在这里,容器嵌套在批处理中。
安装库,编译器并编译我们的协议:
$ go get -u google.golang.org/grpc $ go get -u github.com/golang/protobuf/protoc-gen-go $ sudo apt install protobuf-compiler $ mkdir consignment && cd consignment $ protoc -I=. --go_out=plugins=grpc:. consignment.proto
输出应为文件:
consignment.pb.go
如果是,则出了点问题。 请注意,参数-I是编译器正在寻找文件的路径,--go_out是将在其中创建新文件的路径。 总是有帮助
$ protoc -h
这是gRPC / protobuf库自动生成的代码,因此您可以将protobuf定义与自己的代码关联。
我们将编写main.go
main.go package seaport import ( "log" "net"
请仔细阅读代码中的注释。 显然,这里我们正在创建实现逻辑,在该逻辑中,我们的gRPC方法使用生成的格式进行交互,并在端口50051上创建了一个新的gRPC服务器。
您可以使用$ go run main.go来运行它 ,但是您将看不到任何东西,也将无法使用它……因此,让我们创建一个客户端以实际运行它。
让我们创建一个命令行界面,该界面需要一个JSON文件并与我们的gRPC服务进行交互。
在根目录中,创建$ mkdir consignment-cli的新子目录。 在此目录中,创建具有以下内容的cli.go文件:
cli.go package main import ( "encoding/json" "io/ioutil" "log" "os" pbf "seaport/consignment" "golang.org/x/net/context" "google.golang.org/grpc" ) const ( address = "localhost:50051" defaultFilename = "consignment.json" )
现在创建一个批处理(consignment-cli / consignment.json):
{ "description": " ", "weight": 100, "containers": [ { "customer_id": "_001", "user_id": "_001", "origin": " " } ], "vessel_id": "_001" }
现在,如果您从海港软件包中运行$ go运行main.go ,然后在单独的终端面板中运行$ go运行cli.go。 您应该看到消息“ Created:true”。
但是我们如何验证确切创建了什么呢? 让我们使用GetConsignments方法更新我们的服务,以便我们可以查看所有创建的批处理。
因此,在这里我们在服务上创建了一个名为GetConsignments的新方法,并且还创建了一个新的GetRequest ,该方法尚未包含任何内容。 我们还在回复邮件中添加了已发送批次的字段。 您会注意到这里的类型具有重复的关键字,直到该类型为止。 您可能已经猜到了,这只是意味着将此字段视为这些类型的数组。
不要急于运行该程序,我们的gRPC方法的实现是基于protobuf库创建的接口的匹配,我们需要确保我们的实现与我们的proto定义相匹配。
在这里,我们包括了新的GetConsignments方法,更新了分别在consignments.proto定义中创建的存储库和接口。 如果再次运行$ go,请再次运行main.go ,该程序将再次运行。
让我们更新cli工具,使其包含调用此方法的功能,并且可以列出我们的参与者:
cli.go package main import ( "encoding/json" "io/ioutil" "log" "os" pbf "seaport/consignment" "golang.org/x/net/context" "google.golang.org/grpc" ) const ( address = "localhost:50051" defaultFilename = "consignment.json" )
将上面的代码添加到cli.go中, 然后再次运行$ go运行cli.go。 客户端将运行CreateConsignment,然后调用GetConsignments。 而且您应该在答案列表中看到该聚会的组成。
因此,我们拥有第一个使用protobuf和gRPC与之交互的微服务和客户端。
本系列的下一部分将包括go-micro集成,这是创建基于gRPC的微服务的强大基础。 我们还将创建第二项服务。 在本系列文章的下一部分,请考虑我们在Docker容器中服务的工作。