微服务设计指导-使用云原生微服务解决传统海量跑批时引起的系统间“级联雪崩”以及效率
Posted TGITCIC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微服务设计指导-使用云原生微服务解决传统海量跑批时引起的系统间“级联雪崩”以及效率相关的知识,希望对你有一定的参考价值。
问题描述
这也是一起真实的生产事故,如下图所示
这种“雪崩”是属于企业内部系统雪崩。
我们都知道如果是在外部http (包括一切restful、soap请求、http类型调用)调用上如果存在:a->b->c->d假设系统b为“中间段”,任意一点出错,如果你的http设置的时间超长或者是no connection time或者是无熔断。都会一路上“倒卡系统b“。这叫雪崩。
可是在我们的企业内部系统间也是存在这种”系统间雪崩“效应的。特别是在跑批场景,比如说:
- 柜面收银把数据、扫码购、人脸往交易记录往中台发;
- 交易中台再把数据二传手转到第三方分析引擎;
- 第三方分析引擎一旦出错,就会出现上述这种结果”第三方分析引擎卡死->交易中台卡死->柜面收银“;
然后就是一堆”鸡飞狗跳“,不断加内存、升CPU直到频繁重启都搞不定问题的解决,终于业务老板吃不消了要求改造,然后一群人连问题都找不到,于是就有了:
- 喂,你少发点数据!
- 喂,我只管发你吃不住数据管我什么事?
- 喂,我们没问题是你不行影响到了我们因此这个问题要你来改!
哎呀,那叫一个踢皮球!哎呀,那叫一个“热闹”!哎呀,那叫一个急!
解决方案的理论基础
我们知道了外部级联雪崩,同为内网的企业间系统其实也有雪崩而且更容易出现雪崩。
如上图,当有一个系统处于另外两个legacy系统间,此时这个系统会很“难受”。因为legacy要么是erp要么是c/s传统架构。
企业内的legacy讲究的是业务幂等。因此使用的都是基于DB的悲观锁来做的交易行为。这样的系统,150并发对它们来说已经是it's a myth了。你一个跑批发起,一个大for循环,中大型企业这种类型的跑批至少存在有150-300多种,每一种日交易量好点的都是1万-3万笔流水,银行金融都是讲10万流水的。然后把10万流水乘渠道乘帐目类型得到的用于循环的一个笛卡尔积动不动就是上百万。
上百万的记录套在一个for循环里,往下游的legacy送,对于先进点的“中间地位的交易系统”来说,多线程不是问题,哗啦一下开启个几百个线程,每个线程上千数据的往外就送。
哎呀。。。不需要1分钟,下游系统卡爆。
一旦下游系统卡爆就反向影响中间地位的交易系统,于是就有了这种“雪崩”,具体表现就是突然间前端APP应用或者是小程序应用变得很慢很慢。
然后就是上述一堆甩锅开始了。
因此,解决这一类问题我们需要本着如下的设计原则,这个原则也就是一些先进的大厂经常在面试P6, P7级别或者以上人员希望听到侯选人能够说出以下这些点:
- 多线程必须做到每个线程间不污染;
- 支持重跑、重试、严重错误记录;
- 线程数恒定、可控,跑批时间可以稍长点(都跑批了,你不在乎长那么几十秒,而实际多线程运用了好甚至远远千倍高于设计了不好的盲目开几百上千线程的应用);
- 任务处理不过来时运用“弹性横向扩充应用”来解决分布式计算而不是一味增大线程数;
- 资源尽可能利用少(整个job运行期间:内存<10%利用率,CPU<10%利用率,TCP文件打开数控制在整体文件句柄的10%甚至5%);
- 充分利用“计算机的CPU时间片轮流转“、充分利用并行计算、充分利用缓存、内存、异步;
因此,”跑批“两个字看似simple,but it means everything。是一个高度集成计算机科学专业知识的设计与制作。
此处顺便就补足一下“培训班-只教CRUD”这种急功近利的方式无法教给大家的真正的计算机科学程序员所需要的知识,我们市面上90%的猿们正是缺少了这些核心知识因此才造就了“X农”这个名词的存在,也正是缺少了这些基础知识点造成了一切系统本应该(是个编程的就需要基本应该做到)围绕着这些知识点展开却没能做到的“根本原因”,也造成了我们绝大多数系统有功能无性能,门店数、顾客数稍稍一多系统就爆了,一个系统连半年寿命都达不到(跳脱上北广-大厂的领域,国内绝大多数系统真心无性能,这一点不夸张):
- HTTP=TCP=OS(我们拿unix/linux来举例)的ulimit数,这个数最大到65,535,但你要考虑到OS还有其它的应用要用到文件句柄数,一般来说可以给到web应用的数量为一半,差不多32,000即并发可被打开的http数量,一个大for循环或者不加控制的线程数可以在1分钟内轻而易举到达这个阀值,一旦到了这个阀值,该OS上的应用全“卡死”;
- CPU利用率>80%时,你这台OS上的一切应用都处于”假死“状态,你可以自己拿jmeter,并发线程写个1万,跑1分钟试试,直接把自己电脑搞挂了;
- 内存占用率>90%时,如同CPU利用率>80%情况;
- 特别在万、十万、百万数据循环时,如果你不做sleep, wait的待待,CPU会像一个以11秒百米冲刺的速度的人保持这个速度要跑完45公里一样,它的“肺”不需要多久就爆了。你得让他“喘口气”,这就是CPU分片轮流转。很多人在这种跑批处理时都不知道sleep;
- 前端的APP/小程序应用经常会在跑批时被卡死就是因为很多人以为前后端分离,但实际前端的API是落到后端的spring boot的应用上的呀,而后端和跑批如果正好处于同一个应用而此时跑批正在耗你的http进程,势必也会影响到你的前端访问,因为TO B端的跑批把可用的http连接用完了前端用户如何连得进来呢?都认为前后端分离,但是前端你有API请求呀,要不你不要API请求了,你就一个纯静态应用那么后台就算shutdown也不会影响前台了,这是很多传统甲方型公司的IT甚至CTO一层都想不到的点,毫不夸张的说目前市面上90%(全国范围)甲方型IT都是这种认知;
- 把“系统间的强关联改成弱关联”,把出问题的点、范围约束在尽可能小的范围,那么要多用“异步”架构,这样就不会形成雪崩,要崩也是单崩。崩坏了你的上游或者下游正好暴露出来他们的系统里的问题,如果你要连着跟着一起崩,那么当出现这种问题时就是一锅混水,3个系统本来是两个系统不行,排查解决也可以精准到系统。你现在去“搅和在一起”。。。这是“死也要陪着别人一起死喽?你们间多友情?”;
- 减少传统OLTP型DB的使用或者干脆能不用就不用,一条数据库行级锁就可以一路卡爆你们的系统。适当的使用NOSQL如:mongodb、redis,你会发现同样数据量使用NOSQL的效率是传统DB的千倍、万倍以上;
- 一条条update、insert循环1,000次和把1,000条update语句组装在一起一次性提交,前后性能相差几十有的甚至达到上千倍,因为数据库乐于做“批量一次性提交“而非一条条提交。网络传输亦是如此。比如说你往百度网盘上传3万个文件每个文件只有20K,你可能要上传几小时,而你把3万个文件打成一个ZIP包一次性上传不会超过15分钟。因为网络IO频繁读写是极其”低效“的;
- HTTP或者任何连接不得无超时设定,超时又要尽可能设的短。并且任何连接包括HTTP连接都有两个timeout。一个叫createConnectionTimeout,一个叫readTimeout。createConnectionTime是指两个系统间建立连接通道所用时间,这个时间如果是企业内网>2秒或者4秒,我们算4秒吧,已经算很夸张了,这代表要建立的系统间有一个系统早己经“挂了”。而readTimeout就是http request->response的时间,这个时间就是一次“交易”的时间,在互联网to c端微服务领域我们甚至要求这个readTimeout达到100毫秒或者100毫秒内,可想而知留给你交易一笔交易的时间有多少,为什么要少呢?你时间也可以长呀,处理一笔交易10几秒,好。。。一路雪崩若干系统模块、系统组件、甚至系统,然后全局雪崩、然后小程序/APP白屏、卡死,真happy!因此readTimeout我们控制在4 秒吧,两个参数的关系是readTimeout的时间>createConnectionTime。很多合理的系统的createConnectionTimeout的设定一般不会超过2秒;
好了,大的原则不过如上9点,那么根据上述9点,我们把我们最新的设计展现出来,如何做到“可控恒定线程数、又能做到业务幂等、又能做到效率不差(事实上只会更高)而系统资源开销更少”的来做到以上这件事呢?
提出解决方案
AS-IS & TO-B,是TOGAF企业架构常用的一种架构设计手法。
- AS-IS代表:己有/现有设计;
- TO-B代表:未来、目标、我们要设计成什么样;
在TO-B架构设计里我们可以看到设计的目标如下几点:
- 把A-B-C三个系统间的跑批,从强粘连引起的大范围雪崩约束到小范围雪崩;
- 我们为了保TO C端即小程序/APP不被卡死,那就算雪崩我们也把这个雪崩控制在后台,不会“反射/反弹”到前端,因此我们利用异步;
- 如果要异步就必须要使用到暂存队列,这个暂存队列可以使用mq也可以自己使用“流水表+带状态字段”来制作异步job,具体设计我们分解到后面详细设计中去解说;
- 上游端把数据一条条发过来,交易系统把它吃下来落流水表后直接返回响应,这种请求即readTimeout不会超过1秒;
- 存下来后利用一个异步的job把流水读出来然后以可控线程数的异步机制发送往下游系统“扔”过去;
这就是我们的设计思路,彻底解耦。
解释两个为什么
这两个为什么一旦搞懂其实就搞清了整个设计的核心思想了,非常重要,因此特在此做深度解释。
为什么一定一定要讲究“发送线程为可控、恒定线程”呢?
这个设计运行在一个jvm里,发送线程是恒定的可控的,一般来说这个线程数不易设置超过50,正如我一直以来所说,一般上游或者下游系统都是legacy,这种legacy不要看很“贵”,但真的连150并发都吃不住的。因为这些系统都是“强交易(其实这只是这些系统过于老旧-平均20年前技术栈设计而成导致)”,都是基于DB的悲观锁设计,那么我们有这个“责任”去保护好这些系统。
对于这些系统永远要控制好发往它的请求数要控制住、不搞死,对于整个企业的IT来说“共赢”才能赢,单部门赢不是赢,因此这个设计是很重要的,不能只考虑自己的系统“爽”。
为什么一定要用异步暂存呢
我们可以控制好我们送出去的量不把别人搞死,你怎么保证别人送过来的量不把你搞死呢?这些legacy系统之所以legacy就如我上文所说的根源是这些系统的设计很古老,他们可能连多线程都没法用,很多银行金融型企业甚至用的还是单片机、C来做的,哪来的多线程、微服务、分布式这种先进的技术手段,诚然,在当时那个年代这些系统很先进,但是它们没有跟上时代在进化的潮流中被时代已经淘汰。
那它们发往你的数据高度有可能是“不控线程、直接大量请求泛滥”进你的系统的。因此,你的系统要有能力“挡”,挡住了后呢一点点把这些内部legacy过来的流量“消化”掉。
因此此处就需要使用到异步、暂存、队列这种手法了。
详细设计
对于“前面可以挡得住,挡得住可以吃得下,输出可以控”的核心原则。我们可以用两种手段来落地我们的设计。
- 使用MQ+可控数量MQ的Consumer+RestTemplate的方式;
- 使用MQ+MongoDb来做流水表+SpringBoot线程池+Redisson自续约锁+RestTemplate的方式;
这两种方式又涉及到以下的细节技术。
我特别喜欢在设计转化到实际落地前把要用到的技术栈全部准备好,这是一个好习惯。我不知道大家有没有去过天津,吃过那里的小吃?
在天津,老清老早,天还蒙蒙亮时,你来到天津特别是一些小胡同,看到有一个摊,老板在凌晨4、5点就已经把水烧好、把料都准备好了,一小碟子精盐、一小碟子蒜、一小碟子花生、一小碟子芝麻、葱、酱、虾皮,摆了一桌面。
客人来了后:老板,来一碗老面茶。
老板用手快速的在各个碟子间游走着,拿起这个,拿起那个,快速的往一个海碗里撒入这些预先准备好的料,然后拿了一个大勺,往早已经烧热的大汤锅里这么一撩,然后往满是小料的海碗里这么一浇,喊一声“来了您哎,慢慢吃”。
客人呢?一手拿着果子咬一口一嘴油,另一只手拿着勺这么喝一口老面茶,那叫一个香。
所以呢,我们就把我们的这些“小料”都预先给它准备好了。
序号 | 技术栈名 |
1 | spring boot 2.4.2 |
2 | webflux来做我们的controller |
3 | spring boot的thread pool |
4 | spring boot的quartz |
5 | spring boot redisson自续约锁 |
6 | spring boot rabbitmqTemplate |
7 | spring boot mongoTemplate |
8 | mysql 5.7 |
9 | MongoDb 3.2.x |
10 | RabbitMq 3.8.x |
11 | Redis6.x |
12 | apache jmeter 5.3 |
这些技术分解成两个spring boot工程:
- SkyPayment,用于模拟我们的中台/电商核心交易平台,它会提供一个回调接口,该接口接受一条http请求,这个http请求会达到几万的量,用于模拟上游端往SkyPayment工程里喂入海量的数据,此处的海量数据我们会使用jmeter的Arrival Threads来模拟出这个高并发的量来;
- SkyDownStreamSystem,用于模拟下游系统。即当上游(jmeter)往SkyPayment系统喂入海量的高并发数据时,SkyPayment把这个数据以“二传手”的身份传递给到SkyDownStreamSystem,SkyDownStreamSystem接到SkyPayment转过来的数据对数据库里的payment表的status做状态修改以模拟“入库”、“记帐”的动作;
系统设计要求:
- 这两个工程在运行时,面对几万级别的瞬时流量压入时必须从开始到结束,压入多少数据最终处理完多少数据;
- 有任何数据处理出错系统可以重复、补偿处理;
- 这两个系统中的http连接数必须控制在很小的并发数内,以便于任何系统不会被打爆;
- 在满足了以上三个点的同时还需要做到当海量数据全部发完后,系统可以在SkyPayment端传输完成后的1分钟内把所有的几万条数据处理完毕;
- 全过程每个项目的内存使用不超过2G、CPU不超过10%;
下面开始动手了。
详细设计-用于模拟下游系统的SkyDownStream项目结构
用于入库的controller
@PostMapping(value = "/updateStatusInBatch", produces = "application/json")
@ResponseBody
public Mono<ResponseBean> updateStatusInBatch(@RequestBody List<PaymentBean> paymentList)
ResponseBean resp = new ResponseBean();
try
downStreamService.updatePaymentStatusByList(paymentList);
resp = new ResponseBean(ResponseCodeEnum.SUCCESS.getCode(), "success");
catch (Exception e)
resp = new ResponseBean(ResponseCodeEnum.FAIL.getCode(), "system error");
logger.error(">>>>>>updateStatusInBatch error: " + e.getMessage(), e);
return Mono.just(resp);
DownStreamService.java
@TimeLogger
@Transactional(rollbackFor = Exception.class)
public void updatePaymentStatusByList(List paymentList) throws Exception
downStreamDao.updatePaymentStatusByList(paymentList);
DownStreamDao.java
public void updatePaymentStatusByList(List paymentList);
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace="org.mk.demo.downstreamsystem.dao.DownStreamDao">
<resultMap id="paymentResult"
type="org.mk.demo.downstreamsystem.vo.PaymentBean">
<id column="pay_id" property="payId" javaType="Integer" />
<result column="status" property="status" javaType="Integer" />
<result column="transf_amount" property="transfAmount"
javaType="Double" />
</resultMap>
<update id="updatePaymentStatusById"
parameterType="org.mk.demo.downstreamsystem.vo.PaymentBean">
update sky_payment set status=#status where
pay_id=#payId
</update>
<update id="updatePaymentStatusByList">
<foreach collection="list" item="payment" separator=";">
update sky_payment set status=#payment.status where pay_id=#payment.payId
</foreach>
</update>
</mapper>
大家可以看到此处我有两个dao,一个DAO是根据一条条的pay_id来入库,另一个DAO是用的是batchUpdate方法。
此处为什么我要强调使用batchUpdate?想想我上面提到过的9大基本知识点中的1,000个循环一条条写数据库和一次1,000条一提交,性能可以差几十甚至上千倍的梗。因此在POC代码中我不仅仅实现了RabbitMq和使用NOSQL来实现可控异步多线程分布式计算这两种方式外我还在每个方式中使用了“一条条插入更新数据”和“批量更新数据”两种方式进行了对比,以验证一条条数据插/更新和批量插/更新的效率有多少可怕的区别。
PaymentBean.java
/**
* 系统项目名称 org.mk.demo.skypayment.vo PaymentBean.java
*
* Feb 1, 2022-11:12:17 PM 2022XX公司-版权所有
*
*/
package org.mk.demo.downstreamsystem.vo;
import java.io.Serializable;
/**
*
* PaymentBean
*
*
* Feb 1, 2022 11:12:17 PM
*
* @version 1.0.0
*
*/
public class PaymentBean implements Serializable
private int payId;
public int getPayId()
return payId;
public void setPayId(int payId)
this.payId = payId;
public int getStatus()
return status;
public void setStatus(int status)
this.status = status;
public double getTransfAmount()
return transfAmount;
public void setTransfAmount(double transfAmount)
this.transfAmount = transfAmount;
private int status;
private double transfAmount = 0;
SkyDownStream系统的application.yml配置
mysql:
datasource:
db:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
minIdle: 50
initialSize: 50
maxActive: 300
maxWait: 1000
testOnBorrow: false
testOnReturn: true
testWhileIdle: true
validationQuery: select 1
validationQueryTimeout: 1
timeBetweenEvictionRunsMillis: 5000
ConnectionErrorRetryAttempts: 3
NotFullTimeoutRetryCount: 3
numTestsPerEvictionRun: 10
minEvictableIdleTimeMillis: 480000
maxEvictableIdleTimeMillis: 480000
keepAliveBetweenTimeMillis: 480000
keepalive: true
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 512
maxOpenPreparedStatements: 512
master: #master db
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ecom?useUnicode=true&characterEncoding=utf-8&useSSL=false&useAffectedRows=true&autoReconnect=true&allowMultiQueries=true
username: root
password: 111111
slaver: #slaver db
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3307/ecom?useUnicode=true&characterEncoding=utf-8&useSSL=false&useAffectedRows=true&autoReconnect=true&allowMultiQueries=true
username: root
password: 111111
server:
port: 9082
tomcat:
max-http-post-size: -1
accept-count: 1000
max-threads: 1000
min-spare-threads: 150
max-connections: 10000
max-http-header-size: 10240000
spring:
application:
name: skydownstreamsystem
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
context-path: /skydownstreamsystem
SkyDownStream的pom.xml(parent pom.xml和SkyPayment工程共用)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mk.demo</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>skydownstreamsystem</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>$spring-boot.version</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mq must -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mysql must -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!-- redis must -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- jedis must -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--redisson must start -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.6</version>
<exclusions>
<exclusion>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-23</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--redisson must end -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-21</artifactId>
<version>3.13.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 排除了老版本log4j2后升级到最新的2.17.1 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>$log4j2.version</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>$log4j2.version</version>
</dependency>
<!-- 排除了老版本log4j2后升级到最新的2.15.0 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- 项目通用框架 -->
<dependency>
<groupId>org.mk.demo</groupId>
<artifactId>common-util</artifactId>
<version>$common-util.version</version>
</dependency>
<dependency>
<groupId>org.mk.demo</groupId>
<artifactId>db-common</artifactId>
<version>$db-common.version</version>
</dependency>
</dependencies>
</project>
skyDownStream-下游系统运行起来后怎么用
请求报文示例
[
"payId": "1",
"status": "6"
,
"payId": "2",
"status": "6"
,
"payId": "3",
"status": "6"
,
"payId": "4",
"status": "6"
,
"payId": "5",
"status": "6"
,
"payId": "10",
"status": "6"
]
skypayment数据库表结构
CREATE TABLE `sky_payment` (
`pay_id` int(11) NOT NULL AUTO_INCREMENT,
`status` tinyint(3) DEFAULT NULL,
`transf_amount` varchar(45) DEFAULT NULL,
`created_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_date` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pay_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
我自己写了一个store procedure往这个表里喂入了800多万条数据。因为数据量超过500万后,这种批量操作如果做了不好,很容易出现数据库死锁、主从延迟、数据库事务过长这些幺蛾子问题的发生,从而以此充分模拟线上生产环境。
而实际我们的线上生产环境的数据量涉及到这条出事情跑批的单表数据根本没我自己模拟的数据量大。
详细设计-RabbitMq解决方案
SkyDownStream下游系统就这样了,重点在于我们模拟我们的中台/商城交易系统的SkyPayment系统。
我们先用RabbitMQ+可控消费数+可控线程数的方案来实现
先上SkyPayment和SkyDownStream系统所共用的parent pom。
parent pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.mk.demo</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<jacoco.version>0.8.3</jacoco.version>
<aldi-sharding.version>0.0.1</aldi-sharding.version>
<spring-boot.version>2.4.2</spring-boot.version>
<!-- <spring-boot.version>2.3.1.RELEASE</spring-boot.version> -->
<!-- spring-boot.version>2.0.6.RELEASE</spring-boot.version> <spring-cloud-zk-discovery.version>2.1.3.RELEASE</spring-cloud-zk-discovery.version -->
<zookeeper.version>3.4.13</zookeeper.version>
<!-- <spring-cloud.version>Greenwich.SR5</spring-cloud.version> -->
<spring-cloud.version>2020.0.1</spring-cloud.version>
<dubbo.version>2.7.3</dubbo.version>
<curator-framework.version>4.0.1</curator-framework.version>
<curator-recipes.version>2.8.0</curator-recipes.version>
<!-- druid.version>1.1.20</druid.version -->
<druid.version>1.2.6</druid.version>
<guava.version>27.0.1-jre</guava.version>
<fastjson.version>1.2.59</fastjson.version>
<dubbo-registry-nacos.version>2.7.3</dubbo-registry-nacos.version>
<nacos-client.version>1.1.4</nacos-client.version>
<!-- mysql-connector-java.version>8.0.13</mysql-connector-java.version -->
<mysql-connector-java.version>5.1.46</mysql-connector-java.version>
<disruptor.version>3.4.2</disruptor.version>
<aspectj.version>1.8.13</aspectj.version>
<spring.data.redis>1.8.14-RELEASE</spring.data.redis>
<seata.version>1.0.0</seata.version>
<netty.version>4.1.42.Final</netty.version>
<nacos.spring.version>0.1.4</nacos.spring.version>
<lombok.version>1.16.22</lombok.version>
<javax.servlet.version>3.1.0</javax.servlet.version>
<mybatis.version>2.1.0</mybatis.version>
<pagehelper-mybatis.version>1.2.3</pagehelper-mybatis.version>
<spring.kafka.version>1.3.10.RELEASE</spring.kafka.version>
<kafka.client.version>1.0.2</kafka.client.version>
<shardingsphere.jdbc.version>4.0.0</shardingsphere.jdbc.version>
<xmemcached.version>2.4.6</xmemcached.version>
<swagger.version>2.9.2</swagger.version>
<swagger.bootstrap.ui.version>1.9.6</swagger.bootstrap.ui.version>
<swagger.model.version>1.5.23</swagger.model.version>
<swagger-annotations.version>1.5.22</swagger-annotations.version>
<swagger-models.version>1.5.22</swagger-models.version>
<swagger-bootstrap-ui.version>1.9.5</swagger-bootstrap-ui.version>
<sky-sharding-jdbc.version>0.0.1</sky-sharding-jdbc.version>
<cxf.version>3.1.6</cxf.version>
<jackson-databind.version>2.11.1</jackson-databind.version>
<gson.version>2.8.6</gson.version>
<groovy.version>2.5.8</groovy.version>
<logback-ext-spring.version>0.1.4</logback-ext-spring.version>
<jcl-over-slf4j.version>1.7.25</jcl-over-slf4j.version>
<spock-spring.version>2.0-M2-groovy-2.5</spock-spring.version>
<xxljob.version>2.2.0</xxljob.version>
<java-jwt.version>3.10.0</java-jwt.version>
<commons-lang.version>2.6</commons-lang.version>
<hutool-crypto.version>5.0.0</hutool-crypto.version>
<maven.compiler.source>$java.version</maven.compiler.source>
<maven.compiler.target>$java.version</maven.compiler.target>
<compiler.plugin.version>3.8.1</compiler.plugin.version>
<war.plugin.version>3.2.3</war.plugin.version>
<jar.plugin.version>3.1.1</jar.plugin.version>
<quartz.version>2.2.3</quartz.version>
<h2.version>1.4.197</h2.version>
<zkclient.version>3.4.14</zkclient.version>
<httpcore.version>4.4.10</httpcore.version>
<httpclient.version>4.5.6</httpclient.version>
<mockito-core.version>3.0.0</mockito-core.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<oseq-aldi.version>2.0.22-RELEASE</oseq-aldi.version>
<poi.version>4.1.0</poi.version>
<poi-ooxml.version>4.1.0</poi-ooxml.version>
<poi-ooxml-schemas.version>4.1.0</poi-ooxml-schemas.version>
<dom4j.version>1.6.1</dom4j.version>
<xmlbeans.version>3.1.0</xmlbeans.version>
<java-jwt.version>3.10.0</java-jwt.version>
<commons-lang.version>2.6</commons-lang.version>
<hutool-crypto.version>5.0.0</hutool-crypto.version>
<nacos-discovery.version>2.2.5.RELEASE</nacos-discovery.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
<redission.version>3.16.1</redission.version>
<log4j2.version>2.17.1</log4j2.version>
<redis-common.version>0.0.1</redis-common.version>
<common-util.version>0.0.1</common-util.version>
<db-common.version>0.0.1</db-common.version>
<httptools-common.version>0.0.1</httptools-common.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- redis -->
<!-- redission must -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>$redission.version</version>
<!-- <exclusions> <exclusion> <groupId>org.redisson</groupId> <artifactId>redisson-spring-data-23</artifactId>
</exclusion> </exclusions> -->
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-21</artifactId>
<version>$redission.version</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>$spring-cloud-alibaba.version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery
</artifactId>
<version>$nacos-discovery.version</version>
</dependency>
<dependency>
<groupId>com.aldi.jdbc</groupId>
<artifactId>sharding</artifactId>
<version>$aldi-sharding.version</version>
</dependency>
<!-- jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>$java-jwt.version</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>$hutool-crypto.version</version>
</dependency>
<!-- poi must start -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>$poi.version</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>$poi-ooxml.version</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>$poi-ooxml.version</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>$poi-ooxml-schemas.version</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>$dom4j.version</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>$xmlbeans.version</version>
</dependency>
<!-- poi must end -->
<dependency>
<groupId>com.odianyun.architecture</groupId>
<artifactId>oseq-aldi</artifactId>
<version>$oseq-aldi.version</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>$httpcore.version</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>$httpclient.version</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>$zkclient.version</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--quartz依赖 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>$quartz.version</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>$quartz.version</version>
</dependency>
<!-- spring cloud base -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 使用mockito -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>$mockito-core.version</version>
<scope>test</scope>
</dependency>
<!-- jwt token -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>$java-jwt.version</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>$hutool-crypto.version</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>$spring-boot.version</version>
</dependency>
<!-- Logback -->
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>$logback-ext-spring.version</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>$jcl-over-slf4j.version</version>
</dependency>
<!-- 供单元测试时用的数据库 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>$h2.version</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>$zookeeper.version</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- xxl-rpc-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>$xxljob.version</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>$spring-boot.version</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.3-groovy-2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.3-RC1-groovy-2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.6</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>$gson.version</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>$jackson-databind.version</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<version>$spring-boot.version</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>$cxf.version</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>$cxf.version</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>$spring-boot.version</version>
</dependency>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>$swagger.version</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>$swagger.version</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>$swagger-bootstrap-ui.version</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>$swagger-annotations.version</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>$swagger-models.version</version>
</dependency>
<dependency>
<groupId>org.sky</groupId>
<artifactId>sky-sharding-jdbc</artifactId>
<version>$sky-sharding-jdbc.version</version>
</dependency>
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>$xmemcached.version</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>$shardingsphere.jdbc.version</version>
</dependency>
<!-- <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId>
<version>$spring.kafka.version</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId> <version>$kafka.client.version</version>
</dependency> -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>1.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>$mybatis.version</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>$pagehelper-mybatis.version</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>$spring-boot.version</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>$spring-boot.version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>$dubbo.version</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>$dubbo.version</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>$curator-framework.version</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>$curator-recipes.version</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>$mysql-connector-java.version</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>$druid.version</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>$druid.version</version>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>$disruptor.version</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>$guava.version</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>$fastjson.version</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>$dubbo-registry-nacos.version</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>$nacos-client.version</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>$aspectj.version</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>$spring-boot.version</version>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>$seata.version</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>$netty.version</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>$lombok.version</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.boot/nacos-config-spring-boot-starter -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>$nacos.spring.version</version>
<exclusions>
<exclusion>
<artifactId>nacos-client</artifactId>
<groupId>com.alibaba.nacos</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sourceforge.groboutils</groupId>
<artifactId>groboutils-core</artifactId>
<version>5</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>$commons-lang.version</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>redis-common</module>
<module>common-util</module>
<module>db-common</module>
<module>skypayment</module>
<module>skydownstreamsystem</module>
<module>httptools-common</module>
</modules>
</project>
SkyPayment的pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mk.demo</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>skypayment</artifactId>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>$spring-boot.version</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- quartz dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
</dependency>
<!-- mq must -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mysql must -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!-- redis must -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- jedis must -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- redission must -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>$redission.version</version>
<!-- <exclusions> <exclusion> <groupId>org.redisson</groupId> <artifactId>redisson-spring-data-23</artifactId>
</exclusion> </exclusions> -->
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-21</artifactId>
<version>$redission.version</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starte以上是关于微服务设计指导-使用云原生微服务解决传统海量跑批时引起的系统间“级联雪崩”以及效率的主要内容,如果未能解决你的问题,请参考以下文章