- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在分别使用 Dropwizard 框架和 dropwizard-hibernate JPA/Hibernate(使用 PostgreSQL 数据库)来实现 REST API Web 服务。我在资源中有一个方法,我用 @UnitOfWork
注释为整个请求获取一个事务。资源方法调用我的一个方法 DAO s 延伸 AbstractDAO<MyEntity>
并用于与数据库交流我的实体(类型 MyEntity
)的检索或修改。
这DAO方法执行以下操作:首先它选择一个实体实例,因此从数据库中选择一行。之后,检查实体实例并根据其属性更改其某些属性。在这种情况下,应该更新数据库中的行。我没有在任何地方指定关于缓存、锁定或事务的任何其他内容,因此我假设默认设置是某种由 Hibernate 强制执行的乐观锁定机制。因此(我认为),当从当前线程的数据库中选择实体实例后删除另一个线程中的实体实例时, StaleStateException
尝试提交事务时抛出,因为应该更新的实体实例已被其他线程删除。
使用 @UnitOfWork
时注释,我的理解是我无法在 DAO 中捕获此异常方法也不在资源方法中。我现在可以实现 ExceptionMapper<StaleStateException>
为 Jersey 提供带有 Retry-After
header 的 HTTP 503 响应或类似的东西告诉客户重试其请求。但我宁愿先在服务器上重试请求/事务(由于 @UnitOfWork
注释,这里基本上是相同的)。
是否有使用 Dropwizard 时服务器端事务重试机制的示例实现?就像重试可配置的次数(例如 3 次)然后因异常/HTTP 503 响应而失败。你将如何实现?我首先想到的是另一个注释,如 @Retry(exception = StaleStateException.class, count = 3)
我可以将其添加到我的资源中。对此有什么建议吗?或者考虑到不同的锁定/事务相关的事情,我的问题是否有替代解决方案?
最佳答案
另一种方法是使用注入(inject)框架 - 在我的例子中是 guice - 并为此使用方法拦截器。这是一个更通用的解决方案。
DW通过https://github.com/xvik/dropwizard-guicey非常顺利的和guice集成了
我有一个可以重试任何异常的通用实现。它像您一样在注释上工作,如下所示:
@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;
}
}
有关此方法的一些注意事项。
重试的方法必须设计成可以多次调用而不会改变任何结果(例如,如果该方法以增量的形式存储临时结果,那么执行两次可能会增加两次)
数据库异常一般不会保存重试。他们必须打开一个新连接(特别是在重试死锁时,这是我的情况)
除此之外,这个基本实现只是简单地捕获任何内容,然后将重试计数和检测委托(delegate)给实现类。比如我具体的死锁重试拦截器:
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());
}
}
最后,我可以通过以下方式将其绑定(bind)到 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,已经捕获了它们自己的异常。
另请注意方法(get)在从我的数据源池中调用两次时如何检索新连接,以及如何在其中不进行任何修改(因此:可以安全重试)
希望对您有所帮助。
您可以通过实现 ApplicationListeners 或 RequestFilters 或类似的方式来做类似的事情,但我认为这是一种更通用的方法,可以在任何受 guice 限制的方法上重试任何类型的失败。
另请注意,guice 只能在构造类时拦截方法(注入(inject)带注释的构造函数等)
希望对你有帮助,
阿图尔
关于java - 在 Dropwizard/JPA/Hibernate 中自动重试事务/请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39949017/
我想做的是,如果鼠标位于“下一个”按钮上,它会以慢速向右滚动,如果鼠标没有位于“下一个”按钮上,它会停止滚动? 这是我的尝试http://jsfiddle.net/mdanz/nCCRy/14/ $(
StyleCop 是一个很棒的视觉工作室小插件。但它不会向您显示实时提示或提供任何自动修复。 随之而来的是 reSharper 和 StyleCop for reSharper,这是理想的解决方案,但
我为我的MatchQuery使用了模糊性选项,但是我想将模糊性值设置为auto。有什么办法吗? 另外,对于完成建议程序,您可以将其设置为支持unicode,对于我的MatchQuery,有什么方法可以
我想从表中获取一行[字符串名称,字符串密码,int 某些内容]并将其映射到一个 User 对象,该对象具有 3 个属性,如上面的 getter 和 setter有什么方法可以自动完成吗?我考虑过反射,
我有一个像这样的方法:void m1(string str) 并且有一个像这样的类: public class MyClass { public bool b1 { set; get; }
我正在尝试使用 $rootScope 从一个 Controller 向另一个 Controller $broadcast 一些数据。 如果我使用像 ng-click 这样的触发器来运行将广播的功能,它
我考虑了很多关于是要使用完全自动化的缓存还是手动缓存。 我们的自动方法是一种解决方案,它可以挖掘数据库、查询和格式化每个潜在和 future 的数据请求,并将其保存到适当的缓存存储(内存缓存或基于磁盘
我的 CSS 必须使用过渡来更改,直到现在我都使用 div:hover 来实现。 当您单击另一个 div 时需要激活过渡,而不是当您将鼠标悬停在必须移动/更改的 div 上时。 我该怎么做? 谢谢 永
在我的应用程序中,我需要一些动画,但如果它已经设置了动画,则不需要持续时间。但我的问题是它会自动添加持续时间。 在这里你可以看到 2 个函数,第二个没有持续时间但它确实有持续时间(可能从 1 秒开始)
两年前,我需要制作一个工具,通过 POST 自动将 txt/csv 文件上传到我的 Web 服务器,然后使用 cronjob 通过 PHP 对其进行解析。 这有两次在每天午夜自动发生。尽管这行得通,但
请阅读下面程序中的评论: #include void test(char c[]) { c=c+2; //why does this work ? c--; printf("%
也许是个幼稚的问题,但是...... 确认或拒绝: 自动和静态存储持续时间的对象/变量的内存的存在是在编译时确定的,程序运行时失败的可能性绝对为零,因为没有足够的内存用于自动对象。 自然地,当自动对象
有没有什么方法可以自动获得类中属性更改的通知,而不必在每个 setter 中都编写 OnPropertyChanged? (我有数百个属性,我想知道它们是否已更改)。 安东建议 dynamic pro
我们在使用 Azure DevOps 的项目中采用了 gitflow 流程。我有以下场景: 当功能分支合并到 Develop 时,我想在完成拉取请求的同时执行压缩合并策略 当 Release 分支定期
我的网站上有一个评论部分,我将 html 编码的评论保存在我的数据库中。所以我添加了这条评论- "testing" `quotes` \and backslashes\ and html 并将其保存在
是否存在“ checkin 前 TFS 自动 checkout ”这样的功能,以便在我说“ checkin ”之前我不会 checkout 任何文件,例如以防我只是临时更改文件 - 这一直发生。 换句
我有一个运行在 Linux/Apache/Tomcat 堆栈上的网站,它需要每隔几个月自动脱机以进行服务器维护,这将持续任意时间。有哪些选项可以让 Apache 建立和取消“服务器维护”页面? 我需要
我经常在工作中创建文档,在公司内部,由于我们使用的首字母缩写词和缩写词的数量,我们几乎拥有自己的语言。因此,我厌倦了在发布文档之前手动创建首字母缩写词和缩写表,并且快速的谷歌搜索发现了一个可以有效地为
我希望在用户或宏将计算模式从自动更改为手动或手动更改为自动时运行代码。是否有为此触发的事件? (属性是 Application.Calculation 在 Excel 互操作中。) 使用 Excel
这个问题在这里已经有了答案: Repeat command automatically in Linux (13 个回答) 6年前关闭。 我想创建一个脚本来获取另一个文件夹中的所有文件夹名称。并为这些
我是一名优秀的程序员,十分优秀!