posts - 42,comments - 83,trackbacks - 0
        几乎所有使用weblogic的大一点的企业环境中,都会使用到cluster, 使用cluster势必要采用proxy, proxy有很多,apache, iis及weblogic提供的HttpClusterServlet。plugin的配置参数有很多,可参考下面的链接,http://e-docs.bea.com/wls/docs92/plugins/plugin_params.html#wp1157622。这篇文章中,我们主要看看DynamicServerList 内部实现是什么样子的。

        首先我们来看一下DynamicServerList 的具体解释,默认值是enable的,
        When set to OFF, the plug-in ignores the dynamic cluster list used for load balancing requests proxied from the plug-in and only uses the static list specified with the WebLogicCluster parameter. Normally this parameter should remain set to ON. There are some implications for setting this parameter to OFF:
         1:If one or more servers in the static list fails, the plug-in could waste time trying to connect to a dead server, resulting in decreased performance. 
         2:If you add a new server to the cluster, the plug-in cannot proxy requests to the new server unless you redefine this parameter. WebLogic Server automatically adds new servers to the dynamic server list when they become part of the cluster. 
         
         从上面的描述可以看出,DynamicServerList 用于使proxy实时获取后端cluster中的server列表(比如cluster中的member增加、删除,member状态的变化(startup、shutdown)),这样proxy在load balance request的时候可以避免去try dead server。同时可以将请求dispatch到cluster中的新增member上(比如预定义的cluster中有server1, server2,某时刻发现后端server load比较高,新增加一个server3,这时候,如果DynamicServerList 为on,你就不需要重新定义WeblogicCluster,当然也不需要重起plugin)。顺便提一下,DynamicServerList为on的时候,http.conf或HttpClusterServlet对应的web.xml中的WeblogicCluster无需定义所有的cluster member,指定任意一个即可。
WebLogicCluster 10.130.2.41:7021,10.130.2.42:7021,10.130.2.43:7021
WebLogicCluster 10.130.2.41:7021
上面两种写法是等效的,但DynamicServerList若为off,则必须采用上面的写法。

        下面我们来看看proxy是如何感知后端cluster状态的变化,从而及时更新自己手里的server list以便提高dispatch request的速度。
        1:plugin端(以HttpClusterServlet为例)
            在plugin处理client端请求的时候,它在将请求dispatch到后端server的时候,会在http header中加上一个名为X_WEBLOGIC_REQUEST_CLUSTERINFO的internal header, 如下:
HttpClusterServlet.java
1 protected void addRequestHeaders(HttpServletRequest request, PrintStream headerOut, Object o1, Object o2) {
2     super.addRequestHeaders(request, headerOut, o1, o2);
3     
4     headerOut.print(ServletResponseImpl.X_WEBLOGIC_REQUEST_CLUSTERINFO + ": true");
5     headerOut.print(EOL);
6 }

       2: managed server端
       managed server在处理完http request后,回写response到proxy端的时候,检查当前managed server是否位于一个cluster中及request的header中是否包含X_WEBLOGIC_REQUEST_CLUSTERINFO。如果上述条件成立,再去检查当前cluster的hash,如果cluster的hash发生变化(对比当前cluster的hash和proxy传递过来的hash),则将cluster member的信息通知给proxy,这个通知也是通过http header来实现,不同的是header名为:X_WEBLOGIC_CLUSTER_LIST及X_WEBLOGIC_CLUSTER_HASH,如下:
ServletResponseImpl.java
 1   /*package*/ final void writeHeaders() throws IOException {
 2         
 3     HttpServer httper = getHttpServer();
 4     if (httper != null) {
 5       boolean isPlugin = false;
 6       ServerMBean serverMBean = ManagementService.getRuntimeAccess(
 7               WebAppConfigManager.KERNEL_ID).getServer();
 8       if (serverMBean.getCluster() != null &&
 9           request.getHeader(X_WEBLOGIC_REQUEST_CLUSTERINFO) != null) {
10         
11         String hash = request.getHeader(X_WEBLOGIC_CLUSTER_HASH);
12         String oldHash = hash == null ? "" : hash;
            //MemberControllerImpl is a singlton instance and it's hash is changed when cluster changs
13         String currentHash = MembershipControllerImpl.getInstance().getHash();
14         String passedHash = headers.getHeader(X_WEBLOGIC_CLUSTER_HASH);
15         if (currentHash != null && !currentHash.equals(oldHash)) {
16           String[] servers =
17           MembershipControllerImpl.getInstance().getClusterList(
18               request.getConnection().getChannel());
19                         
20             headers.setHeader(X_WEBLOGIC_CLUSTER_HASH, currentHash);
21             headers.setHeader(X_WEBLOGIC_CLUSTER_LIST, sb.toString());//sb presents servers list string
22           }
23         }
24        } 
25     }
    
        3:proxy端,
        回到proxy端,proxy读取managed server的response,将response写回到客户端。在读取response的时候,它同时会解析inter header的信息。如果发现DynamicServerList为true,而且response的header中包含X_WEBLOGIC_CLUSTER_LIST、X_WEBLOGIC_CLUSTER_HASH等信息,它会据此更新request info,如下:
HttpClusterServlet.java
 1   public void addResponseHeaders(HttpServletResponse response, String name, String value, Object o) {
 2     RequestInfo ri = (RequestInfo) o;
 3     if (ri.needToUpdateDynamicList() &&
 4         name.equals(ServletResponseImpl.X_WEBLOGIC_CLUSTER_LIST)) {
 5       ri.setDynamicList(value);      
 6       return;
 7     }
 8     if (ri.needToUpdateDynamicList() &&
 9         name.equals(ServletResponseImpl.X_WEBLOGIC_CLUSTER_HASH)) {
10       ri.setDynamicHash(value);
11       return;
12     }
13         
14   }
        而requestInfo是一个请求范围的变量,更新它其实无法更新到proxy中的server list。server list的更新发生在一个request结束的时候,就HttpServletRequest.service()的finally块中。在finally块中,检查requestInfo中的dynamicServerList存在,如果存在则说明后端cluster发生了变化(否则managed server不会发送X_WEBLOGIC_CLUSTER_LIST信息到proxy端),那么它会将自己手里的serverlist, server hash信息设置为后端返回的值,如下:
 1      finally
 2      {
 3          String dynamicList = ri.getDynamicList();
 4           if (dynamicList != null) {
 5             ServerList servers = new ServerList(dynamicList, false);
 6             if (!useDynamicList) {
 7                         
 8             } else {
 9               servers.setHash(ri.getDynamicHash());
10               if (verbose) trace("Updating dynamic server list: " + dynamicList);
11               srvrList = servers;
12               servers.addToKnownServersList(allKnownServers);
13             }
14      }

       至此,DynamicServerList 的实现流程基本能看明白了吧。而对于static server list,不建议大家使用,否则proxy的分发性能会在cluster不稳定的时候发生下降。 但在cluster本身partition掉的时候,static server list会显得更好。也就是说cluster出现问题了,cluster中的member不能看到所有其他的members(甚至只能看到自己),比如cluster中有4个server, A\B\C\D,如果某一时刻请求被dispatch到A上,而此时如果A只能看到B(即在A的眼中,只有它自己和B可以提供服务),这时候A会将只包含A\B的cluster server list返回给proxy,那么proxy在分发后续请求的时候,只会在A\B上做load balance(C\D不会接受到请求,虽然他们还在running),直到cluster恢复正常或发生变化。而这种情况下,如果static server list的话,A\B\C\D都会接受到proxy分发过来的请求。当然这只是种非正常情况,出现这种情况的时候,我们首要任务应该是解决cluster partition的问题,而不是依赖于static server list。


posted on 2008-11-13 13:48 走走停停又三年 阅读(2601) 评论(6)  编辑  收藏 所属分类: Weblogic

FeedBack:
# re: 浅析weblogic10 plugin中的DynamicServerList
2009-02-25 16:54 | wellpha
请教一下怎么解决你上面说的cluster partition的问题,我配置的httpClusterServlet中返回的server list总是只有一个服务器,但实际上我3个都是启动的。  回复  更多评论
  
# re: 浅析weblogic10 plugin中的DynamicServerList
2009-02-25 16:58 | 走走停停又三年
检查一个server log,看看是multi cast有问题,还是managed server本身出了问题。通常情况下,如果server正常,log中你可以看到join cluster之类的文字  回复  更多评论
  
# re: 浅析weblogic10 plugin中的DynamicServerList
2009-02-26 15:06 | wellpha
谢谢你的答复,我用的是weblogic server 10.3,cluster的通讯方式选的是unicast,这样就一直只能看到一个server。而我改成multicast的方式就没问题,能发现所有的服务器。不知道unicast有什么需要特别配置的地方?  回复  更多评论
  
# re: 浅析weblogic10 plugin中的DynamicServerList
2009-02-26 16:46 | fjin
应该是unicast channel有问题,你重新配置一个channel试试,别用defaul channel。  回复  更多评论
  
# re: 浅析weblogic10 plugin中的DynamicServerList
2009-02-26 16:51 | wellpha
问题已经解决了,是我的unicast channel没配置好,需要指定listen address  回复  更多评论
  
# re: 浅析weblogic10 plugin中的DynamicServerList
2009-06-05 10:23 | flyisland
不错的文章,把整个过程讲清楚了。

昨天刚刚解决了一个weblogic cluster plugin(apache) 分发失败的问题,从proxy log大致看出了这个流程,再看到你的文章,就更加清晰了。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: