需求:項目增長冪等java
場景:
1.三個項目:a 、b、c
2.a項目加冪等
3.b項目dubbo調用項目a的時候超時沒有獲取返回結果,增長重試機制(非當即重試,3min or 5min 後重試)
4.c項目是一個異步的job項目,用來接收mq,異步處理,管理task等。redis
方案:
1.a項目設置請求流水id,將請求先存入redis緩存,處理完成以後更新redis中的狀態,同一個流水id認爲是重複提交,不進行業務處理,直接返回redis中的狀態
2.b項目捕獲調用a項目的超時異常,存入redis隊列
3.c項目啓動兩個task,task1用來獲取redis隊列裏面的信息,落庫。task2用來掃庫,及重試。spring
重點:
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));
圈重點:app
1.inter須要是serviceImpl實現類,若是是interface的話,會報異步
Caused by: java.lang.NoSuchMethodException: com.xxx.xxx.xxx.xxx.xxx.<init>()
2.invoke(Object obj,Object... args) 這裏的obj須要newInstance()一下,不然會報this
java.lang.IllegalArgumentException: object is not an instance of declaring class
調用dubbo接口的寫法:(map爲請求參數)spa
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的方式獲取對象進行反射調用。code
將interface及method配置到數據庫中,就能實現不用改動代碼進行調用的操做了。