微服务与容器化
微服务介绍
- 什么是微服务
- 它是一种架构模式
- 相比较单体架构,微服务架构更独立,能够单独更新和发布
- 微服务里面的服务仅仅用于某一个特定的业务功能
- 为什么需要微服务
- 逻辑清晰
- 快速迭代
- 多语言灵活组合
- 微服务中的DDD是什么
- 领域驱动设计(Domain Driven Design,简称DDD) —— 真正决定软件复杂性的是设计方法
- 作用
- 有助于知道我们确定系统边界
- 能够聚焦在系统核心元素上
- 帮助我们拆分系统
- 常用概念
- 领域
- 领域:领域是有范围界限的,也可以说是有边界的
- 核心域:核心域是业务系统的核心价值
- 通用子域:所有子域的消费者,提供着通用服务
- 支撑子域:专注与业务系统的某一项重要的业务
- 界限上下文
- 理解:描述子
- 方式:领域 + 界限上下文
- 目的:不在于如何划分边界,而是在于如何控制边界
- 领域模型
- 理解:领域模型是对我们软件系统中要解决问题的抽象表达
- 领域:反应的是我们业务上需要解决的问题
- 模型:我们针对该问题提出的解决方案
- 领域
- DDD域微服务四层架构
- 作用
- 还有个定律:康威定律(Conway's Law),通俗讲就是组织架构要和微服务的拆分对应
- 领域驱动设计(Domain Driven Design,简称DDD) —— 真正决定软件复杂性的是设计方法
- 微服务的设计原则
- 要领域驱动设计,而不是数据驱动设计,也不是界面驱动设计。
- 数据驱动设计:比如根据模块先设计数据库,然后再拆分数据库...
- 要边界清晰的微服务,而不是泥球小单体
- 要职能清晰分明,而不是什么都放的大箩筐
- 要做自己能hold住的微服务,而不是过度拆分的微服务
- 要领域驱动设计,而不是数据驱动设计,也不是界面驱动设计。
Docker
- 为什么需要Docker
- 软件更新发布及部署低效,过程繁琐且需要人工介入
- 环境一致性难以保证,不同环境之间迁移成本太高
- 构建容易分发简单
- 应用场景
- 构建运行环境
- 微服务
- CI(持续集成) / CD(持续部署)
- Docker安装
- MacOS安装:
http://desktop.docker.com/mac/main/amd64/Docker.dmg?utm_source=docker&utm_medium=webreferral&utm_campaign=dd-smartbutton&utm_location=module
- Linux 安装:
yum install -y docker
- MacOS安装:
- Docker的重要概念
- 客户端Client:可运行docker指令
- 服务器进程(Docker Daemon):管理镜像和容器
- 镜像仓库:存储镜像的仓库
- 架构图
- Docker常用命令
- Docker仓库操作:
pull, push
- Docker镜像管理:
images, rmi (删除镜像), build
- Docker生命周期管理:
run, start, stop, rm
- Docker仓库操作:
go-micro 之 grpc 和 ProtoBuf
-
RPC和gRPC介绍
- RPC(好处:简单、通用、安全、高效)
- RPC代指远程过程调用(Remote Procedure Call)
- 包含了传输协议和编码(对象序列号)协议
- 允许运行于一台计算机的程序调用另一台计算机的子程序
- gRPC()
- gRPC是一个高性能、开源、通用的RPC框架
- 基于HTTP2.0协议标准设计开发
- 支持多种语言,默认采用Protocol Buffer数据序列化协议
- gRPC基本调用流程解析
- RPC(好处:简单、通用、安全、高效)
-
ProtoBuf及详细语法介绍
- ProtoBuf介绍
- 是一种轻便高效的序列化结构化数据的协议
- 通常是用在存储数据和需要远程数据通信的程序上
- 跨语言、更小(相比json xml等)、更快、更简单
- 为什么使用ProtoBuf
- 加速站点之间数据传输速度
- 解决数据传输不规范问题
- ProtoBuf常用概念
- Message定义:描述了一个请求或响应的消息格式
- Message中字段修饰符
singular
:表示成员有0个或者1个,一般省略不写repeated
:表示该字段可以包含0~N个元素
- Message中字段修饰符
- 字段标识:消息的定义中,每个字段都有一个唯一的数值标签
- 常用数据类型:double、float、int32/64、bool、string、bytes
- Service服务定义:在Service中可以定义一个RPC服务接口
- Message定义:描述了一个请求或响应的消息格式
- proto示例
- ProtoBuf介绍
go-micro 组件架构及通讯原理
- Micro是什么
- 是用来构建和管理分布式程序的系统
- Runtime(运行时):用来管理配置,认证,网络等
- Runtime(运行时)介绍
- 它是工具集,工具名称是 ‘micro’,在命令行使用
- 官方docker版本是
docker pull micro/micro
- Runtime(运行时)组成
- api:api网关
- broker:允许一步消息的消息代理
- network:通过微网络服务构建多云网络
- new:服务模版生成器
- proxy:建立在 Go Micro 上的透明服务代理
- registry:一个服务资源管理器
- store:简单的状态存储
- web:web仪表板浏览服务
- Runtime(运行时)介绍
- Framework(程序开发框架):用来方便编写微服务,go-micro就是一个框架
- Framework(go-micro)介绍
- 它是对分布式系统的高度抽象
- 提供分布式系统开发的核心库
- 可插拔的架构,按需使用
- Framework(go-micro)组件
- 注册(Register):提供了服务发现机制
- 选择器(Selector):能够实现负载均衡
- 传输(Transport):服务与服务之间通信接口
- Broker:提供异步通信的消息发布/订阅接口
- 编码(Codec):消息传输到两端时进行编码与解码
- Server(服务端)、Client(客户端)
- Framework(go-micro)组件架构图
- Framework(go-micro)通信图
- Framework(go-micro)介绍
- Clients(多语言客户端):支持多语言访问服务端
go-micro 案例编写
- protoc 生成 rpc 服务
syntax = "proto3"; package go.micro.service.elasticnotes; option go_package = "./proto/jartin"; service Jartin { rpc SayHello(SayRequest) returns (SayResponse) {} } message SayRequest { string message = 1; } message SayResponse { string answer = 1; } // bash // protoc --go_out=. --go-grpc_out=. ./proto/jartin/elasticnotes.proto
-
编写server端
package main import ( "fmt" "github.com/micro/go-micro/v2" "newmicro/proto/jartin" ) // 实现接口的结构体 type JartinServer struct { } // 需要实现的方法 func (c *JartinServer) SayHello(ctx context.Context, req *SayRequest, res *SayResponse) error { res.Answer = "输出结果,服务连接成功!" } func main() { // 创建新服务 service := micro.NewService( micro.Name("jartin.elasticnotes.server"), ) // 初始化方法 service.Init() // 注册服务 jartin.RegisterJartinServer(service.Server(), new()) // 运行服务 if err := service.Run(); err != nil { fmt.Println(err) } }
-
编写Client端
package main import ( "context" "fmt" "github.com/micro/go-micro/v2" "newmicro/proto/jartin" ) func main() { // 实例化 service := micro.NewService( micro.Name("jartin.elasticnotes.client"), ) // 初始化 service.Init() // jar := jartin.JartinServer("jartin.elasticnotes.server", service.Client()) res, err := jar.SayHello(context.TODO(), &jartin.SayRequest{Message: "接收到了"}) if err != nil { fmt.Println(err) } }