2012-11-26 51 views
5

Tôi có một ứng dụng Java sử dụng Spring/Hibernate (chạy trên Amazon Elastic Beanstalk) với một cá thể Amazon RDS bình thường. Để phân phối tải, tôi đang thêm một bản sao được đọc. Tôi đổi DB.url thành bản sao đã đọc và thử nghiệm một phương thức mà nên chỉ đọc dữ liệu (các phương pháp chắc chắn không sử dụng UPDATE, INSERT hoặc DELETE). Tuy nhiên, ứng dụng đang trả về lỗi.Cách cấu hình Spring/Hibernate với MySQL Read-Replica

Câu hỏi của tôi: Tại sao ứng dụng không thành công khi chỉ đọc dữ liệu? Làm thế nào tôi có thể cấu hình Spring/Hibernate để làm việc với một bản sao đọc?

Các chi tiết:

Các lỗi tôi nhận được là:

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) 

Mã mà các cuộc gọi DB:

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

nơi

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(); 
} 

Và cuối cùng, cấu hình Hibernate:

<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"/> 

Và cuối cùng, như một kiểm tra sanity, tôi đã kết nối với các đọc bản sao trực tiếp và thông qua một kịch bản đơn giản mà thực hiện truy vấn SELECT mà tôi lưu trữ trên một máy chủ của bên thứ ba . Tất cả làm việc như mong đợi.

Ngoài ra, trong nghiên cứu của tôi trước khi đăng câu hỏi này, hầu hết các câu trả lời đều tập trung vào chú thích @Transactional mà chúng tôi không sử dụng. Chú gấu trúc buồn.

Cảm ơn bạn đã được trợ giúp.

+0

Bạn có bỏ qua nguyên nhân của ngoại lệ bị ném không? (ví dụ: bằng cách ném một IEException mới mà không có đối số ném thông thường?) – Vincent

Trả lời

1

Để cung cấp loại quyền truy cập đó (Chỉ đọc bản sao), bạn phải triển khai thuộc tính này.

 <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> 

ở đây, tôi sử dụng hai tài khoản này để cho phép lưu trữ và thêm vào DB. bạn phải loại bỏ điều này nếu bạn không yêu cầu.

 <prop key="store*">PROPAGATION_REQUIRED</prop> 
     <prop key="add*">PROPAGATION_REQUIRED</prop> 
Các vấn đề liên quan