16.路由如何实现
com.alibaba.dubbo.rpc.cluster.directory.AbstractDirectory.list(Invocation) 中织入了路由的逻辑;
使用路由的test case
package com.code260.ss.dubbo.demov.client.routeruler;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.registry.RegistryFactory;
import com.code260.ss.dubbo.demov.facade.service.HelloService;
/**
* <一句话功能简述> <功能详细描述>
*
* @author Chenxiaguang
* @version [版本号, 2015-8-12]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/com/code260/ss/dubbo/demov/client/conf/routerruler/applicationContext.xml")
public class HelloClientTest
{
@Autowired
private HelloService helloService;
@BeforeClass
public static void setup() {
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
// 获取注册中心,这里使用zk
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://127.0.0.1:2182"));
// 注册中心上配置规则
URL condition = URL.valueOf("condition://0.0.0.0/com.code260.ss.dubbo.demov.facade.service.HelloService?category=routers&dynamic=false&rule="
+ URL.encode("host = 192.168.2.3 => port = 20880"));
System.out.println(condition.toString());
registry.register(condition);
}
@Test
public void testSayHello()
{
this.helloService.sayHello("Simon1");
this.helloService.sayHello("Simon2");
this.helloService.sayHello("Simon3");
this.helloService.sayHello("Simon4");
}
}
这是client侧的case,provider继续沿用多个provider的case,此时我们配置了路由规则,让192.168.2.3这台机器发出的调用都路由到端口是20880的服务节点上。
路由实现与服务发现衔接处
dubbo实现路由的地方是在com.alibaba.dubbo.rpc.cluster.directory.AbstractDirectory.list(Invocation)。
贴下相应调用栈和关键代码,调用栈如下:
RegistryDirectory<T>(AbstractDirectory<T>).list(Invocation) line: 81
FailoverClusterInvoker<T>(AbstractClusterInvoker<T>).list(Invocation) line: 260
FailoverClusterInvoker<T>(AbstractClusterInvoker<T>).invoke(Invocation) line: 219
MockClusterInvoker<T>.invoke(Invocation) line: 72
InvokerInvocationHandler.invoke(Object, Method, Object[]) line: 52
proxy0.sayHello(String) line: not available
HelloClientTest.testSayHello() line: 56
代码如下:
com.alibaba.dubbo.rpc.cluster.directory.AbstractDirectory.list(Invocation)
69 public List<Invoker<T>> list(Invocation invocation) throws RpcException {
70 if (destroyed){
71 throw new RpcException("Directory already destroyed .url: "+ getUrl());
}
List<Invoker<T>> invokers = doList(invocation);
74 List<Router> localRouters = this.routers; // local reference
if (localRouters != null && localRouters.size() > 0) {
76 for (Router router: localRouters){
try {
if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, true)) {
79 invokers = router.route(invokers, getConsumerUrl(), invocation);
}
} catch (Throwable t) {
logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
}
}
}
return invokers;
}
79行会根据我们配置的路由规则,过滤出符合路由条件的invoker列表。
此处路由我们使用的是条件路由,具体实现比较简单,阅读com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouter.route(List<Invoker
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!