대체 접근법은 내 경우에는 guice 인 주입 프레임 워크를 사용하고 이에 대한 메소드 인터셉터를 사용하는 것입니다. 이것은보다 일반적인 솔루션입니다. guice와
DW의 integreates 매우 원활 https://github.com/xvik/dropwizard-guicey
을 통해 나는 어떤 예외를 재 시도 할 수있는 일반적인 구현을 가지고있다. 다음은, 주석에, 당신 같이 작동합니다
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {
}
인터셉터는 다음 (문서 도구)을 수행합니다
/**
* Abstract interceptor to catch exceptions and retry the method automatically.
* Things to note:
*
* 1. Method must be idempotent (you can invoke it x times without alterint the result)
* 2. Method MUST re-open a connection to the DB if that is what is retried. Connections are in an undefined state after a rollback/deadlock.
* You can try and reuse them, however the result will likely not be what you expected
* 3. Implement the retry logic inteligently. You may need to unpack the exception to get to the original.
*
* @author artur
*
*/
public abstract class RetryInterceptor implements MethodInterceptor {
private static final Logger log = Logger.getLogger(RetryInterceptor.class);
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if(invocation.getMethod().isAnnotationPresent(Retry.class)) {
int retryCount = 0;
boolean retry = true;
while(retry && retryCount < maxRetries()) {
try {
return invocation.proceed();
} catch(Exception e) {
log.warn("Exception occured while trying to executed method", e);
if(!retry(e)) {
retry = false;
} {
retryCount++;
}
}
}
}
throw new IllegalStateException("All retries if invocation failed");
}
protected boolean retry(Exception e) {
return false;
}
protected int maxRetries() {
return 0;
}
}
몇 가지이 방법에 대한주의.
기타 새로운 연결을 열어야합니다. 예를 들어, 내 특정 교착 상태 재시도 인터셉터 :
public class DeadlockRetryInterceptor extends RetryInterceptor {
private static final Logger log = Logger.getLogger(MsRetryInterceptor.class);
@Override
protected int maxRetries() {
return 6;
}
@Override
protected boolean retry(Exception e) {
SQLException ex = unpack(e);
if(ex == null) {
return false;
}
int errorCode = ex.getErrorCode();
log.info("Found exception: " + ex.getClass().getSimpleName() + " With error code: " + errorCode, ex);
return errorCode == 1205;
}
private SQLException unpack(final Throwable t) {
if(t == null) {
return null;
}
if(t instanceof SQLException) {
return (SQLException) t;
}
return unpack(t.getCause());
}
}
그리고 마지막으로, 내가 수행하여 guice이 바인딩 할 수 있습니다 :
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Retry.class), new MsRetryInterceptor());
모든 클래스를 확인
및 재시 주석 어떤 방법을. 재 시도에 대한
예 방법은 다음과 같습니다
는
@Override
@Retry
public List<MyObject> getSomething(int count, String property) {
try(Connection con = datasource.getConnection();
Context c = metrics.timer(TIMER_NAME).time())
{
// do some work
// return some stuff
} catch (SQLException e) {
// catches exception and throws it out
throw new RuntimeException("Some more specific thing",e);
}
}
내가 압축 풀기를 필요로하는 이유는 오래된 기존의 경우는,이 DAO의 IMPL처럼, 이미 자신의 예외를 잡을 것입니다.
메소드 (A GET가) 내 데이터 소스 풀에서 두 번 호출 새 연결을 검색하는 방법도
주, 별도의 수정 작업이 그 안에 이루어지지하는 방법 (따라서 : 안전 재시도)
나는이 도움이되기를 바랍니다.
ApplicationListeners 또는 RequestFilters 또는 유사한 구현하여 비슷한 일을 할 수 있지만이 guice 바인딩 된 모든 메서드에 대한 모든 종류의 오류를 다시 시도 할 수있는보다 일반적인 방법이라고 생각합니다. 또한
이 클래스를 구성하는 경우에만 방법 인터셉트 (주석 생성자 등을 주입) 할 수 guice에 유의하는 데 도움이
희망,
아르투르
내가 guice 및 인터셉터와 같은 일을하고 있어요 . 저지를 통해 동일을 적용하는 것을 막을 수있는 방법은 없습니다. 그러나 IMO 저지는 요청을 해할 수 있는지 확인해야하는 문제가 있습니다 (예 : 필터를 통해 수행 한 경우).guice method 인터셉터를 사용하면 예외를 잡아 내고 동일한 메소드를 다시 호출 할 수 있습니다. – pandaadb
방금 나는이 PR을 발견했다 : https://github.com/dropwizard/dropwizard/pull/1361 이것으로 나는 DAO의 일을하는 비공개 적 방법 ('@ UnitOfWork'으로 주석 됨)을 만들 수 있었다. 메서드는'StaleStateException'을 발생시킵니다. 그런 다음 첫 번째 방법을 사용하고 재 시도 메커니즘을 구현하는 또 다른 방법을 작성했습니다. 그래서 기본적으로 한 것은 자원 메소드에서 다른 메소드로 세션 라이프 사이클을 이동 시켜서 재 시도 메커니즘을 구축 할 수 있도록하는 것입니다. 아무도 더 나은 접근법을 제시 할 수없는 경우 곧 답변으로 추가하겠습니다. – mxscho