1-1 本课的go微服务有什么不同?
聚焦于容器化可观测的购物微服务系统实战,通过介绍Go语言的应用趋势、容器化优势及微服务适用性,旨在解决学习微服务过程中遇到的难点。课程内容涵盖微服务整体架构、技术工具框架及容器平台等关键技术,包括API网关层、接口层、应用层及领域层等模块。
第2章 Go微服务介绍与容器化入门
2-1 微服务基础介绍
微服务介绍
- 微服务首先他是一种架构模式
- 微服务相比较单体架构,微服务架构更独立,能够单独更新和发布
- 微服务里面的服务仅仅用于某一个特定的业务功能
- 特点
- 逻辑清晰
- 快速迭代
- 多语言灵活组合
微服务与DDD
领域驱动设计(Domain Driven Design,简称DDD )
还有个定律:康威定律(Conway’s Law)。就是说组织架构对应我们微服务拆分。
DDD的作用:真正决定软件复杂性的是设计方法
有助于指导我们确定系统边界
能够聚焦在系统核心元素上
帮助我们拆分系统
DDD常用概念-领域
领域:领域是有范围界限的,也可以说是有边界的
核心域:核心域是业务系统的核心价值
通用子域:所有子域的消费者,提供着通用服务(比如电商领域的短信、邮件就属于这个)
支撑子域:专注于业务系统的某一重要的业务
DDD常用概念-界限上下文
理解∶语文中的语境的意思
方式∶领域+界限上下文
目的:不在于如何划分边界,而在于如何控制边界
DDD常用概念-领域模型
理解∶领域模型是对我们软件系统中要解决问题的抽象表达。
领域∶反应的是我们业务上需要解决的问题
模型:我们针对该问题提出的解决方案、
2-2 微服务必备技能Docker入门介绍
2-3 go-micro基础之 grpc proto
2-4 go-micro 组件架构及通讯原理
2-5 go-micro 入门案例编写
2-6 go-micro 入门案例验证
第3章 微服务模块开发
micro_practice/user at main · yunixiangfeng/micro_practice · GitHub
3-1 micro new 和项目目录创建
开发目录和依赖包
项目目录搭建
# 使用容器方式micro/micro 这个容器创建不了--type=api 只能创建service 估计版本问题
sudo docker pull micro/micro
sudo docker run --rm -v $(pwd):$(pwd) -w $(pwd) micro/micro new user(user是我们需要开发的模块)
# 使用容器方式microhq/micro 这个容器暂时用不起来 老报错GOPATH路径找不到 改天研究一下
sudo docker run --rm -v $(pwd):$(pwd) -w $(pwd) microhq/micro new user(user是我们需要开发的模块)
# 直接安装环境 验证micro是否安装成功:micro --version
# 官网https://micro.mu/introduction 这里的最新版本已经不支持consul建议使用etcd
go get github.com/micro/micro
micro new user
Go module的使用
GORM基本介绍及使用
3-2 go mod 私有化设置 和 gorm 说明
3-3 编写proto并自动生成代码
user.proto
syntax = "proto3";
package go.micro.service.user;
service User {
//注册
rpc Register(UserRegisterRequest) returns (UserRegisterResponse) {}
//登录
rpc Login(UserLoginRequest) returns (UserLoginResponse) {}
//查询用户信息
rpc GetUserInfo(UserInfoRequest) returns (UserInfoResponse) {}
}
message UserInfoRequest {
string user_name = 1;
}
message UserInfoResponse {
int64 user_id = 1;
string user_name = 2;
string first_name = 3;
}
message UserRegisterRequest {
string user_name = 1;
string first_name = 2;
string pwd = 3;
//... 其它信息
}
message UserRegisterResponse {
string message = 1;
}
message UserLoginRequest {
string user_name = 1;
string pwd = 2;
}
message UserLoginResponse {
bool is_success = 1;
}
protoc -I ./ --go_out=./ --micro_out=./ ./proto/user/*.proto
3-4 domain对数据库和模型进行操作
D:\Workspace\Go\src\micro_practice\user\domain\service\user_data_service.go
3-5 编写Handel要暴露的服务
D:\Workspace\Go\src\micro_practice\user\handler\user.go
D:\Workspace\Go\src\micro_practice\user\main.go
3-6 go-micro开发流程梳理
D:\Workspace\Go\src\micro_practice\user\main.go
3-7 dockerfile 打包 user 功能
D:\Workspace\Go\src\micro_practice\user\Dockerfile
FROM alpine
ADD user /user
ENTRYPOINT [ "/user" ]
D:\Workspace\Go\src\micro_practice\user\Makefile
GOPATH:=$(shell go env GOPATH)
.PHONY: proto
proto:
sudo docker run --rm -v $(shell pwd):$(shell pwd) -w $(shell pwd) -e ICODE=CF388DF1EF1C5EBE cap1573/cap-protoc -I ./ --go_out=./ --micro_out=./ ./proto/user/*.proto
.PHONY: build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o user *.go
.PHONY: test
test:
go test -v ./... -cover
.PHONY: dockerBuild
dockerBuild:
sudo docker build -t user:latest .
make proto
make build
make dockerBuild
第4章 注册配置中心实现
https://github.com/yunixiangfeng/micro_practice/tree/main/category
4-1 注册中心的基本介绍
注册中心Consul原理介绍
Consul基本介绍
调用过程原理讲解及集群版本原理
Consul的安装和使用
注册中心Consul基本介绍
Consul是一种服务网格解决方案
提供具有服务发现,配置和分段功能的全功能控制平面
Consul 附带一个简单的内置代理,可以开箱即用
注册中心Consul关键功能
服务发现:客户端可以注册服务,程序可以轻松找到它们所依赖的服务
运行状况检查: Consul 客户端可以提供任意数量的运行状况检查
KV存储:应用程序可以将 Consul 的层级键/值存储用于任何目的包括动态配置,功能标记,协调,领导者选举等
注册中心Consul两个重要协议
Gossip Protocol(八卦协议)
Raft Protocol(选举协议)
4-2 注册中心的安装
注册中心Consul安装
docker pull cap1573/consu
docker run -d -p 8500:8500 cap1573/consul
Consul web 管理界面简单说明
4-3 分类模块目录结构生成
4-4 编写对外暴露的服务
D:\Workspace\Go\src\micro_practice\category\Makefile
GOPATH:=$(shell go env GOPATH)
.PHONY: proto
proto:
sudo docker run --rm -v $(shell pwd):$(shell pwd) -w $(shell pwd) -e ICODE=CF388DF1EF1C5EBE cap1573/cap-protoc -I ./ --micro_out=./ --go_out=./ ./proto/category/category.proto
.PHONY: build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o category-service *.go
.PHONY: test
test:
go test -v ./... -cover
.PHONY: docker
docker:
docker build . -t category-service:latest
D:\Workspace\Go\src\micro_practice\category\proto\category\category.proto
syntax = "proto3";
package go.micro.service.category;
service Category {
rpc CreateCategory(CategoryRequest) returns (CreateCategoryResponse) {}
rpc UpdateCategory(CategoryRequest) returns (UpdateCategoryResponse) {}
rpc DeleteCategory(DeleteCategoryRequest) returns (DeleteCategoryResponse){}
rpc FindCategoryByName(FindByNameRequest) returns (CategoryResponse) {}
rpc FindCategoryByID(FindByIdRequest) returns (CategoryResponse){}
rpc FindCategoryByLevel(FindByLevelRequest) returns (FindAllResponse) {}
rpc FindCategoryByParent(FindByParentRequest) returns (FindAllResponse) {}
rpc FindAllCategory(FindAllRequest) returns (FindAllResponse){}
}
message CategoryRequest {
string category_name = 1;
uint32 category_level = 2;
int64 category_parent = 3;
string category_image = 4;
string category_description = 5;
}
message CreateCategoryResponse {
string message =1 ;
int64 category_id =2;
}
message UpdateCategoryResponse {
string message = 1;
}
message DeleteCategoryRequest {
int64 category_id =1 ;
}
message DeleteCategoryResponse {
string message =1;
}
message FindByNameRequest {
string category_name =1;
}
message CategoryResponse {
int64 id = 1;
string category_name =2;
uint32 category_level = 3;
int64 category_parent =4;
string category_images =5;
string category_description =6;
}
message FindByIdRequest {
int64 category_id = 1;
}
message FindByLevelRequest {
uint32 level =1;
}
message FindByParentRequest {
int64 parent_id =1;
}
message FindAllRequest {
}
message FindAllResponse {
repeated CategoryResponse category =1;
}
protoc -I ./ --micro_out=./ --go_out=./ ./proto/category/category.proto
4-5 数据库进行交互
D:\Workspace\Go\src\micro_practice\category\domain\model\category.go
D:\Workspace\Go\src\micro_practice\category\domain\repository\category_repository.go
D:\Workspace\Go\src\micro_practice\category\domain\service\category_data_service.go
4-6 编写Handler
D:\Workspace\Go\src\micro_practice\category\handler\category.go
4-7 配置中心/注册中心的使用
D:\Workspace\Go\src\micro_practice\category\main.go
package main
import (
"git.imooc.com/coding-447/category/common"
"git.imooc.com/coding-447/category/domain/repository"
service2 "git.imooc.com/coding-447/category/domain/service"
"git.imooc.com/coding-447/category/handler"
"github.com/jinzhu/gorm"
"github.com/micro/go-micro/v2"
log "github.com/micro/go-micro/v2/logger"
"github.com/micro/go-micro/v2/registry"
"github.com/micro/go-plugins/registry/consul/v2"
_ "github.com/jinzhu/gorm/dialects/mysql"
category "git.imooc.com/coding-447/category/proto/category"
)
func main() {
//配置中心
consulConfig,err := common.GetConsulConfig("127.0.0.1",8500,"/micro/config")
if err !=nil {
log.Error(err)
}
//注册中心
consulRegistry := consul.NewRegistry(func(options *registry.Options) {
options.Addrs = []string{
"127.0.0.1:8500",
}
})
// New Service
service := micro.NewService(
micro.Name("go.micro.service.category"),
micro.Version("latest"),
//这里设置地址和需要暴露的端口
micro.Address("127.0.0.1:8082"),
//添加consul 作为注册中心
micro.Registry(consulRegistry),
)
//获取mysql配置,路径中不带前缀
mysqlInfo := common.GetMysqlFromConsul(consulConfig,"mysql")
//连接数据库
db,err := gorm.Open("mysql",mysqlInfo.User+":"+mysqlInfo.Pwd+"@/"+mysqlInfo.Database+"?charset=utf8&parseTime=True&loc=Local")
if err !=nil {
log.Error(err)
}
defer db.Close()
//禁止复表
db.SingularTable(true)
//rp := repository.NewCategoryRepository(db)
//rp.InitTable()
// Initialise service
service.Init()
categoryDataService := service2.NewCategoryDataService(repository.NewCategoryRepository(db))
err = category.RegisterCategoryHandler(service.Server(),&handler.Category{CategoryDataService:categoryDataService})
if err != nil {
log.Error(err)
}
// Run service
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
4-8 完善Consul配置
D:\Workspace\Go\src\micro_practice\category\common\config.go
D:\Workspace\Go\src\micro_practice\category\common\mysql.go
D:\Workspace\Go\src\micro_practice\category\common\swap.go
consul 新建key/value
第5章 链路追踪观望台
5-1 jaeger 原理
链路追踪作用与特性
链路追踪 jaeger 术语,原理,组件,安装
在代码中使用链路追踪jaeger
微服务链路追(jaeger)踪作用
它是用来监视和诊断基于微服务的分布式系统
用于服务依赖性分析,辅助性能优化
微服务链路追踪(jaeger)主要特性
高扩展性
原生支持 OpenTracing
可观察性
微服务链路追踪(jaeger)-术语 Span
Jaeger 中的逻辑工作单元
具有操作名称,操作的开始时间和持续时间
跨度可以嵌套并排序以建立因果关系模型
Operation name:操作名称(也可以称作 Span name
Start timestamp:起始时间
Finish timestamp:结束时间
Span tag:一组键值对构成的Span 标签集合
Span log:一组Span 的日志集合
SpanContext:span 上下文对象
References( Span 间关系):相关的零个或者多个 Span
微服务链路追踪(jaeger)的五个重要组件
Jaeger-client (客户端库)
Agent(客户端代理)
Collector ( 数据收集处理)
Data Store (数据存储)
UI(数据查询与前端界面展示)
微服务链路追踪(jaeger)的安装
docker pull cap1573/jaeger
docker run -d --name jaeger -p 6831:6831/udp -p 16686:166861 cap1573/jaeger
5-2 商品领域 proto编写
D:\Workspace\Go\src\micro_practice\product\proto\product\product.proto
syntax = "proto3";
package go.micro.service.product;
service Product {
rpc AddProduct(ProductInfo) returns (ResponseProduct){}
rpc FindProductByID(RequestID) returns (ProductInfo){}
rpc UpdateProduct(ProductInfo) returns (Response) {}
rpc DeleteProductByID(RequestID) returns (Response) {}
rpc FindAllProduct(RequestAll) returns (AllProduct){}
}
message ProductInfo {
int64 id = 1;
string product_name = 2;
string product_sku = 3;
double product_price = 4;
string product_description = 5;
int64 product_category_id = 6;
repeated ProductImage product_image = 7;
repeated ProductSize product_size = 8;
ProductSeo product_seo = 9;
}
message ProductImage {
int64 id = 1;
string image_name = 2;
string image_code = 3;
string image_url = 4;
}
message ProductSize{
int64 id = 1;
string size_name = 2;
string size_code = 3;
}
message ProductSeo {
int64 id = 1;
string seo_title = 2;
string seo_keywords = 3;
string seo_description =4;
string seo_code = 6;
}
message ResponseProduct {
int64 product_id = 1;
}
message RequestID {
int64 product_id = 1;
}
message Response {
string msg = 1;
}
message RequestAll{
}
message AllProduct{
repeated ProductInfo product_info =1;
}
D:\Workspace\Go\src\micro_practice\product\Makefile
.PHONY: proto
proto:
sudo docker run --rm -v $(shell pwd):$(shell pwd) -w $(shell pwd) -e ICODE=CF388DF1EF1C5EBE cap1573/cap-protoc -I ./ --micro_out=./ --go_out=./ ./proto/product/product.proto
.PHONY: build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o product-service *.go
.PHONY: test
test:
go test -v ./... -cover
.PHONY: docker
docker:
docker build . -t product-service:latest
5-3 商品领域 模型编写
D:\Workspace\Go\src\micro_practice\product\domain\model\product.go
D:\Workspace\Go\src\micro_practice\product\domain\model\product_size.go
D:\Workspace\Go\src\micro_practice\product\domain\model\product_seo.go
D:\Workspace\Go\src\micro_practice\product\domain\model\product_image.go
5-4 商品领域repository 开发
D:\Workspace\Go\src\micro_practice\product\domain\repository\product_repository.go
5-5 商品领域 service开发
D:\Workspace\Go\src\micro_practice\product\domain\service\product_data_service.go
5-6 商品领域 handler开发
D:\Workspace\Go\src\micro_practice\product\handler\product.go
5-7 商品领域 链路追踪使用
D:\Workspace\Go\src\micro_practice\product\common\config.go
D:\Workspace\Go\src\micro_practice\product\common\mysql.go
D:\Workspace\Go\src\micro_practice\product\common\swap.go
D:\Workspace\Go\src\micro_practice\product\common\jaeger.go
package common
import (
"github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go"
"github.com/uber/jaeger-client-go/config"
"io"
"time"
)
//创建链路追踪实例
func NewTracer(serviceName string, addr string) (opentracing.Tracer, io.Closer, error) {
cfg := &config.Configuration{
ServiceName:serviceName,
Sampler:&config.SamplerConfig{
Type: jaeger.SamplerTypeConst,
Param: 1,
},
Reporter: &config.ReporterConfig{
BufferFlushInterval: 1*time.Second,
LogSpans: true,
LocalAgentHostPort: addr,
},
}
return cfg.NewTracer()
}
D:\Workspace\Go\src\micro_practice\product\main.go
D:\Workspace\Go\src\micro_practice\product\productClient.go
package main
import (
"context"
"fmt"
"git.imooc.com/coding-447/product/common"
go_micro_service_product "git.imooc.com/coding-447/product/proto/product"
"github.com/micro/go-micro/v2"
"github.com/micro/go-micro/v2/registry"
consul2 "github.com/micro/go-plugins/registry/consul/v2"
opentracing2 "github.com/micro/go-plugins/wrapper/trace/opentracing/v2"
"github.com/opentracing/opentracing-go"
"log"
)
func main() {
//注册中心
consul := consul2.NewRegistry(func(options *registry.Options) {
options.Addrs = []string{
"127.0.0.1:8500",
}
})
//链路追踪
t,io,err:=common.NewTracer("go.micro.service.product.client","localhost:6831")
if err !=nil {
log.Fatal(err)
}
defer io.Close()
opentracing.SetGlobalTracer(t)
service := micro.NewService(
micro.Name("go.micro.service.product.client"),
micro.Version("latest"),
micro.Address("127.0.0.1:8085"),
//添加注册中心
micro.Registry(consul),
//绑定链路追踪
micro.WrapClient(opentracing2.NewClientWrapper(opentracing.GlobalTracer())),
)
productService:=go_micro_service_product.NewProductService("go.micro.service.product",service.Client())
productAdd := &go_micro_service_product.ProductInfo{
ProductName: "imooc",
ProductSku: "cap",
ProductPrice: 1.1,
ProductDescription: "imooc-cap",
ProductCategoryId: 1,
ProductImage: []*go_micro_service_product.ProductImage{
{
ImageName: "cap-image",
ImageCode: "capimage01",
ImageUrl: "capimage01",
},
{
ImageName: "cap-image02",
ImageCode: "capimage02",
ImageUrl: "capimage02",
},
},
ProductSize: []*go_micro_service_product.ProductSize{
{
SizeName: "cap-size",
SizeCode: "cap-size-code",
},
},
ProductSeo: &go_micro_service_product.ProductSeo{
SeoTitle: "cap-seo",
SeoKeywords: "cap-seo",
SeoDescription: "cap-seo",
SeoCode: "cap-seo",
},
}
response,err:=productService.AddProduct(context.TODO(),productAdd)
if err !=nil {
fmt.Println(err)
}
fmt.Println(response)
}
jager ui
find trace
链路追踪数据写入的过程中可以加入kafaka缓冲压力
可以通过链路追踪发现我们是否有循环调用
在链路中如非必要尽量避免带入异步场景的span
链路追踪还有哪些场景?
异步链路如何实现?
第6章 熔断,限流,负载均衡
6-1 熔断器作用和原理
6-2 限流的作用和原理
6-3 负载均衡作用和原理
6-4 微服务API网关
6-5 server端 proto 文件编写
6-6 service 端 model 开发
6-7 server端 repository 开发
6-8 server端口service开发
6-9 common 独立使用
6-10 server端 handler开发
6-11 server 端 添加限流
6-12 购物车API层 添加熔断
6-13 购物车API层 添加负载均衡
6-14 API 网关及熔断看板使用
第7章 性能监控能力完善
7-1 监控系统prometheus基本介绍
7-2 docker-compose 基础介绍
7-3 docker-compose 具体使用的例子
7-4 订单领域 proto 开发
7-5 订单领域 model 开发
7-6 订单领域 repository 开发
7-7 订单领域 service 开发
7-8 微服务handler 代码编写
7-9 订单main.go 添加 prometheus 监控
7-10 监控系统可视化
第8章 服务级观测台完成
8-1 日志系统ELK 架构介绍
8-2 Filebeat 工作原理及注意事项
8-3 Logstash 工作原理
8-4 docker-compose 配置安装 ELK
8-5 国际支付 PayPal 账户和沙盒环境指南
8-6 日志zap 封装
8-7 支付服务端 Proto 开发
8-8 支付信息 handler 开发
8-9 支付服务端 main.go 文件开发
8-10 FileBeat 下载和使用说明
8-11 支付API proto 开发
8-12 国际支付PayPal handler 退款业务开发(上)
8-13 国际支付PayPal handler 退款业务开发(下)
8-14 支付PayPal main.go 开发及效果展示(上)
8-15 支付PayPal main.go 开发及效果展示(下)
8-16 幂等性介绍
8-17 Kibana日志可视化展示
第9章 项目部署,完成闭环
9-1 k8s 基础入门及架构介绍
9-2 k8s api server 架构及创建应用原理
9-3 k8s 不同种类controller 作用讲解
9-4 k8s 安装-阿里云创建ECS
9-5 k8s 安装 服务器基础安装
9-6 k8s 安装初始化Master 节点
9-7 k8s node 节点加入集群
9-8 kompose 介绍和说明
9-9 kubectl 常用命令讲解