1
0
mirror of synced 2025-12-22 18:08:12 +08:00

fix: WxMpServiceImpl中用ThreadLocal记录重试次数,这个是有问题的,因为在多线程(线程池)环境下ThreadLocal是不会被清0的

This commit is contained in:
Daniel Qian
2015-01-21 14:08:34 +08:00
parent 1635024146
commit e53c921d17
8 changed files with 280 additions and 72 deletions

View File

@@ -353,4 +353,22 @@ public interface WxCpService {
* @param wxConfigProvider
*/
public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider);
/**
* <pre>
* 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试
* 默认1000ms
* </pre>
* @param retrySleepMillis
*/
void setRetrySleepMillis(int retrySleepMillis);
/**
* <pre>
* 设置当微信系统响应系统繁忙时,最大重试次数
* 默认5次
* </pre>
* @param maxRetryTimes
*/
void setMaxRetryTimes(int maxRetryTimes);
}

View File

@@ -52,12 +52,14 @@ public class WxCpServiceImpl implements WxCpService {
protected WxCpConfigStorage wxCpConfigStorage;
protected final ThreadLocal<Integer> retryTimes = new ThreadLocal<Integer>();
protected CloseableHttpClient httpClient;
protected HttpHost httpProxy;
private int retrySleepMillis = 1000;
private int maxRetryTimes = 5;
public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) {
try {
return SHA1.gen(wxCpConfigStorage.getToken(), timestamp, nonce, data).equals(msgSignature);
@@ -366,6 +368,33 @@ public class WxCpServiceImpl implements WxCpService {
* @throws WxErrorException
*/
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
int retryTimes = 0;
do {
try {
return executeInternal(executor, uri, data);
} catch (WxErrorException e) {
WxError error = e.getError();
/**
* -1 系统繁忙, 1000ms后重试
*/
if (error.getErrorCode() == -1) {
int sleepMillis = retrySleepMillis * (1 << retryTimes);
try {
System.out.println("微信系统繁忙," + sleepMillis + "ms后重试(第" + (retryTimes + 1) + "次)");
Thread.sleep(sleepMillis);
} catch (InterruptedException e1) {
throw new RuntimeException(e1);
}
} else {
throw e;
}
}
} while(++retryTimes < maxRetryTimes);
throw new RuntimeException("微信服务端异常,超出重试次数");
}
protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
String accessToken = getAccessToken(false);
String uriWithAccessToken = uri;
@@ -381,31 +410,10 @@ public class WxCpServiceImpl implements WxCpService {
* 42001 access_token超时
*/
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) {
// 强制设置wxCpConfigStorage它的access token过期了这样在下一次请求里就会刷新access token
// 强制设置wxMpConfigStorage它的access token过期了这样在下一次请求里就会刷新access token
wxCpConfigStorage.expireAccessToken();
return execute(executor, uri, data);
}
/**
* -1 系统繁忙, 1000ms后重试
*/
if (error.getErrorCode() == -1) {
if (retryTimes.get() == null) {
retryTimes.set(0);
}
if (retryTimes.get() > 4) {
retryTimes.set(0);
throw new RuntimeException("微信服务端异常,超出重试次数");
}
int sleepMillis = 1000 * (1 << retryTimes.get());
try {
System.out.println("微信系统繁忙," + sleepMillis + "ms后重试");
Thread.sleep(sleepMillis);
retryTimes.set(retryTimes.get() + 1);
return execute(executor, uri, data);
} catch (InterruptedException e1) {
throw new RuntimeException(e1);
}
}
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
@@ -416,7 +424,6 @@ public class WxCpServiceImpl implements WxCpService {
throw new RuntimeException(e);
}
}
protected CloseableHttpClient getHttpclient() {
return httpClient;
}
@@ -451,4 +458,15 @@ public class WxCpServiceImpl implements WxCpService {
}
}
@Override
public void setRetrySleepMillis(int retrySleepMillis) {
this.retrySleepMillis = retrySleepMillis;
}
@Override
public void setMaxRetryTimes(int maxRetryTimes) {
this.maxRetryTimes = maxRetryTimes;
}
}