需求:項目增加冪等
場景:
1.三個項目:a 、b、c
2.a項目加冪等
3.b項目dubbo調用項目a的時候超時沒有獲取返回結果,增加重試機制(非立即重試,3min or 5min 后重試)
4.c項目是一個異步的job項目,用來接收mq,異步處理,管理task等。
方案:
1.a項目設置請求流水id,將請求先存入redis緩存,處理完成之后更新redis中的狀態,同一個流水id認為是重復提交,不進行業務處理,直接返回redis中的狀態
2.b項目捕獲調用a項目的超時異常,存入redis隊列
3.c項目啟動兩個task,task1用來獲取redis隊列里面的信息,落庫。task2用來掃庫,及重試。
重點:
1.c項目只是異步接口消息沒有業務處理邏輯
2.task2重試的時候需要通過dubbo接口調用b來進行重新發起請求,及后續處理。
這里重點分享一下通過反射機制調用dubbo接口(map為請求參數)
String inter = "com.xxx.xxx.xxx.xxx.xxx.xxx"; Class<?> mClass = Class.forName(inter); Method method = mClass.getMethod("methodNamexxx",new Class[]{String.class}); Object object = method.invoke(mClass.newInstance(),JSON.toJSONString(map));
圈重點:
1.inter需要是serviceImpl實現類,如果是interface的話,會報
Caused by: java.lang.NoSuchMethodException: com.xxx.xxx.xxx.xxx.xxx.<init>()
2.invoke(Object obj,Object... args) 這里的obj需要newInstance()一下,否則會報
java.lang.IllegalArgumentException: object is not an instance of declaring class
調用dubbo接口的寫法:(map為請求參數)
String inter = "com.xxx.xxx.xxx.IxxxService";
String methodName = "xxxxx";
Class<?> mClass = Class.forName(inter); Map<String,Object> map = new HashMap<>(); AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Object obj = context.getBean(this.getBeanName(inter)); Method method = mClass.getMethod(methodName,new Class[]{Object.class}); Object object = method.invoke(obj,JSON.toJSON(map));
public String getBeanName(String str){ String name = str.substring(str.lastIndexOf(".")+2,str.length()); name = name.substring(0,1).toLowerCase() + name.substring(1,name.length()); return name; }
通過解析inter獲取beanName,通過spring獲取bean的方式獲取對象進行反射調用。
將interface及method配置到數據庫中,就能實現不用改動代碼進行調用的操作了。