基于SpringBoot的微服务架构与K8S容器部署实践
前不久作为架构师完成了某知名快消企业的⼀个业务中台建设。系统上线后,经历了双⼗⼀活动的流量⾼峰,整体运⾏稳定。最近有空,便将此次架构的思路,⼼得稍作整理在这篇博客中分享⼀下。不会深⼊每⼀个技术细节,⽽是把⽤到的技术、框架、⼯具做⼀个简单的回顾,作为⽇后的参考。
业务架构
业务架构⽅⾯,该系统作为业务中台,主要负责客户资产管理,包括客户的卡、券以及其他虚拟资产。通过对外暴露标准restful接⼝的⽅式提供服务。服务的调⽤⽅包括⾃有渠道的app、⼩程序,以及合作伙伴渠道,包括招⾏、阿⾥等。⽽系统本⾝也会通过服务⽹关去调⽤公司内部的其他业务系统接⼝,如通过客户中⼼接⼝同步会员信息等。
根据⽬前的统计,这个业务中台,每⽇的服务调⽤量在700万次左右,有活动时也会超过1000万次。⽽⼤部分交易,发⽣在上班、午休以及下午3点左右(下午茶)的时间段内。
由于涉及到客户业务细节,这⾥对业务架构就不做详细说明了。
技术架构
这个案例中采⽤了基于SpringBoot的微服务架构。结合企业⾃⾝的基础架构设施,进⾏K8S容器化部署,并采⽤Kong API Gateway对各业务中台暴露的API接⼝进⾏统⼀管理。
Kong API Gateway
随着微服务架构在企业中的流⾏,原来⼤⽽全的系统被拆分为粒度较⼩的中台,⽽系统中的⼤部分功能则被以restful API形式提供的服务所取代,这使得IT系统能够更加快速地响应业务变化带来的挑战,但同时随着服务的增加,如何有效管理这些服务却成为难题。
在⼀些中⼩型项⽬中,我们⼀般都会采⽤Spring Cloud的技术栈,并选择Spring Cloud Gateway来作服务⽹关。然⽽,对于⼀些⼤型企业,则需要全局考虑服务的治理,⽹关性能,以及其他扩展功能。
在这个案例中,企业使⽤了Kong作为API⽹关。中台将需要开放外部使⽤的API,通过⽹关控制台进⾏注册,添加证书,⽣成Auth Key供关联⽅使⽤。
Kong具有以下⼀些特性,能够很好地满⾜⼤型组织对于服务⽹关的需求:
开源(本案例中使⽤的是Kong的企业版,提供了原⼚服务)
亚毫秒级的响应延迟,得益于基于Nginx与OpenResty带来的超⾼性能
单节点25K TPS
springboot框架的作用
认证、授权、限流、数据转换(此案例中会员ID被添加到请求头中)、⽇志、统计分析
应⽤架构
整个系统采⽤java开发后端以及vue开发前端,应⽤部分共分为4个服务组件,全部进⾏容器化部署,并通过Ingress Controller负载均衡对外暴露服务:
资产服务:提供客户资产相关的服务接⼝
资产消费者服务:MQ监听服务,异步处理资产相关请求
控制台服务:资产管理运维类服务接⼝,供控制台前端使⽤
控制台前端服务:使⽤Vue开发的控制台前端应⽤(如下图)
SpringBoot
除控制台前端外,其他三个组件均采⽤⽬前主流的java微服务框架SpringBoot 2.3.4开发(考虑到稳定性,未使⽤最新的2.4版本)。
本案例中,通过开发应⽤框架,实现了系统中数据表达形式的统⼀,以及标准的据转换、校验、消息绑定、错误处理等功能。架构师需要对
应⽤框架负责,简明、⾼效、统⼀的应⽤框架,能够提升开发效率,产出标准⼀致的代码,保证交付质量。
应⽤框架不在本⽂的讨论范围内,⽽以下⼀些技巧或第三⽅包,却在我们构建⼤多数SpringBoot应⽤中得到使⽤。
####定制MyBatis 数据层框架采⽤MyBatis,在⼤型应⽤中MyBatis能够帮助程序员更好地控制数据层交互,并进⾏调优。⼀般可以在l中配置MyBatis,但当我们需要让MyBatis⽀持更多定制特性(如:多数据库⽀持)时,可以通过定义SqlSessionFactory bean来实现。
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sfb = new SqlSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setVfs(SpringBootVFS.class);
Properties props = new Properties();
props.setProperty("dialect", Dialect());
props.setProperty("reasonable", String.valueOf(dataConfiguration.isPageReasonable()));
PageHelper pagePlugin = new PageHelper();
pagePlugin.setProperties(props);
Interceptor[] plugins = {pagePlugin};
sfb.setPlugins(plugins);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sfb.Resources("classpath*:mappers/"+ Dialect()+"/*.xml"));
sfb.setTypeAliasesPackage("bl.del");
SqlSessionFactory factory = Object();
//        Configuration().addInterceptor(new CoreResultSetHandler());
return factory;
}
复制代码
使⽤logback⽇志组件
采⽤logback⽇志框架,可以在logback配置⽂件中指定针对不同的Spring profile在不同的环境中采⽤不同的⽇志级别,并采⽤不同的appender。同时引⼊spring-cloud-starter-sleuth依赖,通过设置traceId,使整个请求全链路上的所有⽇志打印出⼀致的traceId,⼤⼤⽅便了各系统间⽣产问题的协同排查。另外,采⽤异步⽅式记录⽇志,也有利于降低IO阻塞。
<springProfile name="stg">
<root level="error">
<appender-ref ref="STDOUT"/>
<appender-ref ref="SAVE-ERROR-TO-FILE-STG"/>
</root>
<logger name="" level="error" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC-SAVE-TO-FILE-STG"/>
</logger>
</springProfile>
<springProfile name="prod">
<root level="error">
<appender-ref ref="STDOUT"/>
<appender-ref ref="SAVE-ERROR-TO-FILE-PROD"/>
</root>
<logger name="" level="error" additivity="false">
<appender-ref ref="ASYNC-SAVE-TO-FILE-PROD"/>
</logger>
</springProfile>
复制代码
SSL加密及密码安全
全链路传输加密已成为企业安全中必不可少的措施。通过在classpath中引⼊CA颁发(也可以使⽤⾃签)的jks证书,并在application配置⽂件中进⾏简单配置,便可实现SpringBoot应⽤的SSL加密。
ssl:
enabled: true
key-store: classpath:xxx.jks
key-store-type: JKS
key-store-password: RUIEIoUD
key-password: RUIEIoUD
require-ssl: true
复制代码
密码以明⽂形式存放在配置⽂件中,也是不安全的。你可以jasypt加密配置⽂件中使⽤到的密码,或者直接使⽤Key-Vault⽅案,⽐如本案例中会分别在微软云环境中使⽤Azure Key Vault或本地IDC中使⽤Cyberark Conjur⽅案。
###同步与异步服务 我们并没有使⽤Spring Webflux来⽀持reactive特性,因为,这会增加开发复杂度,并且Webflux虽然改善了Web容器阻塞机制,但并不能从根本上解决⾼并发请求到来时的阻塞问题。
在这个案例中,通过搭建了3个节点的RabbitMq镜像集,作为消息中间件,并通过应⽤框架的⽀持,实现了服务的同步异步切换功能。我们将对外提供的服务注册到数据库中,在应⽤启动时,读⼊redis缓存。当请求到来时,通过API code判断该请求的响应模式:同步或异步。如果是同步请求则直接处理,⽽如果是异步请求,则发送到RabbitMq中,再由经过封装的消费者组件进⾏异步消费,最终达到削峰的⽬的。
对于开发⼈员来说,他们只需要关注服务的业务逻辑开发,由应⽤框架统⼀处理服务的同步,异步切换,消息发送或失败时的异常处理,以及死信队列的维护等⼯作。
Dockerfile
案例中的四个组件需要实现容器化部署,分别为SpringBoot应⽤与Vue应⽤创建Dockerfile。
典型的SpringBoot应⽤Dockerfile如下,⼀般情况下⼤型组织会构建私有镜像仓库,通过私有仓库拉取镜像的速度更快,能够节省CICD的时间。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。