一、前言
在系统开发过程中,有些业务功能面临日切
(日期切换)问题,比如结息跑批问题,在当前工作日临近24点的时候触发结息,实际交易时间我们预期的是当前时间,但是由于业务执行耗时,可能进行了日切,业务跑到下一个工作日了,这样业务如果采用下一个工作日的时间进行业务计算,可能会导致业务结果与预期不一致
,有没有什么解决方案呢?
二、解决方案
在这里,我们可以采用一种解决方案,就是交易时间不采用系统时间,交易时间的获取从上游应用(可以从时间服务器获取)请求传递下来,下游应用在处理业务时,采用传递的交易时间,而不是直接使用系统时间来处理。
下面采用一个案例进行演示说明:比如我们有一个利息结算场景,需要对金额进行每天产生的利息进行结算,某些请求可能在临近24点的时候触发,此时,下游系统处理时可能发生日切,此时我们要保证业务结果是符合预期的,按照上述描述进行演示。
1. 搭建nacos注册中心
我们这里采用两个应用来进行模拟业务请求,需要用到注册中心,这里采用Nacos作为注册中心:Nacos下载地址
Nacos部署可以参考:nacos安装手册
2. 创建服务提供方应用
首先创建一个简单spring Boot应用,当做服务提供方。
-
导入相关依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
-
增加相关配置
server: port: 7092 spring: cloud: nacos: discovery: namespace: public server-addr: 127.0.0.1:8848 application: name: provider
-
编写业务逻辑代码:
import com.alibaba.nacos.api.utils.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.Map; @RestController public class ProviderController { /** * 计算利息 * * @param paraMap * @return */ // 以下逻辑只是为了业务说明,并非真实业务 @PostMapping("/calInterest") public BigDecimal calInterest(@RequestBody Map<String, Object> paraMap) { // 以下逻辑只是为了业务说明,并非真实业务 // 获取交易日期 String traceDateStr = (String) paraMap.get("traceDate"); // 如果有交易日期则取当前日期,否则取系统时间 LocalDate traceDate = StringUtils.isBlank(traceDateStr) ? LocalDate.now() : LocalDate.parse(traceDateStr); // 获取存款日期 LocalDate