简体   繁体   English

如何在具有多个服务器的同一数据库上使用骆驼 JPA 组件?

[英]How to use camel JPA component on the same database with multiple servers?

I am currently setting up my camel project and I can't make my JPA poller to work on several concurrent servers.我目前正在设置我的骆驼项目,但我无法让我的 JPA 轮询器在多个并发服务器上工作。

Here is the my camel route :这是我的骆驼路线:

public class TicketPoller extends RouteBuilder {

    /** The uri. */
    private final String uri = "jpa://Ticket?consumeDelete=false&consumeLockEntity=true&consumer.SkipLockedEntity=true&consumer.query=select t from Ticket t where t.state=1";

    @Override
    public void configure() {
        from(uri).to("log:input");

    }
}

I use @Consumed annotation to change the ticket state when polled directly in my Hibernate entity :在我的 Hibernate 实体中直接轮询时,我使用 @Consumed 注释来更改票证状态:

@Entity
@Table(name = "TICKET", schema = "TEIKITEL")
public class Ticket implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "TICKET_ID")
    private String ticketId;

    @Column(name = "STATE")
    private int state;

    ...

    @Consumed
    public void changeTicketState() {
        this.state = 2;
    }

    @Override
    public String toString() {
        return "Ticket@ticketId=" + this.ticketId;
    }
}

It works fine when I launch it on one single Tomcat server (Tomcat 8) from Eclipse.当我从 Eclipse 的一台 Tomcat 服务器 (Tomcat 8) 上启动它时,它工作正常。

But when I launch 2 servers polling on the same database I have these errors when I insert some lines in my TICKET table :但是当我在同一个数据库上启动 2 个服务器轮询时,当我在我的 TICKET 表中插入一些行时出现这些错误:

On my first server I can see this :在我的第一台服务器上,我可以看到:

Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,796 INFO  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] input(180) - Exchange[ExchangePattern: InOnly, BodyType: com.teikitel.model.entity.Ticket, Body: Ticket@ticketId=TICKET1]
Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,812 INFO  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] input(180) - Exchange[ExchangePattern: InOnly, BodyType: com.teikitel.model.entity.Ticket, Body: Ticket@ticketId=TICKET2]

On my second server :在我的第二台服务器上:

Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,859 WARN  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(144) - SQL Error: 54, SQLState: 61000
2016-04-05 15:04:56,859 ERROR [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(146) - ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,874 WARN  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(144) - SQL Error: 54, SQLState: 61000
2016-04-05 15:04:56,874 ERROR [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(146) - ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

Did someone run into the same problem ?有人遇到过同样的问题吗?

Loic洛伊克

There is no errors ! 没有错误!

These error logs come from Hibernate, not from Camel. 这些错误日志来自Hibernate,而不是来自Camel。

Camel does its Job and skip the element locked in database (your log action triggered is executed only once on one instance) but it uses Hibernate to perform its non-blocking select request. Camel执行其Job并跳过锁定在数据库中的元素(触发的日志操作仅在一个实例上执行一次)但它使用Hibernate执行其非阻塞选择请求。 Hibernate throw an exception which is successfully ignored by Camel BUT print the error in your log output. Hibernate抛出异常,Camel BUT成功忽略该异常,在日志输出中打印错误。 This is what you see. 这就是你所看到的。

I gess the solution to your problem is to set the Hibernate log to a higher level. 我解决你的问题的方法是将Hibernate日志设置到更高的级别。

With problems like theses (synchro) do not hesitate to use the delay method in camel to understand better : 对于诸如论文(同步)之类的问题,请不要犹豫,使用骆驼中的延迟方法来更好地理解:

public class TicketPoller extends RouteBuilder {

/** The uri. */
private final String uri = "jpa://Ticket?consumeDelete=false&consumeLockEntity=true&consumer.SkipLockedEntity=true&consumer.query=select t from Ticket t where t.state=1";

@Override
public void configure() {
    from(uri).delay(10000).to("log:input"); //wait 10sec 

}

} }

it seems like the entity is already locked for the other thread running in the first server. 看起来实体已经锁定了第一台服务器上运行的其他线程。 You are locking the cell with consumeLockEntity=true and you are not waiting for the release consumer.SkipLockedEntity=true so the connection in the second server is close after trying without waiting. 您正在使用consumeLockEntity = true锁定单元格,并且您没有等待发布使用消费者 .SkipLockedEntity = true因此在尝试之后第二个服务器中的连接关闭而不等待。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM