分布式应用上下文(Distributed ThreadLocal)

1.问题

单机应用内,在进程内部,我们可以使用ThreadLocal传递应用上下文的方式. 当前的 Spring Secrucity , Spring TransactionManager,  Log4J MDC, Struts2 ActionContext等等应用场景随处可见.

 

但在是分布式系统下,由于不是在同一个进程内,所以无法使用ThreadLocal. 那么什么是分布式ThreadLocal呢?就是将一个系统中的ThreadLocal信息可以传递至下一个系统,将两者的调用可以关联起来。如对应用有一个调用,我们生成一个请求ID (traceId),在后面所有分布式系统调用中,可以通过这个traceId将所有调用关联起来,这样查找调用日志都将十分方便.

 

2.实现方式

我们现在使用的通讯协议,一般都包含两部分:Header,Body. 如 Soap Header,Http Header. 通过自定义Header,可以带上我们的自定义信息。 然后在服务器端解析Header,再得到自定义信息。那么就可以完成Distributed ThreadLocal的功能。

 

 

 

如上图,通过两个拦截器,client在调用之前,将DistrbiutedThreadLocal中的信息放在soap header中,在服务端方法调用之前,从soap header中取回 DistrbiutedThreadLocal信息。

 

 

3. 实现代码.

以下为CXF webservice的实现代码,一个DistributedThreadLocal及增加了两个拦截器. hessian 也可以自定义Header,完成传递.

 

DistributedThreadLocal

 

/**
 * 分布式 ThreadLocal, 存放在ThreadLocal中的数据可以传输至另外一台机器上
 * @author badqiu
 */
public class DistributedThreadLocal {
	public static String DISTRIBUTED_THREAD_LOCAL_KEY_PREFIX = "tl_";
	
	public static ThreadLocal> threadLocal = new ThreadLocal>();

	public static void putAll(Map map) {
		getMap().putAll(map);
	}
	
	public static void put(String key, String value) {
		getMap().put(key, value);
	}

	public static String get(String key) {
		Map map = threadLocal.get();
		if (map == null)
			return null;
		return (String) map.get(key);
	}

	public static Map getMap() {
		Map map = threadLocal.get();
		if (map == null) {
			map = new HashMap();
			threadLocal.set(map);
		}
		return map;
	}

	public static void clear() {
		threadLocal.set(null);
	}

}

 

DistributedThreadLocalInSOAPHeaderInterceptor

 

/**
 * 输入(In)拦截器,用于从 WebService SOAP 的Header中取回DistributedThreadLocal中的信息,并存放在DistributedThreadLocal中
 * 
 * @author badqiu
 */
public class DistributedThreadLocalInSOAPHeaderInterceptor extends AbstractSoapInterceptor {
	
    private SAAJInInterceptor saajIn = new SAAJInInterceptor();  
    
    public DistributedThreadLocalInSOAPHeaderInterceptor() {  
        super(Phase.PRE_PROTOCOL);  
        getAfter().add(SAAJInInterceptor.class.getName());  
    }  

	public void handleMessage(SoapMessage message) throws Fault {
		SOAPMessage doc = message.getContent(SOAPMessage.class);  
        if (doc == null) {  
            saajIn.handleMessage(message);  
            doc = message.getContent(SOAPMessage.class);  
        }  
        
        Map headers = toHeadersMap(doc);  
		DistributedThreadLocal.putAll(headers);
		
	}

	private Map toHeadersMap(SOAPMessage doc) {
		SOAPHeader header = getSOAPHeader(doc);  
        if (header == null) {  
            return new HashMap(0);  
        } 
        
        Map headersMap = new HashMap();
        NodeList nodes = header.getChildNodes();
        for(int i=0; i
 

DistributedThreadLocalOutSOAPHeaderInterceptor

 

/**
 * 输出(Out)拦截器,用于将DistributedThreadLocal中的信息存放在 WebService SOAP 的Header中
 * 
 * @author badqiu
 */
public class DistributedThreadLocalOutSOAPHeaderInterceptor extends AbstractSoapInterceptor {
	
	public DistributedThreadLocalOutSOAPHeaderInterceptor() {
		super(Phase.WRITE);
	}

	public void handleMessage(SoapMessage message) throws Fault {
		
		List
headers = message.getHeaders(); Map threadlocalMap = DistributedThreadLocal.getMap(); for(Map.Entry entry : threadlocalMap.entrySet()) { headers.add(getHeader(entry.getKey(), entry.getValue())); } } private Header getHeader(String key, String value) { QName qName = new QName(key); Document document = DOMUtils.createDocument(); Element element = document.createElement(key); element.appendChild(document.createTextNode(value)); SoapHeader header = new SoapHeader(qName, element); return (header); } }
 

CXF spring配置文件:

 

server端: 

 



	Apache CXF的Web Service配置

	
	
	

	
	
		
		
			
		
	
	
	
	

 

client端:

 


	Apache CXF Web Service Client端配置

	
		
			
		
	

 

4. 应用场景.

通过分布式应用上下文,暂时想到的几个应用场景.

 

1. Log4j MDC traceId传递.  通过一个traceId,将所有相关的 操作所有的日志信息关联起来。

2. sessionId 传递, 让我们的应用也有状态,可以使用session什么的

3. Security(username,password)传递. 在需要安全调用的地方,避免污染接口,需要显式的在接口传递username,password. 相对应的 WSSecurity也可以走这个通道

 

 

 

 

 

 

分布式应用上下文的概念,全球首创,欢迎转载(因为google 搜索不到相关文章,或许早已经有相同的概念了,欢迎提醒我)。

 

 

 

 

 

你可能感兴趣的:(应用服务器,Apache,WebService,Spring,SOAP)