task idempotent

     Recently, I am working on a business flow system, which is deployed in a distributed environment and uses a distributed scheduling system. First, the task can be restarted on an available machine when the system is down and the system is released. Second, the task needs to be retried. , after the interface execution fails, you need to set the interval time of the scheduling system to restart the start task on the business cluster (the threads and processes of the business may change), because the business interfaces in the business flow are all influential or not idempotent, such as closing the application , this command cannot be executed repeatedly.

     This requires that each retry/restart unit is idempotent. My idea is to be able to record the execution process of each external interface. If a certain interface has already executed a certain step, skip this stage to ensure that the command will not be issued repeatedly. .

     I divide each business interface into 3 stages, the command is issued (successfully issued, failed to be issued), the command is executed successfully (executed successfully, executed successfully), the command result is successfully stored (successful in storage, failed in storage), the basic Model

public class IdempotentFlag {

	private Boolean commandSendDown = false;

	// 2 Unknown (for asynchronous tasks, the command is issued successfully, and continuous detection is required in this state) 0 Failure 1 Success
	private int commandSuccess = 2;

	private Boolean commandResultInDB = false;
       // Additional information about the task, such as the TaskID returned by the asynchronous task
	private String attachInfo;
}

     Each idempotent object has a key, which is unique in the entire process. For the storage of idempotent objects, I use the Enhance dynamic proxy, so that the proxy object can be obtained: if the database exists, the data initialization object is retrieved from the database. The database does not exist to construct a default object.

public class IdempotentFlagFroxyFactory implements MethodInterceptor {


	private String contextKey;

	public IdempotentFlagFroxyFactory(String contextKey) {
		this.contextKey = contextKey;
	}

	public IdempotentFlag getProxy() {

		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(IdempotentFlag.class);
		enhancer.setCallback(this);

		IdempotentFlag clearObject = (IdempotentFlag) enhancer.create();
                String IdempotentFlagString =   getFromDB(contextKey);
		if (StringUtils.isNotBlank(IdempotentFlagString)) {
			IdempotentFlag dbObject = IdempotentFlag.toObject(IdempotentFlagString);
			try {
				BeanUtils.copyProperties (clearObject, dbObject);
			} catch (Exception e) {
				e.printStackTrace ();
			}
		}
		return clearObject;
	}

	@Override
	public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		Object result = proxy.invokeSuper(target, args);
		if (method.getName().contains("set")) {
			IdempotentFlag flag = (IdempotentFlag) target;
			context.putPersistentString(contextKey, flag.toString());
		}
		return result;
	}



}

         A state machine can be created in the save phase around the external interface to ensure that the task is idempotent, will not be repeatedly issued, and can be retried after failure.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326765601&siteId=291194637