一:介绍
指数退避算法的定义和使用可以在网上搜搜。提供一下wiki的介绍部分定义:an algorithm that uses feedback to multiplicatively decrease the rate of some process, in order to gradually find an acceptable rate.
这边我介绍的是,指数退避的算法其实不只可以在网络包的重传机制中实现网络包的合理的重传机制。而且可以封装好相应的接口,从而利用这样的接口产生任何一种你需要的时间,或者你需要的重传的计数等。这些的应用只是利用了指数退避算法的本质,即根据要求产生需要的范围内的一个随机数,供需要的Action调用。
二:C代码的实现封装的接口
网上有很多只是介绍了指数退避算法的定义,和一份blog的伪代码和Javacode的实现。然后就是更种Copy了。这里上了部分笔记和C封装的代码,这样的接口调用,根据接口里的注释,可以做一定的修改,然后可以产生一个你需要的指数的随机数,供你程序的动态的使用。
/*the pesudocode Do some asynchronous operation:retries = 0Do wait for (2^retries * 100) millisecondsstatus = Get the result of the asynchronous operationIf satatus = Success retry = FalseElse If status = Not_Ready retry = trueElse if satus = Throttled retry = true Elsesom other error occurrred, so stop calling the API retry = false End ifretries = retries + 1While(retry AND (reties < MAX_RETRIES))
*/#include <math.h>/* Define the status of the retry
** The flag of the result you can define as you need
**
***/
typedef ResStaus
{eRES_None,eRES_Success,eRES_OtherError
}st_ResStatus;/* The MinTime Your action need to be active */
#define MAX_ACTIVE_TIME 100
#define MAX_ACTIVE_RETRIES 16/* The times of exponential backoff */
double getWaitTimeExp(int RetryCount, long BaseTimes)
{double TempWait = 0;TempWait = (pow(2, RetryCount) * BaseTimes);return TempWait;
}/* The operations */
int OperationWaitForResult()
{long Token = 0;int Retries = 0;bool RetryFlag = false;st_ResStatus Result = eRES_None;/* The BaseTime is the one times your action need to active */double BaseTimes = 0;double WaitTime = 0;do{/* Get the waittime times first */WaitTime = (MIN_ACTIVE_TIME > getWaitTimeExp(RetryCount, BaseTimes) ? getWaitTimeExp(RetryCount, BaseTimes) : MAX_ACTIVE_TIME);printf("WaitTime :%ld\n", WaitTime);/* The thread hangup waittime */sleep(WaitTime);/* Your action functions return the status of the executed the functions */ Result = YourActionFunc();switch(Result){/* Do your actions process */case eRES_Success:RetryFlag = false;break;/* Do your cation the error process */case eRES_OtherError:RetryFlag = true;break;default:/* The stop flag of your action need to process */break;}}while(RetryFlag && ((Retries++) < (MAX_ACTIVE_RETRIES))/* Do your later process */
}
其实这里面的精华部分,就是取得指数规避的动态的指数参数,并且这个返回的Times, 你可以用在定时器,或者你需要重复调用的Action的限制的时间,次数等。
三:实例的介绍
这里具体的代码就不上了,不过提供一个思路。比如你想定时的去做一action,但是随着不同的返回值(程序接口运行的状态)你想动态的合理的规划定时器的调用时间,你就可以按照上面的指数退避的接口,产生一个合理的指数Times,然后设定一个最大,最小值,然后将此接口获得值提供给定时器的超时时间。这样可以合理的利用定时器的资源,从而使你的代码达到一种合理的利用资源的效果。其他的比如你重新注册等。这里的时间或许你可以在各个方面去实现,这样你不只在使用指数,其他的一些实用都可以应用。
四:Given a method to gerenated a uniforms times
这里直接上了参照wiki的方法,代码和对应的算法公式。只需将上面的codes funcation 进行一些改变就可以了:
/*Give the uniform distribution of backoff times The expected backoff time is the mean of the possibilities.That is ,after c collisions,the number of backoff slots is in [0, 1, ..., N], where N = 2^c -1 and the expected backoff time (in lsots) is (1)/(N + 1)(Sigma(1 -- N))for example:when c = 3;N = 2^C - 1;N = 7;and the calculate the mean of the back off time possibilities E(c) = (1)/(N + 1)(Sigma(1 -- N))= N / 2 = (2^C - 1) / 2;which is, for the example, E(3) = 3.5 slots
*/
/* The times of exponential backoff */
double getWaitTimeExp(int RetryCount, long BaseTimes)
{double TempWait = 0;TempWait = (pow(2, RetryCount) * BaseTimes);/* Give the uniform distribution of backoff times */TempWait = (TempWait - 1) / 2;return TempWait;
}
这样每次产生的time,就是一个唯一的Uniform time .
以上的仅供参考,欢迎指教