Spring 의 AbstractRoutingDataSource와 Mybatis의 Mapper를 이용하여 코딩을 했다는 내용의 글을 올렸다.
http://knight76.tistory.com/entry/mysql-%EC%97%90%EC%84%9C-%EB%8F%99%EC%9D%BC%ED%95%9C-table-schema%EB%A5%BC-%EA%B0%80%EC%A7%84-Multi-DB-%EB%A5%BC-java%EB%A1%9C-%EC%A0%91%EA%B7%BC%ED%95%98%EA%B8%B0
Mybatis의 Mapper 클래스와 XML를 이용한 것은 기존의 Mybatis의 XML을 쓰기 편한 장점이 있었다.
대충 관련코드를 공유..
public class DynamicRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicContextHolder.getDataSourceName(); } } |
mybatis의 SqlSessionFactoryBean를 상속받아 SqlSessionFactory를 생성하게 하는 Bean.
public class DynamicSqlSessionFactoryBean extends SqlSessionFactoryBean { private DataSource dataSource; private Resource configLocation; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public void setConfigLocation(Resource configLocation) { this.configLocation = configLocation; } public SqlSessionFactory buildSqlSessionFactory() { super.setConfigLocation(configLocation); super.setDataSource(dataSource); SqlSessionFactory factory = null; try { factory = super.buildSqlSessionFactory(); } catch (IOException e) { e.printStackTrace(); } return factory; } public void afterPropertiesSet() throws Exception { } } |
@Aspect @Component public class ExecutionAspect implements InitializingBean { public Object distribute(ProceedingJoinPoint joinPoint) throws Throwable { … 중략.. SqlSessionFactory s = createSqlSessionFactory(dataSourceNumber); SqlSession sqlSession = s.openSession(); DynamicContextHolder.setSqlSession(sqlSession); Object returnValue = joinPoint.proceed(); DynamicContextHolder.clear(); return returnValue; } |
createSqlSessionFactory () 메소드가 DynamicSqlSessionFactoryBean 의 buildSqlSessionFactory를 매번 생성하도록 하였다.
처음에는 괜찮아보였지만. 성능상 큰 이슈가 발생했다.
mybatis의 mapper xml를 사용하기 위해서 매번 mybatis의 SqlSessionFactory생성하는 코드를 넣을 때 유의해야 한다. 성능이 떨어질 수 밖에 없다.
(또한, AbstractRoutingDataSource 사용 자체가 매번 DB connection을 DBPool로부터 fetch 해서 사용하고 close 하는 것도 성능 이슈이긴 했다. )
성능이 잘 안 나와서 덤프를 떠보니.. Blocked 된 쓰레드를 많이 발견했다.
XML을 매번 읽어서 SqlSessionFactory를 만드는 작업은 xerces lock 에 의해서 성능을 떨어뜨리도록 되어 있다.
"TP-Processor1275" daemon prio=10 tid=0x00002aaabc31c800 nid=0x11d4 waiting for monitor entry [0x0000000044f6f000] java.lang.Thread.State: BLOCKED (on object monitor) at com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory.getInstance(DTDDVFactory.java:44) - waiting to lock <0x00000006f0854ae8> (a java.lang.Class for com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.<init>(XML11Configuration.java:538) at com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration.<init>(XIncludeAwareParserConfiguration.java:125) at com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration.<init>(XIncludeAwareParserConfiguration.java:86) at sun.reflect.GeneratedConstructorAccessor10.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at java.lang.Class.newInstance0(Class.java:355) at java.lang.Class.newInstance(Class.java:308) at com.sun.org.apache.xerces.internal.parsers.ObjectFactory.newInstance(ObjectFactory.java:349) at com.sun.org.apache.xerces.internal.parsers.ObjectFactory.createObject(ObjectFactory.java:154) at com.sun.org.apache.xerces.internal.parsers.ObjectFactory.createObject(ObjectFactory.java:97) at com.sun.org.apache.xerces.internal.parsers.DOMParser.<init>(DOMParser.java:133) at com.sun.org.apache.xerces.internal.parsers.DOMParser.<init>(DOMParser.java:117) at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.<init>(DocumentBuilderImpl.java:115) at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl.newDocumentBuilder(DocumentBuilderFactoryImpl.java:72) at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:237) at org.apache.ibatis.parsing.XPathParser.<init>(XPathParser.java:122) at org.apache.ibatis.builder.xml.XMLMapperBuilder.<init>(XMLMapperBuilder.java:74) at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:310) at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:104) at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:89) at org.mybatis.spring.SqlSessionFactoryBean.buildSqlSessionFactory(SqlSessionFactoryBean.java:374) at jp.google.center.multidatasource.DynamicSqlSessionFactoryBean.buildSqlSessionFactory(DynamicSqlSessionFactory Bean.java:42) at jp.google.center.multidatasource.ExecutionAspect.distribute(ExecutionAspect.java:110) |
구글에 검색해보니.. 이미 성능 이슈가 난 것으로 알려져 있다. (fixed가 되어 있다.jaxb도 연관되어 있었음을 확인할 수 있다. )
https://issues.apache.org/jira/browse/CXF-3180
결국. AbstactDataSourceRouter를 제외하는 구조로 변경했다. 미리 Connection Pool과 Mybatis SqlSessionFactory를 초기화과정에서 만들어지도록 했다. 만들어진 SqlSessionFactory를 사용하도록 하니.
성능이 3배 정도로 나왔다.