本项目以电商注册/购物场景,演示基于敏捷开发、微服务架构,在云原生环境下构建高性能、高并发、高可用、弹性伸缩互联网平台的主要技术。基础部分是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和SkyWalkingUI功能比较丰富,都提供应用/服务、实例等层级的性能统计,两者各有特色;ZipKinUI功能最弱,只提供依赖关系、具体调用链查看分析;
额外的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,都支持开关方式启用和禁用。
- 操作系统
LinuxWindows: 必须安装一个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版本进行扩缩容,查看访问效果。













