网友投稿 373 2022-06-21
随着互联网应用的深入,很多传统行业也都需要接入到互联网。我们公司也是这样,保险核心需要和很多保险中介对接,比如阿里、京东等等。这些公司对于接口服务的性能有些比较高的要求,传统的核心无法满足要求,所以信息技术部领导高瞻远瞩,决定开发互联网接入服务,满足来自性能的需求。
概念
CompletionService将Executor和BlockingQueue的功能融合在一起,将Callable任务提交给CompletionService来执行,然后使用类似于队列操作的take和poll等方法来获得已完成的结果,而这些结果会在完成时被封装为Future。对于更多的概念,请参阅其他网络文档。
线程池的设计,阿里开发手册说过不要使用Java Executors 提供的默认线程池,因此需要更接近实际的情况来自定义一个线程池,根据多次压测,采用的线程池如下:
public ExecutorService getThreadPool(){
return new ThreadPoolExecutor(75,
125,
180000,
TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<>(450),
new ThreadPoolExecutor.CallerRunsPolicy());
}
说明:公司的业务为低频交易,对于单次调用性能要求高,但是并发压力根本不大,所以 阻塞队列已满且线程数达到最大值时所采取的饱和策略为调用者执行。
实现
业务
投保业务主要涉及这几个大的方面:投保校验、核保校验、保费试算
投保校验:最主要的是要查询客户黑名单和风险等级,都是千万级的表。而且投保人和被保人都需要校验
核保校验:除了常规的核保规则校验,查询千万级的大表,还需要调用外部智能核保接口获得用户的风险等级,投保人和被保人都需要校验
保费试算:需要计算每个险种的保费
设计
根据上面的业务,如果串行执行的话,单次性能肯定不高,所以考虑多线程异步执行获得校验结果,再对结果综合判断
投保校验:采用一个线程(也可以根据投保人和被保人数量来采用几个线程)
核保校验:
常规校验:采用一个线程
外部调用:有几个用户(指投保人和被保人)就采用几个线程
保费计算:有几个险种就采用几个线程,最后合并得到整个的保费
代码
以下代码是样例,实际逻辑已经去掉
先创建投保、核保(常规、外部调用)、保费计算4个业务服务类:
投保服务类:InsuranceVerificationServiceImpl,假设耗时50ms
@Service
public class InsuranceVerificationServiceImpl implements InsuranceVerificationService {
private static final Logger logger = LoggerFactory.getLogger(InsuranceVerificationServiceImpl.class);
@Override
public TaskResponseModel insuranceCheck(String key, PolicyModel policyModel) { try { //假设耗时50ms Thread.sleep(50); return TaskResponseModel.success().setKey(key).setData(policyModel); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }核保常规校验服务类:UnderwritingCheckServiceImpl,假设耗时50ms@Service public class UnderwritingCheckServiceImpl implements UnderwritingCheckService { private static final Logger logger = LoggerFactory.getLogger(UnderwritingCheckServiceImpl.class); @Override public TaskResponseModel underwritingCheck(String key, PolicyModel policyModel) { try { //假设耗时50ms Thread.sleep(50); return TaskResponseModel.success().setKey(key).setData(policyModel); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }核保外部调用服务类:ExternalCallServiceImpl,假设耗时200ms@Service public class ExternalCallServiceImpl implements ExternalCallService { private static final Logger logger = LoggerFactory.getLogger(ExternalCallServiceImpl.class); @Override public TaskResponseModel externalCall(String key, Insured insured) { try { //假设耗时200ms Thread.sleep(200); ExternalCallResultModel externalCallResultModel = new ExternalCallResultModel(); externalCallResultModel.setIdcard(insured.getIdcard()); externalCallResultModel.setScore(200); return TaskResponseModel.success().setKey(key).setData(externalCallResultModel); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }试算服务类:TrialCalculationServiceImpl,假设耗时50ms@Service public class TrialCalculationServiceImpl implements TrialCalculationService { private static final Logger logger = LoggerFactory.getLogger(TrialCalculationServiceImpl.class); @Override public TaskResponseModel trialCalc(String key, Risk risk) { try { //假设耗时50ms Thread.sleep(50); return TaskResponseModel.success().setKey(key).setData(risk); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }统一返回接口类:TaskResponseModel, 上面4个服务的方法统一返回TaskResponseModel@Data @ToString @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode @Accessors(chain = true) public class TaskResponseModel implements Serializable { private String key; //唯一调用标志 private String resultCode; //结果码 private String resultMessage; //结果信息 private T data; //业务处理结果 public static TaskResponseModel success() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("200"); return taskResponseModel; } public static TaskResponseModel failure() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
try {
//假设耗时50ms
Thread.sleep(50);
return TaskResponseModel.success().setKey(key).setData(policyModel);
} catch (InterruptedException e) {
logger.warn(e.getMessage());
return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage());
核保常规校验服务类:UnderwritingCheckServiceImpl,假设耗时50ms
public class UnderwritingCheckServiceImpl implements UnderwritingCheckService {
private static final Logger logger = LoggerFactory.getLogger(UnderwritingCheckServiceImpl.class);
public TaskResponseModel underwritingCheck(String key, PolicyModel policyModel) { try { //假设耗时50ms Thread.sleep(50); return TaskResponseModel.success().setKey(key).setData(policyModel); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }核保外部调用服务类:ExternalCallServiceImpl,假设耗时200ms@Service public class ExternalCallServiceImpl implements ExternalCallService { private static final Logger logger = LoggerFactory.getLogger(ExternalCallServiceImpl.class); @Override public TaskResponseModel externalCall(String key, Insured insured) { try { //假设耗时200ms Thread.sleep(200); ExternalCallResultModel externalCallResultModel = new ExternalCallResultModel(); externalCallResultModel.setIdcard(insured.getIdcard()); externalCallResultModel.setScore(200); return TaskResponseModel.success().setKey(key).setData(externalCallResultModel); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }试算服务类:TrialCalculationServiceImpl,假设耗时50ms@Service public class TrialCalculationServiceImpl implements TrialCalculationService { private static final Logger logger = LoggerFactory.getLogger(TrialCalculationServiceImpl.class); @Override public TaskResponseModel trialCalc(String key, Risk risk) { try { //假设耗时50ms Thread.sleep(50); return TaskResponseModel.success().setKey(key).setData(risk); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }统一返回接口类:TaskResponseModel, 上面4个服务的方法统一返回TaskResponseModel@Data @ToString @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode @Accessors(chain = true) public class TaskResponseModel implements Serializable { private String key; //唯一调用标志 private String resultCode; //结果码 private String resultMessage; //结果信息 private T data; //业务处理结果 public static TaskResponseModel success() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("200"); return taskResponseModel; } public static TaskResponseModel failure() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
核保外部调用服务类:ExternalCallServiceImpl,假设耗时200ms
public class ExternalCallServiceImpl implements ExternalCallService {
private static final Logger logger = LoggerFactory.getLogger(ExternalCallServiceImpl.class);
public TaskResponseModel externalCall(String key, Insured insured) { try { //假设耗时200ms Thread.sleep(200); ExternalCallResultModel externalCallResultModel = new ExternalCallResultModel(); externalCallResultModel.setIdcard(insured.getIdcard()); externalCallResultModel.setScore(200); return TaskResponseModel.success().setKey(key).setData(externalCallResultModel); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }试算服务类:TrialCalculationServiceImpl,假设耗时50ms@Service public class TrialCalculationServiceImpl implements TrialCalculationService { private static final Logger logger = LoggerFactory.getLogger(TrialCalculationServiceImpl.class); @Override public TaskResponseModel trialCalc(String key, Risk risk) { try { //假设耗时50ms Thread.sleep(50); return TaskResponseModel.success().setKey(key).setData(risk); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }统一返回接口类:TaskResponseModel, 上面4个服务的方法统一返回TaskResponseModel@Data @ToString @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode @Accessors(chain = true) public class TaskResponseModel implements Serializable { private String key; //唯一调用标志 private String resultCode; //结果码 private String resultMessage; //结果信息 private T data; //业务处理结果 public static TaskResponseModel success() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("200"); return taskResponseModel; } public static TaskResponseModel failure() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
//假设耗时200ms
Thread.sleep(200);
ExternalCallResultModel externalCallResultModel = new ExternalCallResultModel();
externalCallResultModel.setIdcard(insured.getIdcard());
externalCallResultModel.setScore(200);
return TaskResponseModel.success().setKey(key).setData(externalCallResultModel);
试算服务类:TrialCalculationServiceImpl,假设耗时50ms
public class TrialCalculationServiceImpl implements TrialCalculationService {
private static final Logger logger = LoggerFactory.getLogger(TrialCalculationServiceImpl.class);
public TaskResponseModel trialCalc(String key, Risk risk) { try { //假设耗时50ms Thread.sleep(50); return TaskResponseModel.success().setKey(key).setData(risk); } catch (InterruptedException e) { logger.warn(e.getMessage()); return TaskResponseModel.failure().setKey(key).setResultMessage(e.getMessage()); } } }统一返回接口类:TaskResponseModel, 上面4个服务的方法统一返回TaskResponseModel@Data @ToString @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode @Accessors(chain = true) public class TaskResponseModel implements Serializable { private String key; //唯一调用标志 private String resultCode; //结果码 private String resultMessage; //结果信息 private T data; //业务处理结果 public static TaskResponseModel success() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("200"); return taskResponseModel; } public static TaskResponseModel failure() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
return TaskResponseModel.success().setKey(key).setData(risk);
统一返回接口类:TaskResponseModel, 上面4个服务的方法统一返回TaskResponseModel
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Accessors(chain = true)
public class TaskResponseModel implements Serializable {
private String key; //唯一调用标志
private String resultCode; //结果码
private String resultMessage; //结果信息
private T data; //业务处理结果
public static TaskResponseModel success() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("200"); return taskResponseModel; } public static TaskResponseModel failure() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("200"); return taskResponseModel; } public static TaskResponseModel failure() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
taskResponseModel.setResultCode("200");
return taskResponseModel;
public static TaskResponseModel failure() { TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
TaskResponseModel taskResponseModel = new TaskResponseModel<>(); taskResponseModel.setResultCode("400"); return taskResponseModel; } }注:key为这次调用的唯一标识,由调用者传进来resultCode结果码,200为成功,400表示有异常resultMessage信息,表示不成功或者异常信息data业务处理结果,如果成功的话 这些服务类都是单例模式要使用用CompletionService的话,需要创建实现了Callable接口的线程投保Callable:@Data @AllArgsConstructor public class InsuranceVerificationCommand implements Callable> { private String key; private PolicyModel policyModel; private final InsuranceVerificationService insuranceVerificationService; @Override public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
taskResponseModel.setResultCode("400");
注:
key为这次调用的唯一标识,由调用者传进来
resultCode结果码,200为成功,400表示有异常
resultMessage信息,表示不成功或者异常信息
data业务处理结果,如果成功的话
这些服务类都是单例模式
要使用用CompletionService的话,需要创建实现了Callable接口的线程
投保Callable:
public class InsuranceVerificationCommand implements Callable> {
private String key;
private PolicyModel policyModel;
private final InsuranceVerificationService insuranceVerificationService;
public TaskResponseModel call() throws Exception { return insuranceVerificationService.insuranceCheck(key, policyModel); } }核保常规校验Callable:@Data @AllArgsConstructor public class UnderwritingCheckCommand implements Callable> { private String key; private PolicyModel policyModel; private final UnderwritingCheckService underwritingCheckService; @Override public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
return insuranceVerificationService.insuranceCheck(key, policyModel);
核保常规校验Callable:
public class UnderwritingCheckCommand implements Callable> {
private final UnderwritingCheckService underwritingCheckService;
public TaskResponseModel call() throws Exception { return underwritingCheckService.underwritingCheck(key, policyModel); } }核保外部调用Callable:@Data @AllArgsConstructor public class ExternalCallCommand implements Callable> { private String key; private Insured insured; private final ExternalCallService externalCallService; @Override public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
return underwritingCheckService.underwritingCheck(key, policyModel);
核保外部调用Callable:
public class ExternalCallCommand implements Callable> {
private Insured insured;
private final ExternalCallService externalCallService;
public TaskResponseModel call() throws Exception { return externalCallService.externalCall(key, insured); } }试算调用Callable:@Data @AllArgsConstructor public class TrialCalculationCommand implements Callable> { private String key; private Risk risk; private final TrialCalculationService trialCalculationService; @Override public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
return externalCallService.externalCall(key, insured);
试算调用Callable:
public class TrialCalculationCommand implements Callable> {
private Risk risk;
private final TrialCalculationService trialCalculationService;
public TaskResponseModel call() throws Exception { return trialCalculationService.trialCalc(key, risk); } }注:每一次调用,需要创建这4种Callable 返回统一接口TaskResopnseModel异步执行的类:TaskExecutor@Component public class TaskExecutor { private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class); //线程池 private final ExecutorService executorService; public TaskExecutor(ExecutorService executorService) { this.executorService = executorService; } //异步执行,获取所有结果后返回 public List> execute(List>> commands) { //创建异步执行对象 CompletionService> completionService = new ExecutorCompletionService<>(executorService); for (Callable> command : commands) { completionService.submit(command); } //获取所有异步执行线程的结果 int taskCount = commands.size(); List> params = new ArrayList<>(taskCount); try { for (int i = 0; i < taskCount; i++) { Future> future = completionService.take(); params.add(future.get()); } } catch (InterruptedException | ExecutionException e) { //异常处理 params.clear(); params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误")); } //返回,如果执行中发生error, 则返回相应的key值:error return params; } }注:为单例模式 接收参数为List>>,也就是上面定义的4种Callable的列表 返回List>,也就是上面定义4种Callable返回的结果列表 我们的业务是对返回结果统一判断,业务返回结果有因果关系 如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;调用方:CompletionServiceController@RestController public class CompletionServiceController { //投保key private static final String INSURANCE_KEY = "insurance_"; //核保key private static final String UNDERWRITING_KEY = "underwriting_"; //外部调用key private static final String EXTERNALCALL_KEY = "externalcall_"; //试算key private static final String TRIA_KEY = "trial_"; private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class); private final ExternalCallService externalCallService; private final InsuranceVerificationService insuranceVerificationService; private final TrialCalculationService trialCalculationService; private final UnderwritingCheckService underwritingCheckService; private final TaskExecutor taskExecutor; public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) { this.externalCallService = externalCallService; this.insuranceVerificationService = insuranceVerificationService; this.trialCalculationService = trialCalculationService; this.underwritingCheckService = underwritingCheckService; this.taskExecutor = taskExecutor; } //多线程异步并发接口 @PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8") public String asyncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); asyncExecute(policyModel); logger.info("异步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } //串行调用接口 @PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8") public String syncExec(@RequestBody PolicyModel policyModel) { long start = System.currentTimeMillis(); syncExecute(policyModel); logger.info("同步总共耗时:" + (System.currentTimeMillis() - start)); return "ok"; } private void asyncExecute(PolicyModel policyModel) { List>> baseTaskCallbackList = new ArrayList<>(); //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService); baseTaskCallbackList.add(externalCallCommand); } //投保校验 InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService); baseTaskCallbackList.add(insuranceVerificationCommand); //核保校验 UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService); baseTaskCallbackList.add(underwritingCheckCommand); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService); baseTaskCallbackList.add(trialCalculationCommand); } List> results = taskExecutor.execute(baseTaskCallbackList); for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
return trialCalculationService.trialCalc(key, risk);
每一次调用,需要创建这4种Callable
返回统一接口TaskResopnseModel
异步执行的类:TaskExecutor
@Component
public class TaskExecutor {
private static final Logger logger = LoggerFactory.getLogger(TaskExecutor.class);
//线程池
private final ExecutorService executorService;
public TaskExecutor(ExecutorService executorService) {
this.executorService = executorService;
//异步执行,获取所有结果后返回
public List> execute(List>> commands) {
//创建异步执行对象
CompletionService> completionService = new ExecutorCompletionService<>(executorService);
for (Callable> command : commands) {
completionService.submit(command);
//获取所有异步执行线程的结果
int taskCount = commands.size();
List> params = new ArrayList<>(taskCount);
for (int i = 0; i < taskCount; i++) {
Future> future = completionService.take();
params.add(future.get());
} catch (InterruptedException | ExecutionException e) {
//异常处理
params.clear();
params.add(TaskResponseModel.failure().setKey("error").setResultMessage("异步执行线程错误"));
//返回,如果执行中发生error, 则返回相应的key值:error
return params;
为单例模式
接收参数为List>>,也就是上面定义的4种Callable的列表
返回List>,也就是上面定义4种Callable返回的结果列表
我们的业务是对返回结果统一判断,业务返回结果有因果关系
如果线程执行有异常,也返回List,这个时候列表中只有一个TaskResponseModel,key为error, 后续调用者可以通过这个来判断线程是否执行成功;
调用方:CompletionServiceController
@RestController
public class CompletionServiceController {
//投保key
private static final String INSURANCE_KEY = "insurance_";
//核保key
private static final String UNDERWRITING_KEY = "underwriting_";
//外部调用key
private static final String EXTERNALCALL_KEY = "externalcall_";
//试算key
private static final String TRIA_KEY = "trial_";
private static final Logger logger = LoggerFactory.getLogger(CompletionServiceController.class);
private final TaskExecutor taskExecutor;
public CompletionServiceController(ExternalCallService externalCallService, InsuranceVerificationService insuranceVerificationService, TrialCalculationService trialCalculationService, UnderwritingCheckService underwritingCheckService, TaskExecutor taskExecutor) {
this.externalCallService = externalCallService;
this.insuranceVerificationService = insuranceVerificationService;
this.trialCalculationService = trialCalculationService;
this.underwritingCheckService = underwritingCheckService;
this.taskExecutor = taskExecutor;
//多线程异步并发接口
@PostMapping(value = "/async", headers = "Content-Type=application/json;charset=UTF-8")
public String asyncExec(@RequestBody PolicyModel policyModel) {
long start = System.currentTimeMillis();
asyncExecute(policyModel);
logger.info("异步总共耗时:" + (System.currentTimeMillis() - start));
return "ok";
//串行调用接口
@PostMapping(value = "/sync", headers = "Content-Type=application/json;charset=UTF-8")
public String syncExec(@RequestBody PolicyModel policyModel) {
syncExecute(policyModel);
logger.info("同步总共耗时:" + (System.currentTimeMillis() - start));
private void asyncExecute(PolicyModel policyModel) {
List>> baseTaskCallbackList = new ArrayList<>();
//根据被保人外部接口调用
for (Insured insured : policyModel.getInsuredList()) {
ExternalCallCommand externalCallCommand = new ExternalCallCommand(EXTERNALCALL_KEY + insured.getIdcard(), insured, externalCallService);
baseTaskCallbackList.add(externalCallCommand);
//投保校验
InsuranceVerificationCommand insuranceVerificationCommand = new InsuranceVerificationCommand(INSURANCE_KEY, policyModel, insuranceVerificationService);
baseTaskCallbackList.add(insuranceVerificationCommand);
//核保校验
UnderwritingCheckCommand underwritingCheckCommand = new UnderwritingCheckCommand(UNDERWRITING_KEY, policyModel, underwritingCheckService);
baseTaskCallbackList.add(underwritingCheckCommand);
//根据险种进行保费试算
for(Risk risk : policyModel.getRiskList()) {
TrialCalculationCommand trialCalculationCommand = new TrialCalculationCommand(TRIA_KEY + risk.getRiskcode(), risk, trialCalculationService);
baseTaskCallbackList.add(trialCalculationCommand);
List> results = taskExecutor.execute(baseTaskCallbackList);
for (TaskResponseModel t : results) { if (t.getKey().equals("error")) { logger.warn("线程执行失败"); logger.warn(t.toString()); } logger.info(t.toString()); } } private void syncExecute(PolicyModel policyModel) { //根据被保人外部接口调用 for (Insured insured : policyModel.getInsuredList()) { TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
if (t.getKey().equals("error")) {
logger.warn("线程执行失败");
logger.warn(t.toString());
logger.info(t.toString());
private void syncExecute(PolicyModel policyModel) {
TaskResponseModel externalCall = externalCallService.externalCall(insured.getIdcard(), insured); logger.info(externalCall.toString()); } //投保校验 TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
logger.info(externalCall.toString());
TaskResponseModel insurance = insuranceVerificationService.insuranceCheck(INSURANCE_KEY, policyModel); logger.info(insurance.toString()); //核保校验 TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
logger.info(insurance.toString());
TaskResponseModel underwriting = underwritingCheckService.underwritingCheck(UNDERWRITING_KEY, policyModel); logger.info(underwriting.toString()); //根据险种进行保费试算 for(Risk risk : policyModel.getRiskList()) { TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
logger.info(underwriting.toString());
TaskResponseModel risktrial = trialCalculationService.trialCalc(risk.getRiskcode(), risk); logger.info(risktrial.toString()); } } }注:1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行2.在异步并发执行函数asyncExecute中:根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。 根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的 创建投保校验的Callable实例,业务上只需要一个 创建核保校验的Callable实例,业务上只需要一个 将Callable列表传入到TaskExecutor执行异步并发调用 根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)验证验证数据:{"insuredList":[{"idcard":"laza","name":"320106"},{"idcard":"ranran","name":"120102"}],"policyHolder":"lazasha","policyNo":"345000987","riskList":[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]}上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.本地开发的配置为8C16G:同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms 多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms验证:同步接口输出耗时:可以看到耗时601ms验证:多线程异步执行接口输出耗时:可以看到为204ms结果:基本和我们的预期相符合。结束这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git 版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。 上一篇:Linux中Hadoop的安装与配置(Hadoop安装方式) 下一篇:在ServletFilter层返回多字段提示给前端(servlet返回数据给前端) 相关文章 Java编程实现NBA赛事接口调用实例代码 373 2022-06-21 Python怎么调用GPT3.5接口 373 2022-06-21 Laravel中处理接口并发的方法 373 2022-06-21 发表评论 取消回复 发布评论 暂时没有评论,来抢沙发吧~ 推荐文章 接口调用是什么意思?几种常用接口调用方式接口设计原则8款在线 API 接口文档管理工具api管理系统是什么?什么是接口调试?接口调试的步骤有哪些?api 接口管理系统有哪些?接口测试有几种测试方法API文档生成工具有哪些?微服务和api网关区别交换机配置步骤 最近发表 多平台统一管理软件接口,如何实现多平台统一管理软件接口 Flask接口签名sign原理与实例代码浅析 java中的接口是类吗 vue项目接口域名动态的获取方法 zookeeper python接口实例详解 Iterator与LIstIterator接口在java中的区别有哪些 c#自定义Attribute获取接口实现示例代码 hdml指的是什么接口 分析EBS常用接口表 java 单机接口限流处理方案 热评文章 在线接口文档管理工具推荐,支持在线测试,HTTP接口开源的在线接口文档wiki工具Mindoc的介绍与使如何优雅的进行接口设计?接口设计的六大原则是什么?什么是API测试,api检测公司遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息软件接口设计怎么做?前后端分离软件接口设计思路
logger.info(risktrial.toString());
1.为测试方便,提供两个接口调用:一个是串行执行,一个是异步并发执行
2.在异步并发执行函数asyncExecute中:
根据有多少个被保人,创建多少个外部调用的Callable实例,key值为EXTERNALCALL_KEY + insured.getIdcard(),在一次保单投保调用中,每一个被保人Callable的key是不一样的。
根据有多少个险种,创建多少个试算的Callable实例,key为TRIA_KEY + risk.getRiskcode(),在一次保单投保调用中,每一个险种的Callable的key是不一样的
创建投保校验的Callable实例,业务上只需要一个
创建核保校验的Callable实例,业务上只需要一个
将Callable列表传入到TaskExecutor执行异步并发调用
根据返回结果来判断,通过判断返回的TaskResponseModel的key值可以知道是哪类业务校验,分别进行判断,还可以交叉判断(公司的业务就是要交叉判断)
验证
验证数据:
{
"insuredList":
[{"idcard":"laza","name":"320106"},
{"idcard":"ranran","name":"120102"}],
"policyHolder":"lazasha","policyNo":"345000987","riskList":
[{"mainFlag":1,"premium":300,"riskcode":"risk001","riskname":"险种一"},
{"mainFlag":0,"premium":400,"riskcode":"risk002","riskname":"险种二"}]
上面数据表明:有两个被保人,两个险种。按照我们上面的定义,会调用两次外部接口,两次试算,一次投保,一次核保。而在样例代码中,一次外部接口调用耗时为200ms, 其他都为50ms.
本地开发的配置为8C16G:
同步串行接口调用计算:2 * 200 + 2 * 50 + 50 + 50 = 600ms
多线程异步执行调用计算:按照多线程并发执行原理,取耗时最长的200ms
验证:同步接口
输出耗时:可以看到耗时601ms
验证:多线程异步执行接口
输出耗时:可以看到为204ms
结果:基本和我们的预期相符合。
结束
这是将实际生产中的例子简化出来,具体生产的业务比较复杂,不便于展示。
实际情况下,原来的接口需要1000ms以上才能完成单次调用,有的需要2000-3000ms。现在的接口,在生产两台8c16g的虚拟机, 经过4个小时的简单压测能够支持2000用户并发,单次返回时长为350ms左右,服务很稳定,完全能够满足公司的业务发展需求。
提供的这个是可以运行的列子,代码在:https://github.com/lazasha111211/completionservice-demo.git
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~