Home > ejb > MySQL Master/Slave in ambiente JEE

MySQL Master/Slave in ambiente JEE

Con un database MySQL di tipo Master/Slave dobbiamo effettuare le operazioni di scrittura sul Master server e le operazioni di sola lettura, in load balancing, sui Slave server.

Con il MySQL Connector/J possiamo usare questo driver “com.mysql.jdbc.ReplicationDriver”, che in automatico invia le query al Master o agli Slave basandosi sull’attributo read-only della connessione (Connection.getReadOnly()).

Per prima cosa configuriamo il pool di connessioni sul nostro JEE server preferito:

 Url: jdbc:mysql:replication://master,slave1,slave2,slave3/test

Il driver invia le query agli Slave solo se l’auto-commit è settato a false e la connessione a read-only, altrimenti usa il Master.

Se nelle transazioni EJB, al contrario di Spring, si sarebbe potuto impostare la proprietà read-only, probabilmente i JPA provider avrebbero impostato la stessa proprietà sulla connessione. Così, sempre ipotizzando, sarebbe bastato: @TransactionAttribute(TransactionAttributeType.XXXXXX,readOnly=true)

Purtroppo al momento non è possibile, così dobbiamo creare il nostro interceptor e la nostra annotation @ReadOnly.

import javax.interceptor.Interceptor;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@ReadOnly
@Interceptor
public class JpaReadOnlyInterceptor implements Serializable {

  private EntityManager entityManager;

  @PersistenceContext
  protected void setEntityManagerInjection(EntityManager entityManager) {
    this.entityManager = entityManager;
  }

  @AroundInvoke
  public Object setReadOnlyOperation(InvocationContext context) throws Exception {

    Connection connection = entityManager.unwrap(java.sql.Connection.class);

    // solo nel caso in cui l'autoCommit sia abilitato
    //boolean autoCommit = connection.getAutoCommit(); 
    boolean readOnly = connection.isReadOnly();

    try {
      connection.setReadOnly(true);
      // solo nel caso in cui l'autoCommit sia abilitato
      //connection.setAutoCommit(false);

      return context.proceed();
    } finally {
      // restore state
      // solo nel caso in cui l'autoCommit sia abilitato
      //connection.setAutoCommit(autoCommit);
      connection.setReadOnly(readOnly);
    }
  }
}
@Inherited
@InterceptorBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnly {}

Se il vostro JEE server preferito utilizza una versione aggiornata di WELD, dovreste riuscire a utilizzare i nuovi interceptor CDI senza problemi:

@ReadOnly
public DataResult readData(String id) {
...

Altrimenti dovrete utilizzare i “legacy” Ejb interceptor:

@Interceptors(JpaReadOnlyInterceptor.class)
public DataResult readData(String id) {
...

References:

  1. Non c'è ancora nessun commento.
  1. No trackbacks yet.

Lascia un commento

Effettua il login con uno di questi metodi per inviare il tuo commento:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger cliccano Mi Piace per questo: