本项目以电商注册/购物场景,演示基于敏捷开发、微服务架构,在云原生环境下构建高性能、高并发、高可用、弹性伸缩互联网平台的主要技术。基础部分是4个基于SpringBoot
的Dubbo
微服务和1个Web
应用,另外还包括以下技术点:
除PinPoint
外,Dubbo
服务、Web
应用以及所有中间件都支持Docker容器运行,项目包含Dockerfile
、构建Docker
镜像和运行Docker
容器的脚本,无需任何人工部署/配置即可快速运行整个演示应用。
K8s
是一个优秀的容器自动化运维管理平台,简化了容器大规模部署和管理问题,结合Service Mesh
的路由、熔断和限流,微服务架构中的非功能性需求基本都被分拆出来,应用只需聚焦于业务逻辑。- 不可变基础设施、基础设施即代码,基于
Docker
、K8s
、DevOps
的云原生理念,是对运维管理的一场革命。 - 将研发团队持续集成、持续部署、持续交付能力提升一个台阶。
本项目为Mycat
+ ZipKin
运行演示应用提供了K8s
配置文件,可以快速部署到k8s
运行,参考Kubernetes运行演示应用。
关于K8s中部署Dubbo服务 \
Dubbo
服务的注册、发现、负载均衡、故障转移都采用Dubbo自己的机制,不使用K8s Service
。Provider
注册时通过Downward API
得到POD IP
,用POD IP
向Dubbo
注册中心注册,Consumer
从注册中心拿到Provider
的POD IP
,可以直接通讯。Dubbo
服务使用Deployment
部署到K8s
,无需建立K8s Service
,K8s
中基于Deployment
、ReplicaSet
的管理功能都能运用在Dubbo
服务上,包括手动扩缩容以及利用HPA自动扩缩容等。POD
下线、新POD
上线由Dubbo
本身的服务注册发现机制处理。
目前Istio
无法管理Dubbo
流量,本项目演示了使用Istio
对shop-web
进行流量管理。
支付宝的SOFAMesh扩展了Istio
协议,增加了SOFARPC、Dubbo
协议支持,但该项目目前已经作废,直接向Istio
贡献,所以需要花时间等待Istio
接纳这些功能。
本项目演示了使用Mycat
和Sharding-Proxy
进行分库分表,相关概念、部署和使用方法,参考MyCat分库分表概览、Sharding-Proxy分库分表概览,以及它们与阿里云DRDS对比DRDS产品概览。
Mycat
、Sharding-Proxy
和DRDS
都实现了MySQL
协议,成为独立的中间件,将分库分表、读写分离等数据存储的弹性伸缩方案与应用隔离,对应用透明,并且实现语言无关。
Seata
是阿里云分布式事务管理GTS
的开源版,2019年1月开源,1.0.0
版已经发布。相关概念、部署和使用方法参考Seata分布式事务管理框架概览。
Seata
提供AT
、TCC
、Saga
三种柔性事务模式,可以跨微服务和应用实现分布式事务管理,AT
模式对应用几乎透明,使用方便,但目前还存在一些比较严重的问题:
- 性能开销还比较高;
- 在使用
Mycat
、Sharding-Proxy
进行分库分表时,Seata
会产生不少路由到全分片执行的SQL操作,详细参考Seata分布式事务管理框架概览文末;
演示项目支持PinPoint
、SkyWalking
、ZipKin
三种APM工具进行链路跟踪和性能分析,相关概念、部署和使用方法,参考PinPoint部署和使用、SkyWalking部署和使用、ZipKin部署和使用。三种APM工具对比:
- 使用方式:
PinPoint
和SkyWalking
都采用javaagent
方式,对应用代码几乎没有侵入性;ZipKin需要和应用打包到一起,并在应用中完成各种配置,属于强依赖关系; - 链路跟踪能力:整体上看相差不大,基本都参照Google Dapper,也都支持对大量主流框架的跟踪,细节上有些差异:
- 对单次RPC调用分析,
ZipKin
定义的Annotations更精细,参考ZipKin部署和使用; PinPoint
和SkyWalking
都提供将额外方法添加到调用链跟踪的功能,其中PinPoint
对代码完全没有侵入性,SkyWalking
则需要对方法添加注解;SkyWalking
支持在Span
中添加自定义tag功能,利用该功能可以将方法参数值等额外信息记录到Span
中,有利于问题分析;
- 对单次RPC调用分析,
- UI功能:
PinPoint
和SkyWalking
UI功能比较丰富,都提供应用/服务、实例等层级的性能统计,两者各有特色;ZipKin
UI功能最弱,只提供依赖关系、具体调用链查看分析;
额外的UI功能,可以读取APM工具的数据,自定义开发; - 社区支持:
ZipKin
架构灵活、文档完善,社区支持度最高,Spring Cloud
和Service Mesh
(istio)官方提供ZipKin
支持;SkyWalking
是华为员工开发,已成为Apache项目;PinPoint
为韩国公司开源;
云原生环境下K8s
、Istio
为监控、链路跟踪、日志等提供了统一的解决方案,其中ZipKin
和SkyWalking
支持Istio
。
自动化测试、验收测试在敏捷开发、持续集成、持续部署中扮演了重要角色,本项目演示了Postman + Newman
进行接口自动化测试,Fitnesse
进行验收测试(服务接口)。
演示应用支持本地运行、Docker
容器运行、K8s
运行、Istio
运行。另外,演示架构中用到的一些框架,例如MyCat
、ShardingProxy
、Seata
、ZipKin
、SkyWalking
、PinPoint
,都支持开关方式启用和禁用。
- 操作系统
Linux
Windows
: 必须安装一个bash shell
,例如git bash
;Mac
:Mac
自带的sed
与GNU sed
不同,需要在Mac
上安装gnu-seed
:brew install gnu-sed
JDK8+
,Apache Maven
- 容器运行需要安装
Docker
,本地Docker Desktop
环境运行Kubernetes
、Istio
示例,为Docker Desktop
设置6G以上内存。在Mac上为
Docker Desktop
设置5GB内存运行Istio
示例时,曾导致Kubernetes
崩溃,内存改为6G后正常。
./package.sh
为项目编译打包脚本,参数说明:
- 简单运行:不带任何参数执行
package.sh
,仅运行Dubbo微服务和演示应用,使用单个MySQL数据库、Nacos
注册中心,运行4个Dubbo
服务和1个Web应用; - 分库分表:
-mycat
、-sharding-proxy
二选一。-mycat
:使用Mycat
分库分表;-sharding-proxy
:使用Sharding-Proxy
分库分表;
- 分布式事务:
-seata
:使用Seata
分布式事务管理;
- APM全链路跟踪:
-zipkin
、-pinpoint
、-skywalking
三选一。-zipkin
:使用ZipKin
进行链路跟踪、性能分析;-pinpoint
:使用PinPoint
进行链路跟踪、性能分析;-skywalking
:使用SkyWalking
进行链路跟踪、性能分析;
例如./package.sh -mycat -seata -zipkin
- 安装MySQL,建库建表。建库脚本docker/mysql/scripts/1-mydemo.sql,是演示分库分表用的建库脚本,简单方式运行只需要其中
mydemo-dn1
单库即可。 - 部署
nacos
,用于Dubbo
注册中心。参考Nacos快速开始即可。 - 如果要使用到某个中间件,例如
ShardingProxy
、PinPoint
,必须部署配置好。 - 修改项目配置。项目配置都在parent pom.xml中,包括数据库连接信息、
nacos
地址等。 - 编译打包。参考上一节编译打包。
- 按依赖关系依次启动
Dubbo
服务和Web应用:java -jar item-service\target\item-service-0.0.1-SNAPSHOT.jar java -jar stock-service\target\stock-service-0.0.1-SNAPSHOT.jar java -jar user-service\target\user-service-0.0.1-SNAPSHOT.jar java -jar order-service\target\order-service-0.0.1-SNAPSHOT.jar java -jar shop-web\target\shop-web-0.0.1-SNAPSHOT.jar
访问方式:
ShopWeb
:localhost:8090/shopNacos
:localhost:8848/nacos,登录用户/密码:nacos/nacosZipKin
:localhost:9411/zipkinSkyWalking
: localhost:8080Mycat
:数据端口8066
、管理端口9066
,都可以用MySQL
客户端登录访问ShardingProxy
:端口localhost:3307
,可以用MySQL
客户端登录访问
使用Docker
容器运行演示项目非常简单,基础组件无需自行部署、配置,直接运行容器即可。
由于PinPoint
只能采用HBase
存储,本项目未制作Dockerfile
,除PinPoint
外其它组件全部支持容器运行。
- 基础组件构建
Docker
镜像:docker/build-basis.sh
相关脚本和Dockerfile
在docker
目录中,每个基础组件一个子目录,其中build.sh
构建Docker
镜像,run.sh
启动运行Docker
容器,都不需要任何参数。 - 基础组件运行
Docker
容器:docker/deploy-basis.sh
最好根据需要修改deploy-basis.sh
,仅运行本次需要用到的组件。若手工启动,注意按依赖关系依次启动:mysql -> mycat/shardingproxy/nacos/zipkin/skywalking -> seata
。如果启用的组件比较多,例如同时启用
Mycat + Seata + SkyWalking + Nacos
,至少给Docker
分配5G以上内存,否则内存紧张可能导致容器和应用卡死。因为不少组件内存占用比较大,例如Seata
,JVM启动参数-XX:MaxDirectMemorySize
小于1G时一直报OOM异常。 - 为演示应用构建Docker镜像、运行
Docker
容器。- 参考
package.sh
,编译打包; - 使用
./docker/deploy-mydemo.sh
管理Docker
镜像和容器,其操作对象为所有Dubbo
服务和shop-web
应用,参数说明:-build
:构建Docker
镜像;-run
:运行Docker
容器;-stop
:停止Docker
容器;-rm
:删除Docker
容器(需要先停止Docker
容器);-rmi
:删除Docker
镜像(需要先删除Docker
容器);
- 参考
示例:
./docker/build-basis.sh # 为所有基础组件构建Docker镜像
./docker/deploy-basis.sh # 为所有基础组件运行Docker容器
./package.sh -mycat -seata -zipkin # 编译打包演示应用
./docker/deploy-mydemo.sh -build -run # 对演示应用构建Docker镜像、运行容器
./package.sh -shardingproxy -skywalking # 编译打包
./docker/deploy-mydemo.sh -stop -rm -rmi -build -run # 重新构建Docker镜像、运行容器
访问入口:
ShopWeb
:localhost:18090/shopNacos
:localhost:18848/nacos,登录用户/密码:nacos/nacosZipKin
:localhost:19411/zipkinSkyWalking
: localhost:18080Mycat
:数据端口localhost:18066
、管理端口localhost:19066
,都可以用MySQL
客户端登录访问ShardingProxy
:端口localhost:13307
,可以用MySQL
客户端登录访问MySQL
:13306
,可以用MySQL
客户端登录访问
- 部署和启动
Kubernetes
环境。国内环境在Docker Desktop for Windows/Mac
中启用Kubernetes
,参考AliyunContainerService/k8s-for-docker-desktop。 - 参考Docker容器运行,为基础组件
MySQL
、Nacos
、Mycat
、ZipKin
构建Docker
镜像。 无需为演示应用构建Docker
镜像,在下面脚本中会自动重新打包应用,构建Docker
镜像。 - 执行
./k8s/deploy-k8s.sh
在K8s
中部署演示应用。
如果部署过程有错误,执行./k8s/undeploy-k8s.sh
可以将k8s
中已经部署好的部分全部删除。
访问入口:
ShopWeb
:localhost:30090/shopNacos
:localhost:30048/nacos,登录用户/密码:nacos/nacosZipKin
:localhost:30041/zipkinMycat
:数据端口30066
、管理端口30067
,都可以用MySQL客户端登录访问MySQL
:30006
,可以用MySQL客户端登录访问
备注说明:
- 简单起见,本演示项目采用
NodePort
方式向K8s
集群外部暴露端口,方便Docker Desktop
单机模式本地访问,可自行尝试Ingress
等其它K8s
方案。 - 基础组件多为有状态服务,不支持扩缩容(会数据不一致、错误等),另外未采用
PV
、PVC
等,POD
重启所有数据都会丢失。 - 所有
Dubbo
服务支持K8s
扩缩容(user-service
默认部署了2个POD
),可以尝试K8s
管理(在Docker Desktop
中shop-web
不支持扩容,因为使用了NodePort
):# 将user-service扩容到3个POD kubectl scale --replicas=3 -f deployment/svc-user-deployment.yaml # 扩容后可以开启3个窗口,监控user-service POD日志,查看负载均衡分配情况 # 1. 找出user-service的POD kubectl get pods | grep svc-user # 2. 监控每个POD中的容器日志(根据上面语句结果更换容器名称) kubectl logs svc-user-68ff844499-9zqf8 -c svc-user -f kubectl logs svc-user-68ff844499-dgsnx -c svc-user -f ...
- 需要在
Kubernetes
集群中部署Istio
,需要在istio-system
命名空间部署istio-ingressgateway
(Docker Desktop
默认部署和启动istio-ingressgateway
)。 - 在
default
命名空间开启自动注入:kubectl label ns default istio-injection=enabled --overwrite
。 - 参考Docker容器运行,为基础组件
MySQL
、Nacos
、Mycat
、ZipKin
构建Docker
镜像。 - 执行
./istio/deploy-istio.sh
在K8s
中部署演示应用。
如果部署过程有错误,执行./istio/undeploy-istio.sh
可以将k8s
中已经部署好的部分全部删除。 - 在本地
hosts
文件中绑定myshop.com
(Docker Desktop
绑定到本机IP即可)。
通过http://myshop.com/hello/YourName访问。
Dubbo
服务未使用Istio
进行流量管理,与Kubernetes
中部署方案相同(采用Dubbo
自己的服务注册发现机制)。
web-shop
部署了v1
、v2
两个版本,v1
2个POD
,v2
1个POD
,在URL中添加?version=v2
来访问v2
版本。可以分别对v1
、v2
版本进行扩缩容,查看访问效果。