spring 의 동적 루트 를 사용 하여 데이터베이스 부하 균형 을 실현 하 다

111115 단어 MysqlSpring
spring 2.0.1 이 발표 되 기 전에 각 프로젝트 에 이러한 상황 에 대한 다 중 데이터 소스 관리 방식 이 여러 가지 존재 할 수 있 습 니 다. 단,spring 2.0.1 발표 후 AbstractRouting DataSource 를 도입 하여 가능 합 니 다.
org.springframework.jdbc.datasource.lookup.AbstractRouting DataSource 류 를 통합 하여 동적 데이터 원본 을 사용자 정의 합 니 다.

설정 은 다음 과 같 습 니 다:datasource-config.xml:


	
	
		
		
		
		
		
		
		
		
		
	
	
		
		
		
		
		
		
		
		
		
	
	
		
			
				
				
			
		
		
			
		
	
	
	
		
			
		
	
	
	
		
		
		
	
	
		
			
				PROPAGATION_REQUIRED,-PtServiceException
				PROPAGATION_REQUIRED,-PtServiceException
				PROPAGATION_REQUIRED,-PtServiceException
				PROPAGATION_REQUIRED,-PtServiceException
				PROPAGATION_REQUIRED,-PtServiceException
			
		
	
	
		
			true
		
		
			
		
	
	
		
			
		
		
			
		
	
	
		
			
		
		
			
		
	
	
		
			
				
			
		
	
	
		
		
	

com.common.bean.RoutingDataSource 클래스:
package com.common.bean;import java.sql.Connection;import java.sql.SQLException;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;publicclassRoutingDataSourceextendsAbstractRoutingDataSource{protectedObject determineCurrentLookupKey(){//                 Shard shard =ThreadInfoHolder.getCurrentThreadShard();//    DataSourceString dbId = shard ==null?null:String.valueOf(shard.getDbId());return dbId;}@OverridepublicString toString(){//                 Shard shard =ThreadInfoHolder.getCurrentThreadShard();//    DataSourceString dbId = shard ==null?null:String.valueOf(shard.getDbId());return"DB ID "+ dbId +":"+super.toString();}publicString getTargetDbId()throwsSQLException{Connection conn =null;try{//jdbc:oracle:thin:@10.20.151.4:1521:ptdev, UserName=xx, Oracle JDBC driver
            conn = determineTargetDataSource().getConnection();if(conn !=null){String connectionDesc = conn.getMetaData().getURL();int beginIdx = connectionDesc.indexOf("@")+1;int endIdx = connectionDesc.indexOf(":", beginIdx);return connectionDesc.substring(beginIdx, endIdx);}}finally{if(conn !=null){
                conn.close();}}returnnull;}}

com.common.bean.ThreadInfoHolderpackage com.common.bean;publicclassThreadInfoHolder{// thread local,   、                privatestaticfinalThreadLocal<Shard> shardLocal =newThreadLocal<Shard>();/**
     *                  
     * 
     * @return
     */publicstaticShard getCurrentThreadShard(){returnThreadInfoHolder.shardLocal.get();}/**
     *                
     * 
     * @param shard
     */publicstaticvoid addCurrentThreadShard(Shard shard){ThreadInfoHolder.shardLocal.set(shard);}/**
     *            
     * 
     * @param shard
     */publicstaticvoid cleanCurrentThreadShard(){ThreadInfoHolder.shardLocal.remove();}}
com.common.bean.ShardpublicclassShard{//  Account   DB_IDprivateInteger            dbId;/**
     * @return the dbId
     */publicInteger getDbId(){return dbId;}/**
     * @param dbId the dbId to set
     */publicvoid setDbId(Integer dbId){this.dbId = dbId;}}

com.service.DbInfoServicepackage com.service;import java.util.List;import java.util.Map;import com.common.dao.model.User;publicinterfaceDbInfoService{publicList<Map<String,Object>> getUserInfo(User user);}

com.service.impl.DbInfoServiceImplpackage com.service.impl;import java.util.List;import java.util.Map;import com.common.bean.Shard;import com.common.bean.ThreadInfoHolder;import com.common.dao.BaseDao;import com.common.dao.model.User;import com.service.DbInfoService;publicclassDbInfoServiceImplimplementsDbInfoService{publicBaseDao baseDao;publicvoid setBaseDao(BaseDao baseDao){this.baseDao = baseDao;}publicList<Map<String,Object>> getUserInfo(User user){

        baseDao.add("login.addUser", user);List<Map<String,Object>> result=baseDao.getList("login.getUserInfo",user.getName());return result;}}

com.common.bean.Testpackage com.common.bean;import java.util.List;import java.util.Map;import com.common.dao.model.User;import com.service.DbInfoService;publicclassTest{publicDbInfoService dbInfoService;publicvoid setDbInfoService(DbInfoService dbInfoService){this.dbInfoService = dbInfoService;}publicList<Map<String,Object>> getInfo(User user){List<Map<String,Object>> result=dbInfoService.getUserInfo(user);return result;}}

테스트 main 방법 은 다음 과 같 습 니 다.
package com.transaction;import java.util.List;import java.util.Map;import org.springframework.beans.factory.xml.XmlBeanFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.core.io.ClassPathResource;import com.common.bean.Shard;import com.common.bean.Test;import com.common.bean.ThreadInfoHolder;import com.common.dao.model.User;import com.service.impl.DbInfoServiceImpl;publicclassTransactionTest{publicstaticvoid main(String[] args){ApplicationContext ctx =newClassPathXmlApplicationContext("classpath*:spring/datasource-config.xml");Test t=(Test)ctx.getBean("test");User user=newUser();
        user.setName("xj");
        user.setPassword("123");Shard shard=newShard();
        shard.setDbId(1);//  datasource1ThreadInfoHolder.addCurrentThreadShard(shard);List<Map<String,Object>> result =t.getInfo(user);
        shard.setDbId(2);//  datasource2ThreadInfoHolder.addCurrentThreadShard(shard);List<Map<String,Object>> result1 =t.getInfo(user);System.out.println(result);}}

실행 결 과 는 각각 데이터베이스 1 과 데이터베이스 2 에 1 조 기록 을 삽입 했다.
주의:
DbInfoService 에 사물 을 설정 하기 때문에 데이터 원본 을 전환 하 는 코드 ThreadInfoHolder.addCurrentThreadShard(shard)를 설정 합 니 다.DbInfoServiceImpl 류 의 getUser Info 방법 에 놓 으 면 다음 과 같 습 니 다.
publicList<Map<String,Object>> getUserInfo(User user){Shard shard=newShard();
    shard.setDbId(1);ThreadInfoHolder.addCurrentThreadShard(shard);
    baseDao.add("login.addUser", user);

    shard.setDbId(2);ThreadInfoHolder.addCurrentThreadShard(shard);
    baseDao.add("login.addUser", user);List<Map<String,Object>> result=baseDao.getList("login.getUserInfo",user.getName());return result;}

main 방법 변경:
publicstaticvoid main(String[] args){ApplicationContext ctx =newClassPathXmlApplicationContext("classpath*:spring/datasource-config.xml");Test t=(Test)ctx.getBean("test");User user=newUser();
    user.setName("xj");
    user.setPassword("123");List<Map<String,Object>> result =t.getInfo(user);System.out.println(result);}

실행 결 과 는 데이터베이스 1 에 같은 기록 2 개 를 삽입 합 니 다.각각 데이터베이스 1,2 에 하나의 기록 을 삽입 하 는 것 이 아 닙 니 다.이 결 과 는 Db InfoServiceImpl 에 사물 을 설정 하기 때문에 getUser Info 방법 에서 첫 번 째 연결 데이터 베 이 스 는 연결 을 새로 만 들 고 이 연결 을 스 레 드 의 로 컬 변수 인 ThreadLoad 에 연결 합 니 다.나중에 데이터 베 이 스 를 방문 해 야 할 때 새 연결 이 아 닌 이 연결 을 사용 하여 오래된 연결 을 연결 합 니 다.이 예 에서 첫 번 째 데이터 베 이 스 는 데이터베이스 1 을 연결 하 는 것 입 니 다.두 번 째 데이터 베 이 스 를 방문 할 때 이 데이터 베이스 1 의 연결 을 사용 합 니 다.즉,데이터 원본 설정 코드 shard.setDbId(2)를 전환 합 니 다.ThreadInfoHolder.addCurrentThreadShard(shard);효력 을 잃다.마찬가지 로 우 리 는 데이터 원본 코드 를 Test 류 의 getInfo 방법 에 전환 하면 종료 할 수 있 습 니 다.즉,:
publicList<Map<String,Object>> getInfo(User user){Shard shard=newShard();
    shard.setDbId(1);ThreadInfoHolder.addCurrentThreadShard(shard);List<Map<String,Object>> result=dbInfoService.getUserInfo(user);
    shard.setDbId(2);ThreadInfoHolder.addCurrentThreadShard(shard);List<Map<String,Object>> result1=dbInfoService.getUserInfo(user);return result;}

이렇게 하면 정확하게 운행 할 수 있 으 며,사물 을 호출 하기 전에 우 리 는 이미 데이터 원본 을 전환 해 야 한다.
다음으로 이동:http://outofmemory.cn/code-snippet/1459/usage-spring-dongtai-route-switch-zhucong-library
관련 글:
1.
spring AbstractRouting DataSource 를 사용 하여 동적 데이터 원본 을 사용자 정의 할 때의 트 랜 잭 션 처리

좋은 웹페이지 즐겨찾기