1. Background
After the business process, you need to call other system interfaces, the corresponding processing results are notified to the other side, if the synchronous request, if the system is called abnormal or down events, it will cause its own business is affected, the transaction will be blocked, the database connection is not enough, such as abnormal phenomena, can be asynchronous callback to prevent blocking, But there is a problem with the asynchronous situation, if the call is unsuccessful, what happens next? This place needs to be in the time gradient callback, such as the early press 10s interval callback, callback 3 times, if not successfully press the 30s callback, callback 2 times, or not successfully by the minute callback, and so on ... Equivalent to the other side of the system to restore the time, can not always be in an abnormal state or downtime, such as abnormal status, if it is not successful again through the means of manual intervention to deal with, specific business implementation.
2. Technology implementation
The general realization of the idea, such as this process with two queues, the current queue and next queue, the current queue is used to hold the first callback data object, if the call is not successful in the next queue, according to the established time policy to continue the callback until the successful or final persistence after the manual access processing.
The following techniques are used:
- HTTP request Library, Retrofit2
- Queue, Linkedblockingqueue
- Dispatch thread pool, Scheduledexecutorservice
3. Main code Description
Strategy design of 3.1 callback time gradient
The enumeration is used to process the policy rules, which facilitates the maintenance of the code, which designs three parameters, level, callback interval and number of callbacks;
/*** Callback Policy*/ Public enumCallbacktype {//level 1,10s performed 3 timesSECONDS_10 (1, 10, 3), //level 2,30s performed 2 timesSeconds_30 (2, 30, 2), //level 3,60s performed 2 timesMinute_1 (3, 60, 2), //level 4,5min performed 1 timesMinute_5 (4, 300, 1), //level 5,30min performed 1 timesMinute_30 (5, 30*60, 1), //level 6,1h performed 2 timesHour_1 (6, 60*60, 1), //level 7,3h performed 2 timesHour_3 (7, 60*60*3, 1), //level 8,6h performed 2 timesHour_6 (8, 60*60*6, 1); //level Private intLevel ; //callback interval time seconds Private intIntervalTime; //Number of callbacks Private intcount;}
3.2 Data Transfer Object design
Declares an abstract parent class, making it easier for other objects to invoke transport inheritance.
/*** Message Object parent class*/ Public Abstract classMessageinfo {//Start Time Private LongStartTime; //Update Time Private LongUpdateTime; //whether the callback succeeded Private Booleanissuccess=false; //Number of callbacks Private intCount=0; //Callback Policy Privatecallbacktype Callbacktype;}
The object to transfer, inheriting the message parent class;
/*** Ticket Callback information*/ Public classWorkordermessageextendsMessageinfo {//Frame Number PrivateString vin; //Ticket number PrivateString Workorderno; //Work order Status PrivateInteger status; //Work Order Reason PrivateString reason; //Manipulating Users PrivateInteger userid;}
3.3 Use of the scheduling thread pool
//declaration thread pool, sizePrivateScheduledexecutorservice pool = Executors.newscheduledthreadpool (16);
... Slightly while(true){ //get the data from the queue and give it to the timer execution Try{workordermessage message=Messagequeue.getmessagefromnext (); LongExcuetime = Message.getupdatetime () +message.getcallbacktype (). Getintervaltime () * 1000; Longt = excuetime-System.currenttimemillis (); if(t/1000 < 5) {//the data to be executed within 5s is submitted to the dispatch thread poolSYSTEM.OUT.PRINTLN ("Messagehandlenext-meets timer execution condition" +jsonobject.tojsonstring (message)); Pool.schedule (NewCallable<boolean>() {@Override PublicBoolean Call ()throwsException {remotecallback (message); return true; }}, T, Timeunit.milliseconds); }Else{messagequeue.putmessagetonext (message); } } Catch(interruptedexception e) {System.out.println (e); } }
3.4 Retrofit2 is easy to use.
Specific to see the official website related documents to understand, use up or more convenient. http://square.github.io/retrofit/
Retrofit initialization:
ImportRetrofit2. Retrofit;Importretrofit2.converter.gson.GsonConverterFactory; Public classRetrofithelper {Private Static FinalString Http_url = "http://baidu.com/"; Private StaticRetrofit Retrofit; Public StaticRetrofit Instance () {if(Retrofit = =NULL) {Retrofit=NewRetrofit.builder (). BASEURL (Http_url). Addconverterfactory (gsonconverterfactory . Create ()). build (); } returnRetrofit; }}
If you need to modify the time-out period, the connection time and so on can be initialized, retrofit using okhttpclient
ImportOKHTTP3. okhttpclient;ImportRetrofit2. Retrofit;Importretrofit2.converter.gson.GsonConverterFactory;ImportJava.util.concurrent.TimeUnit; Public classRetrofithelper {Private Static FinalString Http_url = "http://baidu.com/"; Private StaticRetrofit Retrofit; Public StaticRetrofit Instance () {if(Retrofit = =NULL) {Retrofit=NewRetrofit.builder (). BASEURL (Http_url). Client (NewOkhttpclient.builder (). ConnectTimeout (, Timeunit.seconds)//Connection Time. ReadTimeout (Timeunit.seconds)//Read Time. WriteTimeout (Timeunit.seconds)//Write Time. Build ()). Addconverterfactory (Gsonconverterfactory.create ()) . build (); } returnRetrofit; }}
Retrofit using an interface call, first declare an interface;
Import Com.alibaba.fastjson.JSONObject; Import Com.woasis.callbackdemo.bean.WorkOrderMessage; Import Retrofit2. Call; Import Retrofit2.http.Body; Import Retrofit2.http.POST; Public Interface workordermessageinterface { @POST ("/api") call <JSONObject> Updatebatteryinfo (@Body workordermessage message);}
The interface and the instance object are ready, and then the call is made;
Private voidremotecallback (Workordermessage message) {//instance Interface ObjectWorkordermessageinterface workordermessageinterface = Retrofithelper.instance (). Create (Workordermessageinterface.class); //Calling interface MethodsCall<jsonobject> Objectcall =workordermessageinterface.updatebatteryinfo (message); System.out.println ("Remote Call Execution:" +NewDate ()); //Asynchronous Call ExecutionObjectcall.enqueue (NewCallback<jsonobject>() {@Override Public voidOnresponse (call<jsonobject> call, response<jsonobject>response) {System.out.println ("messagehandlenext**** Call succeeded" +Thread.CurrentThread (). GetId ()); Message.setsuccess (true); System.out.println ("Messagehandlenext-Callback succeeded" +jsonobject.tojsonstring (message)); } @Override Public voidOnFailure (call<jsonobject>Call , Throwable throwable) {System.out.println ("messagehandlenext++++ call failed" +Thread.CurrentThread (). GetId ()); //failed to put data into queue Try { //Initialize the callback policy LongCurrentTime =System.currenttimemillis (); Message.setupdatetime (currenttime); Message.setsuccess (false); Callbacktype Callbacktype=Message.getcallbacktype (); //Get Rank intLevel =Callbacktype.getlevel (Callbacktype); //number of fetches intCount =Callbacktype.getcount (Callbacktype); //If the level is already the highest, no callback if(CallbackType.HOUR_6.getLevel () = = Callbacktype.getlevel () && count = =Message.getcount ()) {System.out.println ("messagehandlenext-rank highest, no longer callback, offline Processing:" +jsonobject.tojsonstring (message)); }Else { //to see if Count is the largest, count the maximum to increase the level if(Message.getcount () <Callbacktype.getcount ()) {Message.setcount (Message.getcount ()+1); }Else{//if not small, increase the levelMessage.setcount (1); level+ = 1; Message.setcallbacktype (level) (Callbacktype.gettypebylevel); } messagequeue.putmessagetonext (message); } } Catch(interruptedexception e) {e.printstacktrace (); System.out.println ("Messagehandlenext-failed to put queue data"); } } }); }
3.5 Results achieved
4. Summary
The implementation of the time gradient to the corresponding other system interface, no longer cause its own business due to the exception of other systems and blocked. Ask the big boys to see if there is any unreasonable place, welcome to criticize.
Source: