Spring Cloud基于Spring Boot开发,提供一套完整的微服务解决方案,具体包括服务注册与发现,配置中心,全链路监控,API网关,熔断器,远程调用框架,工具客户端等选项中立的开源组件,而且能够根据需求对部分组件进行扩展和替换。
java
Service Mesh,这里以Istio(目前Service Mesh具体落地实现的一种,且呼声最高)为例简要说明其功能。 Istio 有助于下降这些部署的复杂性,并减轻开发团队的压力。它是一个彻底开源的服务网格,能够透明地分层到现有的分布式应用程序上。它也是一个平台,包括容许它集成到任何日志记录平台、遥测或策略系统的 API。Istio的多样化功能集使你可以成功高效地运行分布式微服务架构,并提供保护、链接和监控微服务的统一方法。
git
从上面的简单介绍中,咱们能够看出为何会存在要把Spring Cloud体系的应用迁移到Service Mesh这样的需求,总结下来,有四方面的缘由:
github
来简单看一下他们的功能对比:spring
功能列表 | Spring Cloud | Isito |
---|---|---|
服务注册与发现docker |
支持,基于Eureka,consul等组件,提供server,和Client管理安全 |
支持,基于XDS接口获取服务信息,并依赖“虚拟服务路由表”实现服务发现bash |
链路监控网络 |
支持,基于Zikpin或者Pinpoint或者Skywalking实现架构 |
支持,基于sideCar代理模型,记录网络请求信息实现app |
API网关 |
支持,基于zuul或者spring-cloud-gateway实现 |
支持,基于Ingress gateway以及egress实现 |
熔断器 |
支持,基于Hystrix实现 |
支持,基于声明配置文件,最终转化成路由规则实现 |
服务路由 |
支持,基于网关层实现路由转发 |
支持,基于iptables规则实现 |
安全策略 |
支持,基于spring-security组件实现,包括认证,鉴权等,支持通讯加密 |
支持,基于RBAC的权限模型,依赖Kubernetes实现,同时支持通讯加密 |
配置中心 |
支持,springcloud-config组件实现 |
不支持 |
性能监控 |
支持,基于Spring cloud提供的监控组件收集数据,对接第三方的监控数据存储 |
支持,基于SideCar代理,记录服务调用性能数据,并经过metrics adapter,导入第三方数据监控工具 |
日志收集 |
支持,提供client,对接第三方日志系统,例如ELK |
支持,基于SideCar代理,记录日志信息,并经过log adapter,导入第三方日志系统 |
工具客户端集成 |
支持,提供消息,总线,部署管道,数据处理等多种工具客户端SDK |
不支持 |
分布式事务 |
支持,支持不一样的分布式事务模式:JTA,TCC,SAGA等,而且提供实现的SDK框架 |
不支持 |
其余 |
…… |
…… |
从上面表格中能够看到,若是从功能层面考虑,Spring Cloud与Service Mesh在服务治理场景下,有至关大量的重叠功能,从这个层面而言,为Spring Cloud向Service Mesh迁移提供了一种潜在的可能性。
在行业当前环境下,还有一个趋势,或者说是现状。愈来愈多的应用走在了通往应用容器化的道路上,或者在将来,容器化会成为应用部署的标准形态。并且不管哪一种容器化运行环境,都自然支撑服务注册发现这一基本要求,这就致使Spring Cloud体系应用上容器的过程当中,存在必定的功能重叠,有可能为后期的应用运维带来必定的影响,而Service Mesh偏偏须要依赖容器运行环境,同时弥补了容器环境所欠缺的内容(后续会具体分析)。
从软件设计角度出发,咱们一直在追求松耦合的架构,也但愿作到领域专攻。例如业务开发人员但愿我只要关心业务逻辑便可,不须要关心链路跟踪,熔断,服务注册发现等支撑工具的服务;而平台支撑开发人员,则但愿个人代码中不要包含任何业务相关的内容。而Service Mesh的出现,让这种状况成为可能。
目前而言Spring Cloud虽然提供了对众多协议的支持,可是受限于Java技术体系。这就要求应用须要在同一种语言下进行开发(这不必定是坏事儿),在某种状况下,不必定适用于一些工做场景。而从微服务设计考虑,不该该受限于某种语言,各个服务应该可以相互独立,你们须要的是遵循通讯规范便可。而Service Mesh刚好能够消除服务间的语言壁垒,同时实现服务治理的能力。
基于以上四点缘由,当下环境,除了部分大多已经提早走在了Service Mesh实践的道路上互联网大厂之外(例如蚂蚁金服的SOFASTACK),也有大部分企业已经开始接触Service Mesh,而且尝试把Spring Cloud构建的应用,迁移到Service Mesh中。
Spring Cloud架构解析的目的在于肯定须要从当前的服务中去除与Service Mesh重叠的功能,为后续服务替换作准备。咱们来看一个典型的Spring Cloud架构体系,如图所示:
从图中咱们能够简要的分析出,一个基于Spring Cloud的微服务架构,主要包括四部份内容:服务网关,应用服务,外围支撑组件,服务管理控制台。
服务网关
服务网关涵盖的功能包括路由,鉴权,限流,熔断,降级等对入站请求的统一拦截处理。具体能够进一步划分为外部网关(面向互联网)和内部网关(面向服务内部管理)。
应用服务
应用服务是企业业务核心。应用服务内部由三部份内容构成:业务逻辑实现,外部组件交互SDK集成,服务内部运行监控集成。
外围支撑组件
外围支撑组件,涵盖了应用服务依赖的工具,包括注册中心,配置中心,消息中心,安全中心,日志中心等。
服务管理控制台
服务管理控制台面向服务运维或者运营人员,实现对应用服务运行状态的实时监控,以及根据状况须要可以动态玩成在线服务的管理和配置。
这里面哪些内容是咱们能够拿掉或者说基于Service Mesh(以Istio为例)能力去作的?分析下来,能够替换的组件包括网关(gateway或者Zuul,由Ingress gateway或者egress替换),熔断器(hystrix,由SideCar替换),注册中心(Eureka及Eureka client,由Polit,SideCar替换),负责均衡(Ribbon,由SideCar替换),链路跟踪及其客户端(Pinpoint及Pinpoint client,由SideCar及Mixer替换)。这是咱们在Spring Cloud解析中须要完成的目标:即肯定须要删除或者替换的支撑模块。
服务单元改造的目的在于基于第一步的解析结果,完成依赖去除或者依赖替换。根据第一步的分析结果服务单元改造分为三步:
删除组件,包括网关,熔断器,注册中心,负载均衡,链路跟踪组件,同时删除对应client的SDK;
替换组件,采用httpClient 的SDK支持http协议的远程调用(原来在Ribbon中),由原来基于注册中心的调用,转变成http直接调用;
配置信息变动,修改与删除组件管理的配置信息以及必要的组件交互代码(根据实际应用状况操做);
固然服务单元改造过程当中,还会涉及到不少的细节问题,都须要根据应用特色进行处理,这里不作深刻分析。
服务容器化是目前应用部署的趋势所在。服务容器化自己有不少不一样的方式,例如基于Jenkins的pipeline实现,基于docker-maven-plugin + dockerfile实现,固然还有不少不一样的方式。这里以Spring Cloud一个demo服务经过docker-maven-plugin+dockerfile实现说明为例:
简易的一个服务的Dockerfile以下所示:
ROM openjdk:8-jre-alpine
ENV TZ=Asia/Shanghai \
SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
JAVA_OPTS="" \
JHIPSTER_SLEEP=0
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
CMD echo "The application will start in ${JHIPSTER_SLEEP}s..." && \
sleep ${JHIPSTER_SLEEP} && \
java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar
# java ${JAVA_OPTS} -Djava.security.egd=environment:/dev/./urandom -jar /app.@project.packaging@
EXPOSE 8080
ADD microservice-demo.jar /app.jar复制代码
文件中定义了服务端口以及运行命令。
Maven-docker-plugin的插件配置以下所示:
<build>
<finalName>microservice-demo</finalName>
<plugins>
......
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
<execution>
<id>tag-image</id>
<phase>package</phase>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<image>${project.build.finalName}:${project.version}</image>
<newName>${docker.registry.name}/${project.build.finalName}:${project.version}</newName>
</configuration>
</execution>
<!--暂时不添加推送仓库的配置-->
</executions>
<configuration>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<imageName>${project.build.finalName}:${project.version}</imageName>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.${project.packaging}</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>复制代码
经过增长docker-maven-plugin,在执行mvn package的时候能够加载Dockerfile,自动构建服务的容器镜像(须要说明的前提是本地安装docker运行环境,或者经过环境变量在开发工具中配置Docker的远程链接环境),从而完成服务容器化改造。
容器环境决定这Service Mesh的部署形态,这里不详细描述容器环境的部署过程。感兴趣的朋友,能够参考https://github.com/easzlab/kubeasz 开源项目,提供了Kubernetes基于ansible的自动化部署脚本。咱们也建议选择Kubernetes来构建容器环境。这里说明容器环境构建的考虑因素:
基于以上两点来考虑容器化环境的部署方案,关键是合理规划,避免资源浪费。
Service Mesh环境构建依赖于容器环境构建,主要考虑两个方面,以Isito为例:
服务注入用于将容器化的服务接入到Service Mesh的平台中,目前主要有两种方式。以Isito为例说明,主要包括自动注入和手动入住。选择手动注入的目的在于能够根据企业内部上线流程,对服务接入进行人为控制。而自动注入则可以更加快捷,方便。到此实际上已经完成服务迁移工做。
因为Service Mesh目前而言,可能是基于声明式的配置文件,达到服务治理的效果,所以没法实时传递执行结果。基于这种缘由,须要一个独立的Service Mesh的管理控制台,一方面可以查看各个服务的运行状态以及策略执行状况,另一方面可以支持服务运行过程当中策略的动态配置管理。目前而言,能够在Isito安装过程当中选择kiali做为一个控制台实现,固然将来也会有大量的企业提供专门的服务。
经过以上七个步骤,可以在必定程度上帮助企业应用,从Spring Cloud迁移到Service Mesh上,但迁移过程当中必然存在不断踩坑的过程,须要根据应用特色,事前作好评估规划。
首先,从容器化的环境出发,后续Knative,Kubernetes,Service Mesh必然会构建出一套相对完整的容器化PaaS解决方案,从而完成容器化PaaS支撑平台的构建。Service Mesh将为容器运行态提供保驾护航的做用。
其次,就目前Service Mesh的落地实现而言,对于一些特定需求的监测粒度有所欠缺,例如调用线程栈的监测(固然,从网络层考虑,或者不在Service Mesh的考虑范围以内),可是偏偏在不少服务治理场景的要求范围之中。咱们也须要针对这种状况,考虑实现方案。
最后,你们一直诟病的性能和安全问题。目前已经有所增强,可是依然被吐槽。
总体而言,Spring Cloud是微服务实现服务治理平台的现状,而Service Mesh倒是将来,固然也不能彻底取而代之,毕竟设计思路和侧重点不一样,是否迁移须要根据业务场景而定。
本文由博云研究院原创发表,转载请注明出处。