一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

一种基于AOP+ThreadLocal技术的分布式系统断点重试方法与流程

2021-12-13 00:56:00 来源:中国专利 TAG:

一种基于aop threadlocal技术的分布式系统断点重试方法
技术领域
1.本发明属于软件信息技术领域,具体涉及一种基于aop threadlocal技术的分布式系统断点重试方法。


背景技术:

2.在业务系统中,因为网络或者异常数据等一些原因,程序会发生异常,在失败后如何保持交易的原子性和一致性是需要着重考虑的一个问题。
3.在单体架构中,因为只有涉及到一个应用,解决以上原子性和一致性问题,只需要开启声明式事务管理就可以了。在分布式架构中实现原子性和一致性首先想到的是通过分布式事务来实现,分布式事务方案包括:xa、tcc、本地消息表、可靠消息最终一致性等。我们较为熟悉的开源分布式事务框架:seata,其包含at模式、tcc模式、sage模式、xa模式。还有蚂蚁金服黑科技:dtx,其包含tcc模式、fmt托管模式、xa模式。
4.以上方案可以解决分布式一致性问题,但是或多或少需要引入其他中间件,或者部署额外的服务,或者部署一个分布式事务协调中心来实现。但是对于中小型公司而言引入中间件需要专项团队来维护其稳定性,部署额外的服务也需要人力去维护。
5.所以对于大部分的分布式接口调用,如果使用分布式事务很繁琐,直接就是监控、记录日志、事后快速的定位排查问题、通过重试来保证业务最终执行成功。
6.在发生异常时,一般主要涉及三种业务场景,1)在业务流程入口处直接中断了;2)在业务流程执行中途中断,但是此时只执行了一些查询操作没有任何修改操作;3)在业务流程执行到中途中断,但此时已经执行了大量的增删改操作。对于前两种业务场景,因为没有涉及到更新操作,那么直接发起重试无需人为过多干预,但是对于第三种业务场景下,同样也是最常见的情况,其通常采用手工处理的方式,需要手工处理大量的数据来回滚已经成功的操作,或者修复未完成的操作,然后才能发起手工重试,存在耗费大量的人力的问题,其次手工干预也带来了一定的异常数据风险。


技术实现要素:

7.为了解决上述现有技术存在的缺陷,本发明的目的在于提供一种基于aop threadlocal 技术的分布式系统断点重试方法,其目的在于,克服现有技术手工处理人力浪费、耗时长、容易出错的缺陷,实现了断点重试、多次断点重试的效果,同时降低发生异常数据的风险概率。
8.本发明采用的技术方案如下:
9.一种基于aop threadlocal技术的分布式系统断点重试方法,包括如下步骤:
10.步骤1:通过aop切面表达式指定需要支持断点重试的方法并定义所有方法的 operationtype;
11.步骤2:在需要支持断点重试的业务流程中开启断点重试;
12.步骤3:在发生异常后,持久化已经执行成功的方法返回值;
13.步骤4:清空threadlocal变量,防止内存溢出。
14.其中,所述步骤1具体包括:
15.步骤1.1:借助aspectj插件,通过其中的@pointcut注解来指定切面;
16.步骤1.2:通过execution、@annotation函数名称进行匹配,或是通过args、@args方法参数进行匹配,或是通过within、target类名来进行匹配;
17.步骤1.3:指定之后,aop通过动态代理技术,对于所指定的方法进行环切,在方法执行前做重试的判断,或是在方法执行之后获取执行结果,并获取返回值;
18.在上述步骤中,在已经指定的方法中,如果想要支持忽略查询方法断点重试,需要在方法中加入此方法的操作类型注解@operationtype,反之则默认为更新交易。
19.在上述步骤中,如果为查询操作则指定@operationtype(value=“query”),如果为更新操作则指定@operationtype(value=“update”)。
20.在上述步骤中,在项目中假如我们想对于所有的remote包下面的所有方法支持断点重试,那么我们可以这么定义:execution(*com.company.remote.*.*(..))。..))。
21.所述步骤2具体包括:
22.步骤2.1:对于业务流程f开启断点重试,只需要调用supportretry()方法,其中如果重试标识为false,则是正常交易流程,进行正常逻辑处理;如果重试标识为true,则是重试交易流程,进行重试逻辑处理。
23.在上述步骤中,所述步骤2.1中为正常交易交易,处理流程具体为:
24.(1)程序将以上几个参数放入threadlocal变量inputthreadlocal;
25.(2)在业务流程执行过程中,假设执行到方法m1,那么首先判断程序通过 inputthreadlocal是否为空,如果为空,说明开启了断点重试,如果不为空则说明没有开启断点重试,如果开启了断点重试,那么从inputthreadlocal中获取当前线程的入参信息,判断重试处理标识;
26.(3)判断重试处理标识是为false,则首先通过代理类执行实际方法,获取返回结果和返回值信息,判断结果为成功,则继续判断是否为查询交易,如果是忽略查询方法==true&& @operationtype(value=“query”),则不保存方法结果信息,否则将结果放入threadlocal 变量outputthreadlocal,并返回;判断结果为失败,则直接返回不做任何处理。
27.在上述步骤中,所述步骤2.1中为重试交易流程,处理流程具体为:
28.(1)首先通过交易唯一流水号查询出上次执行的结果信息并放入threadlocal变量 outputthreadlocal中,然后将入参放入threadlocal变量inputthreadlocal中;
29.(2)在业务流程执行过程中,假如说执行到方法m2,那么首先判断程序通过 inputthreadlocal是否为空,如果为空,说明开启了断点重试,如果不为空则说明没有开启断点重试,如果开启了断点重试,那么从inputthreadlocal中获取当前线程的入参信息,判断重试处理标识。
30.(3)判断重试处理标识是为true,则首先从outputthreadlocal中上次方法的执行记录,然后通过方法全限定名称和当前调用次数匹配到对应的上次执行记录,如果查询为空,则说明此方法还没有执行或者执行失败,通过代理直接调用方法执行,如果查询存在记录,则取出上次结果信息并反序列化为方法返回,返回调用方。
31.在上述步骤中,所述步骤2.1中假如在同一个流程中对于同一方法调用了两次,程序引入了第三个threadlocal变量callcountthreadlocal,此变量起到了计数器的作用,用于保存此线程每一个方法的执行次数,当第一次调用时,方法m1的调用次数为1,当第二次调用时,方法m1调用次数为2,依次类推。最后将本次执行方法对应次数与方法的返回一同保存起来。
32.所述步骤3包括以下步骤:
33.步骤3.1:当流程发生异常后,通过try..catch捕获异常;
34.步骤3.2:在catch块中调用persistretrydtos()方法;
35.步骤3.3:方法首先检索threadlocal变量outputthreadlocal中是否存在待保存执行成功的方法返回信息,如果不存在,则不做任何处理;
36.步骤3.4:如果存在待保存信息,调用持久化方法,将实体信息集合保存到本地数据库。
37.所述步骤4包括以下步骤:
38.步骤4.1:在方法执行完毕,返回之前,通过try..finally中的finally处理块中清除缓存;
39.步骤4.2:在finally块中调用clear()方法;
40.步骤4.2:方法获取inputthreadlocal、outputthreadlocal、callcountthreadlocal三个线程变量,并调用它们的remove方法做清空,防止程序执行完毕线程变量没有释放,导致内存溢出。
41.综上所述,由于采用了上述技术方案,本发明的有益效果是:
42.1.程序断点重试。通过基于threadlocal aop的技术手段,起到了异常后业务流程快速恢复的作用,解决了现有技术中手工处理人力浪费、耗时长、容易出错的缺陷,实现了断点重试、多次断点重试的效果。
43.2.支持mq、dubbo、sofa等多种调用方式的断点重试。通过统一对于mq、dubbo、sofa公共入口做了切面处理技术手段,起到了灵活配置的作用,解决了断点重试不够灵活、支持场景较少的缺陷,实现了支持多种调用方式重试的效果。
44.3.支持同一方法多次调用的断点重试。通过巧妙的利用线程变量callcountthreadlocal 来记录每个方法调用次数的技术手段,起到了被调用方法计数的作用,解决了同一方法多次调用无法区别的问题,实现了重试处理时遇到对于同一方法已经执行成功的调用选择跳过,对于没有执行成功的调用继续调用的效果。
45.4.当考虑流程查询方法无影响时,支持忽略保存查询方法。通过定义@operationtype注解的方式,起到了定义该方法是“查询”或者“更新”的作用,解决了查询方法可以忽略仍然保存带来的效率效率和存储资源浪费问题,实现了查询方法灵活决定是否保存的效果。
46.5.多种存储方式的支持。通过默认实现的三种存储方式,并开放给使用者自定义存储方式实现的手段,起到了开发者可以灵活选择存储方式的作用,解决了没有mysql数据库依然支持断点重试的问题,实现了支持mysql、redis、zookeeper多种存储方式灵活选择的效果。
47.6.在手工处理方案中,需要开发人员非常熟悉业务处理逻辑,在业务失败后根据
代码处理逻辑将已经执行成功的交易回退掉。本发明中只需要开发逻辑中加入一定二开三清除几个步骤,开发人员无需了解业务逻辑,只要简单确认后点击程序重试即可。
48.7.在手工处理方案中,收到预警后需要耗费大量的人力来处理异常数据。本发明中,只需一个人通过页面单笔和批量重试,可以快速处理失败的交易。
49.8.在手工处理过程中非常容易出错,假如手工恢复一个账务发生异常的交易,但是由于手误或者疏忽大意,把数据恢复错误了,那么可能会影响到后续的账务操作,还可能会导致更复杂的账务问题。在本发明的技术方案中,由于无需手工干预程序业务处理结果数据,故不会存在手工处理带来的数据错误风险。
附图说明
50.本发明将通过例子并参照附图的方式说明,其中:
51.图1是本发明中断点重试整体处理流程图;
52.图2是本发明实施例中正常流程下业务处理逻辑图;
53.图3是本发明实施例中重试流程下业务处理逻辑图;
54.名词解释
55.threadlocal:是线程本地存储,在每个线程中都创建了一个threadlocalmap对象,每个线程可以访问自己内部threadlocalmap对象内的value,步骤中inputthreadlocal、 outputthreadlocal、callcountthreadlocal三个变量是threadlocal类型的变量,用来保存线程变量信息;
56.@operationtype:自定义注解,用来标注此方法是查询方法,还是更新方法,为断点重试功能提供方法的操作功能。里面主要分为“查询操作”和“更新操作”;
57.mq:消息队列,此处使用了mq接收并开始处理整个业务流程,也可以是其他异步的处理流程;
58.aop aspect:切面,底层通过aop实现,可以通过引入aspectj插件来定义;
59.threadlocal:线程变量,可以用来定义线程变量,不同线程互不影响,详细步骤中 inputthreadlocal、outputthreadlocal、callcountthreadlocal三个变量是threadlocal类型的变量;
60.db:存储介质,可以是mysql数据库、oracle数据库、也可以非关系型数据库redis、也可以是zookeeper;
61.gtw:网关微服务;
62.loan:借据微服务;
63.acct:账务微服务;
64.fee:费用微服务;
65.batch:批量微服务;
66.portal:门户微服务;
67.method1/method2/method3/method4:代表四个不同的方法,也可以认为是4个不同的业务处理逻辑,他们处于同一处理流程中,而且有先后调用顺序: method1

>method2

>method3

>method4;
68.持久化:就是将每个方法的结果数据保存起来,在断点重试的时候做判断跳过使
用。
具体实施方式
69.为使本技术实施例的目的、技术方案和优点更加清楚,下面将结合本技术实施例中附图,对本技术实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅是本技术一部分实施例,而不是全部的实施例。通常在此处附图中描述和示出的本技术实施例的组件可以各种不同的配置来布置和设计。因此,以下对在附图中提供的本技术的实施例的详细描述并非旨在限制要求保护的本技术的范围,而是仅仅表示本技术的选定实施例。基于本技术的实施例,本领域技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本技术保护的范围。
70.在本技术实施例的描述中,需要说明的是,术语“上”、“下”、“左”、“右”、“竖直”、“水平”、“内”、“外”等指示的方位或位置关系为基于附图所示的方位或位置关系,或者是该发明产品使用时惯常摆放的方位或位置关系,仅是为了便于描述本技术和简化描述,而不是指示或暗示所指的装置或元件必须具有特定的方位、以特定的方位构造和操作,因此不能理解为对本技术的限制。此外,术语“第一”、“第二”、“第三”等仅用于区分描述,而不能理解为指示或暗示相对重要性。
71.下面结合图1~图3对本发明作详细说明。
72.一种基于aop threadlocal技术的分布式系统断点重试方法,包括如下步骤:
73.步骤1:通过aop切面表达式指定需要支持断点重试的方法并定义所有方法的 operationtype;
74.其中,所述步骤1具体包括:
75.步骤1.1:借助aspectj插件,通过其中的@pointcut注解来指定切面;
76.步骤1.2:通过execution、@annotation函数名称进行匹配,或是通过args、@args方法参数进行匹配,或是通过within、target类名来进行匹配;
77.步骤1.3:指定之后,aop通过动态代理技术,对于所指定的方法进行环切,在方法执行前做重试的判断,或是在方法执行之后获取执行结果,并获取返回值;
78.在上述步骤中,在已经指定的方法中,如果想要支持忽略查询方法断点重试,需要在方法中加入此方法的操作类型注解@operationtype,反之则默认为更新交易。
79.在上述步骤中,如果为查询操作则指定@operationtype(value=“query”),如果为更新操作则指定@operationtype(value=“update”)。
80.在上述步骤中,在项目中假如我们想对于所有的remote包下面的所有方法支持断点重试,那么我们可以这么定义:execution(*com.company.remote.*.*(..))。..))。
81.步骤2:在需要支持断点重试的业务流程中开启断点重试;
82.所述步骤2具体包括:
83.步骤2.1:对于业务流程f开启断点重试,只需要调用supportretry()方法,其中如果重试标识为false,则是正常交易流程,进行正常逻辑处理;如果重试标识为true,则是重试交易流程,进行重试逻辑处理;如果重试标识为****,则是同一方法多次调用的处理流程,进行同一方法多次调用的处理流程逻辑处理。其中,方法入参需要指定重试标识、交易唯一流水号、业务类型、是否忽略查询方法几个参数。
84.上述步骤步骤2.1中,如果为正常交易交易,其处理流程具体为:
85.(1)程序将以上几个参数放入threadlocal变量inputthreadlocal;
86.(2)在业务流程执行过程中,假设执行到方法m1,那么首先判断程序通过 inputthreadlocal是否为空,如果为空,说明开启了断点重试,如果不为空则说明没有开启断点重试,如果开启了断点重试,那么从inputthreadlocal中获取当前线程的入参信息,判断重试处理标识;
87.(3)判断重试处理标识是为false,则首先通过代理类执行实际方法,获取返回结果和返回值信息,判断结果为成功,则继续判断是否为查询交易,如果是忽略查询方法==true&& @operationtype(value=“query”),则不保存方法结果信息,否则将结果放入threadlocal变量outputthreadlocal,并返回;判断结果为失败,则直接返回不做任何处理。
88.附图2为本实施例中对上述情况的详细解释:
89.图2中介绍了正常处理流程在分布式系统中的交互流程,途中涉及到5个微服务,包括: gtw

网关微服务,loan

借据微服务,acct

账务微服务,fee

费用微服务,batch

批量消息微服务,其中batch服务负责接收断点重试信息并持久化到数据库db中;
90.从gtw服务中开启一个业务流程,然后调用supportretry()方法“开启断点重试”,将本次交易的唯一标识放入inputthreadlocal中,然后调用本地方法“method1”,此时执行成功,则将“method1”返回值序列化为json串保存到outputthreadlocal;
91.然后调用loan服务远程方法“method2”,此时也执行成功,则将“method2”返回值序列化为json串保存到outputthreadlocal;
92.然后调用acct服务远程方法“method3”,此时发生异常,获取threadlocal中的执行记录,并调用batch服务持久化断点重试信息;如果成功,则继续调用fee服务“method4”;
93.最后清空threadlocal并结束处理流程。
94.在上述步骤中,所述步骤2.1中为重试交易流程,处理流程具体为:
95.(1)首先通过交易唯一流水号查询出上次执行的结果信息并放入threadlocal变量 outputthreadlocal中,然后将入参放入threadlocal变量inputthreadlocal中;
96.(2)在业务流程执行过程中,假如说执行到方法m2,那么首先判断程序通过inputthreadlocal是否为空,如果为空,说明开启了断点重试,如果不为空则说明没有开启断点重试,如果开启了断点重试,那么从inputthreadlocal中获取当前线程的入参信息,判断重试处理标识。
97.(3)判断重试处理标识是为true,则首先从outputthreadlocal中上次方法的执行记录,然后通过方法全限定名称和当前调用次数匹配到对应的上次执行记录,如果查询为空,则说明此方法还没有执行或者执行失败,通过代理直接调用方法执行,如果查询存在记录,则取出上次结果信息并反序列化为方法返回,返回调用方。
98.其中为重试流程时:mq接收消息后,程序开启断点重试,首先程序会判断是否重试流程,如果是重试流程,首先通过txnsn从db中获取上次的执行记录,并保存到threadlocal 中;程序首先执行method1,此时会进入切面逻辑,首先从threadlocal中获取此方法的执行记录,如果存在则直接跳过,如果不存在则执行方法的调用;后续调用后的处理逻辑同成功执行流程。
99.为了清楚的表达重试业务处理逻辑,附图3详细的表示了重试流程下,业务如何流转的。
100.图3中介绍了重试处理流程在分布式系统中的交互流程,途中涉及到6个微服务,包括: gtw

网关微服务,loan

借据微服务,acct

账务微服务,fee

费用微服务,batch

批量消息微服务,portal

内管微服务;其中batch服务负责接收断点重试信息并持久化到数据库db 中,portal服务实现通过前端页面发起重试处理;
101.从portal服务开启重试流程,获取重试报文信息,并通过mq异步通知gtw服务,其中在消息头headers中放入重试标识,以标识该交易为重试交易;
102.gtw服务接收重试通知流水,通过headers解析重试标识,如果重试标识为1,然后调用 supportretry()方法“开启断点重试”并传入重试标识,将本次交易的唯一标识txnsn放入inputthreadlocal中;然后根据txnsn调用batch服务查询执行日志并将执行日志放入 outputthreadlocal;
103.然后调用本地方法“method1”,调用前根据方法“method1”的全限定名称匹配执行记录,此时存在,则反序列化执行记录方法返回信息,并返回给调用方;
104.然后调用loan服务远程方法“method2”,调用前根据方法“method2”的全限定名称匹配执行记录,此时存在,则反序列化执行记录方法返回信息,并返回给调用方;
105.然后调用acct服务远程方法“method3”,调用前根据方法“method2”的全限定名称匹配执行记录,此时不存在,则直接进行方法调用,并将返回信息保存到outputthreadlocal;
106.然后调用fee服务远程方法“method4”,调用前根据方法“method4”的全限定名称匹配执行记录,此时不存在,则直接进行方法调用,此时发生异常,则重复图2中的异常后处理;
107.最后清空threadlocal并结束处理流程。
108.在上述步骤中,所述步骤2.1中假如在同一个流程中对于同一方法调用了两次,程序引入了第三个threadlocal变量callcountthreadlocal,此变量起到了计数器的作用,用于保存此线程每一个方法的执行次数,当第一次调用时,方法m1的调用次数为1,当第二次调用时,方法m1调用次数为2,依次类推。最后将本次执行方法对应次数与方法的返回一同保存起来。
109.步骤3:在发生异常后,持久化已经执行成功的方法返回值;
110.所述步骤3包括以下步骤:
111.步骤3.1:当流程发生异常后,通过try..catch捕获异常;
112.步骤3.2:在catch块中调用persistretrydtos()方法;
113.步骤3.3:方法首先检索threadlocal变量outputthreadlocal中是否存在待保存执行成功的方法返回信息,如果不存在,则不做任何处理;
114.步骤3.4:如果存在待保存信息,调用持久化方法,将实体信息集合保存到本地数据库。
115.步骤4:清空threadlocal变量,防止内存溢出。
116.所述步骤4包括以下步骤:
117.步骤4.1:在方法执行完毕,返回之前,通过try..finally中的finally处理块中清
除缓存;
118.步骤4.2:在finally块中调用clear()方法;
119.步骤4.2:方法获取inputthreadlocal、outputthreadlocal、callcountthreadlocal三个线程变量,并调用它们的remove方法做清空,防止程序执行完毕线程变量没有释放,导致内存溢出。
120.附图1是正常交易流程中断点重试的实现原理图,以下为该图的详细解释:
121.流程中通过接收请求开启处理流程,本图以“mq”接收为例说明;接收到请求数据后开启通过调用supportretry()方法“开启断点重试”;然后做“是否重试流程”的判断,如果非重试流程,则说明为正常流程,程序首先执行method1,此时会进入切面逻辑,切面中首先进行方法调用,在方法“method1/2/3/4”执行之前首先执行切面“aop aspect”逻辑,做“是否开启断点重试”判断,如果已经开启断点重试则进行后续逻辑处理,执行方法“method1/2/3/4”并获取方法返回信息,判断方法返回成功则保存到“threadlocal”中,如果方法执行返回失败则获取“threadlocal”中保存的所有方法返回信息,持久化到存储中,本图以“db”为例说明;
122.如果是“重试流程”,则通过交易流水号txnsn从“db”中获取上次的执行记录,将执行记录保存到threadlocal中,然后在切面逻辑“aop aspect”,判断为“重试流程”,则从“threadlocal”中根据方法全限定名称获取上次执行记录,如果获取成功则反序列化结果信息返回给调用方,如果获取失败则说明上次执行失败,本次继续执行此方法逻辑;
123.综上,最终实现了程序异常后,重新发起重试可以从断点处继续执行的目的。
124.以上所述实施例仅表达了本技术的具体实施方式,其描述较为具体和详细,但并不能因此而理解为对本技术保护范围的限制。应当指出的是,对于本领域的普通技术人员来说,在不脱离本技术技术方案构思的前提下,还可以做出若干变形和改进,这些都属于本技术的保护范围。
再多了解一些

本文用于企业家、创业者技术爱好者查询,结果仅供参考。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献