什么是微服务?
一种软件体系结构模式,用于将大型单块应用程序分解为更小、可管理的独立服务,这些服务通过语言无关协议进行通信,每个服务的重点做好一件事
微服务的概念并不新鲜,这是对服务导向架构的重新构想,但其方法更整体地与unix进程和管道保持一致。
微服务架构的理念:
- 服务很小 - 细粒度作为单一的商业目的类似于unix哲学“做一件事,做得好”
- 组织文化应该包含部署和测试的自动化。这减轻了管理和运营的负担
- 文化和设计原则应该包含失败和错误,类似于反脆弱系统。
好处:
- 更容易扩展开发 - 团队围绕不同的业务需求进行组织并管理自己的服务。
- 更容易理解 - 微服务要小得多,通常是1000 LOC或更低。
- 更容易部署新版本的服务 - 可以独立部署,扩展和管理服务。
- 改进的容错和隔离 - 关注点的分离可以最大限度地减少一个服务中的问题对另一个服务的影响。
- 提高执行速度 - 团队通过独立开发,部署和管理微服务,更快地满足业务需求。
- 可重用的服务和快速原型 - 微服务中根深蒂固的unix哲学允许您重用现有服务并在更快的速度上构建全新的功能。
micro 与go-micro 的区别
micro
Micro解决了构建微服务系统的关键要求。它采用微服务架构模式并将其转换为一组工具,由以下功能组成:
- API网关:使用服务发现进行动态请求路由的单个入口点。API网关允许您在后端构建可扩展的微服务架构,并在前端整合服务公共API。micro api通过发现和可插拔处理程序提供强大的路由,以提供http,grpc,websockets,发布事件等。
- 交互式CLI:用于直接从终端描述,查询和与您的平台和服务进行交互的CLI。CLI为您提供了您希望了解微服务发生情况的所有命令。它还包括一个交互模式。
- 服务代理:基于 go-micro 构建的透明代理。将服务发现,负载平衡,容错,消息编码,中间件,监控等卸载到单个位置。独立运行或与服务一起运行。
- 模板生成:创建新的服务模板以快速入门。Micro提供用于编写微服务的预定义模板。始终以相同的方式开始,构建相同的服务以提高工作效率。
- SlackOps Bot:在您的平台上运行的机器人,让您可以从Slack本身管理您的应用程序。微型机器人支持ChatOps,使您能够通过消息传递与团队一起完成所有工作。它还包括创建松弛命令作为动态发现的服务的能力。
- Web仪表板: Web仪表板允许您浏览服务,描述其端点,请求和响应格式,甚至可以直接查询它们。仪表板还为想要即时进入终端的开发人员提供了内置的CLI体验。
- Go Framework:利用强大的 go-micro 框架轻松快速地开发微服务。Go Micro抽象出分布式系统的复杂性,并提供更简单的抽象来构建高度可扩展的微服务。
go-micro
go-micro提供了分布式系统开发的核心要求,包括RPC和事件驱动的通信。
主要功能。
- 服务发现 - 自动服务注册和名称解析。服务发现是微服务开发的核心。当服务A需要与服务B通话时,它需要该服务的位置。默认发现机制是多播DNS(mdns),一种零配置系统。您可以选择使用SWIM协议为p2p网络设置八卦,或者为弹性云原生设置设置consul。
- 负载平衡 - 基于服务发现构建的客户端负载平衡。一旦我们获得了服务的任意数量实例的地址,我们现在需要一种方法来决定要路由到哪个节点。我们使用随机散列负载平衡来提供跨服务的均匀分布,并在出现问题时重试不同的节点。
- 消息编码 - 基于内容类型的动态消息编码。客户端和服务器将使用编解码器和内容类型为您无缝编码和解码Go类型。可以编码任何种类的消息并从不同的客户端发送。客户端和服务器默认处理此问题。这包括默认的protobuf和json。
- 请求/响应 - 基于RPC的请求/响应,支持双向流。我们提供了同步通信的抽象。对服务的请求将自动解决,负载平衡,拨号和流式传输。启用tls时,默认传输为http / 1.1或http2。
- Async Messaging - PubSub是异步通信和事件驱动架构的一流公民。事件通知是微服务开发的核心模式。启用tls时,默认消息传递是点对点http / 1.1或http2。
- 可插拔接口 - Go Micro为每个分布式系统抽象使用Go接口。因此,这些接口是可插拔的,并允许Go Micro与运行时无关。您可以插入任何基础技术。在github.com/micro/go-plugins中找到插件 。
开始
准备工作
安装go语言环境,并开启go module功能,可以设置 GOPROXY=https://goproxy.io 环境变量可以永久加速下载包。在环境变量path添加一行配置 %GOPATH%bin这样可以在 go get 的时候安装的软件可以直接使用,不需要切换路径,GOPATH:是工作空间目录
临时加速,只在当前控制台有效:
- win: set GOPROXY=https://goproxy.io
- linux + mac: GOPROXY=https://goproxy.io
1,下载proto,选择自己需要的版本解压放在 %GOPATH%bin下,方便管理:
https://github.com/protocolbuffers/protobuf/releases
2,安装protoc-gen-go:
go get -u github.com/golang/protobuf/protoc-gen-go
3,安装micro:
go get github.com/micro/micro
创建项目
go mod init module名:用于创建go module项目module名:建议和父文件夹的名字相同
在桌面新建文件夹 demo
自定义一个文件夹:打开cmd
进入桌面上的demo
后,运行 go mod init demo,
运行完后新建handler,proto/hello文件夹,以及main.go文件
目录结构定义为:
demo
-handler
-proto
--hello
main.go
go.mod
在proto/hello下新建 hello.proto文件,内容如下
syntax = "proto3"; // 定义protobuf版本
//定义接口
service Hello {
rpc Say (SayRequest) returns (SayResponse); //定义接口方法
}
// SayRequest,SayResponse:可以为不同接口定义输入输出参数
message SayRequest {
string name = 1;
}
message SayResponse {
string msg = 1;
}
打开cmd
进入proto/hello下 编译proto文件:
protoc --micro_out=. --go_out=. hello/hello.proto
然后就会产生两个文件,hello.micro.go,hello.pb.go
在handler下,新建hello_handler.go文件
package handler
import (
"context"
pb "demo/proto/hello"//proto文件的路径
)
type hello struct{}
func NewHelloApi() pb.HelloHandler {
return &hello{}
}
func (self *hello) Say(ctx context.Context, req *pb.SayRequest, resp *pb.SayResponse) error {
resp.Msg = "hello " + req.Name
return nil
}
编写main:
package main
import (
"fmt"
"github.com/micro/go-micro"
"log"
"demo/handler"
hello_api "demo/proto/hello"
)
const (
ServiceName = "demo.api"
)
func main() {
service := micro.NewService(
micro.Name(ServiceName),
micro.Version("1.0.0"),
)
service.Init()
//挂载服务
err := hello_api.RegisterHelloHandler(service.Server(), handler.NewHelloApi())
if err != nil {
fmt.Println(err)
}
// 启动api服务
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
更新依赖:
go mod tidy
运行:
go run main.go
测试
使用 micro提供的工具
micro call demo.api Hello.Say '{"name":"John"}'
使用 postman
运行 网关:
micro api --namespace=demo
测试接口
细节
运行网关的时候:添加namespace这个参数,该参数值( demo)和 ServiceName(demo.api)的前缀必须要一致,而后面的字符就是访问该服务的前缀 ,例如:api ,所以通过网关访问就是:http://127.0.0.1:8080/api/hello/say,
hello:是定义的接口,
say:是该接口提供的方法