2012-11-26 36 views
5

Ich habe eine Java-Anwendung, die Spring/Hibernate (auf Amazon Elastic Beanstalk ausgeführt) mit einer normalen Amazon RDS-Instanz verwendet. Um die Last zu verteilen, füge ich eine Read-Replica hinzu. Ich vertauschte die DB.url mit dem gelesenen Replikat und testete eine Methode, die sollte nur Daten lesen (die Methoden verwenden definitiv nicht UPDATE, INSERT oder DELETE). Die Anwendung gibt jedoch Fehler zurück.So konfigurieren Sie Spring/Hibernate mit MySQL Read-Replica

Meine Fragen: Warum schlägt die Anwendung fehl, wenn nur Daten gelesen werden? Wie kann ich Spring/Hibernate für die Arbeit mit einer Read-Replica konfigurieren?

Die Details:

Der Fehler Ich erhalte ist:

INFO: Internal error in method IEngageManager.getSimpleExamActivityLiveResults, ARGUMENTS=[ 
    Credentials { 
(m) password=0c2a765c057a31c51b68d0f6c75cef93, 
(m) email=w1jg 
    } 
] 
com.iengage.exceptions.IEException: Internal error in method IEngageManager.getSimpleExamActivityLiveResults, ARGUMENTS=[ 
    Credentials { 
    (m) password=0c2a765c057a31c51b68d0f6c75cef93, 
    (m) email=w1jg 
    } 
] 
    at com.iengage.exceptions.ExceptionWrapper.overridingInvoke(ExceptionWrapper.java:25) 
    at com.iengage.springobjects.SingletonMethodInterceptor.invoke(SingletonMethodInterceptor.java:18) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621) 
    at com.iengage.managers.IEngageManager$$EnhancerByCGLIB$$c8a2c385.getSimpleExamActivityLiveResults(<generated>) 
    at com.iengage.services.IEngageService.getSimpleExamActivityLiveResults(IEngageService.java:379) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:616) 
    at com.sun.xml.ws.api.server.InstanceResolver$1.invoke(InstanceResolver.java:246) 
    at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:146) 
    at com.sun.xml.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:257) 
    at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:93) 
    at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595) 
    at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554) 
    at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539) 
    at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436) 
    at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:243) 
    at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:444) 
    at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:244) 
    at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:135) 
    at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doGet(WSServletDelegate.java:129) 
    at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doPost(WSServletDelegate.java:160) 
    at com.sun.xml.ws.transport.http.servlet.WSSpringServlet.doPost(WSSpringServlet.java:52) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) 
    at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:680) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:679) 

Der Code, der die DB-Aufrufe:

public LecturerBO getLecturerByCode(Credentials credentials) { 
    return findSingleResultByCriteria(LecturerBO.class,Restrictions.eq("loginCode",credentials.getPassword())); 
} 

wo

protected <T> T findSingleResultByCriteria(Class<T> clazz, Criterion... criterion) { 
    Criteria crit = getSession().createCriteria(clazz); 
    for (Criterion c : criterion) { 
     crit.add(c); 
    } 
    return (T) crit.uniqueResult(); 
} 

Und zuletzt, die Hibernate-Konfiguration:

<bean id="generalManagerProxyTemplate" 
     class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" 
     abstract="true"> 
    <property name="transactionManager" ref="hibernateTransactionManager"/> 
    <property name="proxyTargetClass" value="true"/> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="*">PROPAGATION_REQUIRED</prop> 
     </props> 
    </property> 
    <property name="preInterceptors"> 
     <list> 
      <bean class="com.iengage.exceptions.ExceptionWrapper"/> 
      <bean class="com.iengage.utils.PerformanceLogger"/> 
     </list> 
    </property> 
</bean> 

<bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
</bean> 

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="dataSource" ref="pooledDataSource"/> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop> 
      <prop key="transaction.auto_close_session">true</prop> 
      <prop key="transaction.flush_before_completion">true</prop> 
      <prop key="show_sql">false</prop> 
      <prop key="hibernate.cache.use_query_cache">false</prop> 
      <prop key="hibernate.show_sql">false</prop> 
     </props> 
    </property> 
    <property name="annotatedClasses"> 
     <bean class="com.iengage.dao.EntityList"/> 
    </property> 
</bean> 

<bean id="pooledDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="${db.driverClassName}"/> 
    <property name="url" value="${db.url}"/> 
    <property name="username" value="${db.username}"/> 
    <property name="password" value="${db.password}"/> 
    <property name="defaultAutoCommit" value="false"/> 
    <property name="testWhileIdle" value="true"/> 
</bean> 

<bean id="abstractDAO" class="com.iengage.dao.GeneralDAO" abstract="true"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
    <property name="dataSource" ref="pooledDataSource"/> 
</bean> 

<bean id="dao" class="com.iengage.dao.IEngageDAO" parent="abstractDAO"/> 

Und zuletzt, als Plausibilitätsprüfung, ich mit der Lese-Replik habe eine Verbindung direkt und über ein einfaches Skript, die SELECT-Abfragen ausgeführt, die ich auf einem fremden Server gehostet . Alles funktioniert wie erwartet.

Auch in meiner Forschung vor dem Posten dieser Frage, konzentrierte sich die meisten Antworten auf die @Transactional Annotation, die wir nicht verwenden. Trauriger Panda.

Danke für jede Hilfe.

+0

Sie die Ursache der ausgelösten Ausnahme weglassen? (z. B. indem eine neue IEx-Ausnahme ohne das übliche Argument geworfen wird?) – Vincent

Antwort

1

Um diese Art von Zugriff (Nur Read-Replica) bereitzustellen, müssen Sie diese Eigenschaft implementieren.

 <property name="transactionAttributes"> 
      <props> 
       <prop key="get*">PROPAGATION_REQUIRED,readOnly 
       </prop> 
       <prop key="find*">PROPAGATION_REQUIRED,readOnly 
       </prop> 
       <prop key="load*">PROPAGATION_REQUIRED,readOnly 
       </prop> 
       <prop key="store*">PROPAGATION_REQUIRED</prop> 
       <prop key="add*">PROPAGATION_REQUIRED</prop> 
      </props> 
     </property> 

Hier verwende ich diese zwei zu speichern und in DB hinzufügen. Sie müssen dies entfernen, wenn Sie nicht benötigen.

 <prop key="store*">PROPAGATION_REQUIRED</prop> 
     <prop key="add*">PROPAGATION_REQUIRED</prop> 
Verwandte Themen