一. 拉取源码
到Dubbo官网 https://github.com/apache/incubator-dubbo/tree/2.5.x 下载源码,解压。
二. 导入IDEA
选择解压后的源码目录,一路点击next
三. 实现LoadBalance接口
在loadbalance包中,创建一个class,并实现LoadBalance接口。 如下:创建SameSessionIdLoadBalance类实现LoadBalance接口
/**
* 保存sessionId和服务地址的映射关系
* invoker.getUrl().getAddress()可以获取到该invoker的服务地址信息
* sessinoId存在,那么就返回sessionId所在的invoker
* sessionId不存在,那么就轮训的找一个invoker返回
*/
public class SameSessionIdLoadBalance implements LoadBalance { private final static Logger logger = LoggerFactory.getLogger(SameSessionIdLoadBalance.class); private Map<String,String> sessionIdAddress = new ConcurrentHashMap<String,String>(256); private AtomicInteger index = new AtomicInteger(0); @Override public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException { Invoker result = null;
//约定方法的第一个参数就是sessionId String sessionId = (String) invocation.getArguments()[0]; if(!sessionIdAddress.containsKey(sessionId)){ result = invokers.get(index.getAndIncrement()%invokers.size()); sessionIdAddress.put(sessionId,result.getUrl().getAddress()); }else{ String destAddress = sessionIdAddress.get(sessionId); for (Invoker<T> invoker : invokers) { if(invoker.getUrl().getAddress().equals(destAddress)){ result = invoker; } } } logger.info(\"sesisonId: \" + sessionId + \" ,method: \" + invocation.getMethodName() + \" ,select \" + result.getUrl().getAddress() + \" broker\"); return result; } }
四. 添加配置信息
添加的samesessionloadbalance就是该负载均衡的名字。
五. 构建安装源码
打开终端控制台执行mvn clean install -Dmaven.test.skip
最后会在maven的本地仓库中生成jar包
可以通过360解压缩查看jar包中的class文件,看看我们的代码是否编译进去了。
六. 测试代码
公共接口
public interface DemoService { String saySomething(String msg); }
provider实现该接口
public class DemoServiceImpl implements DemoService { public String saySomething(String msg) {
//每次启动 把20880改成相应的端口 方便观察结果。 return \"this is 20880 \" + msg; } }
Provider启动
public class Provider { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(\"classpath:provider.xml\"); ctx.start(); System.in.read(); } }
provider.xml
<?xml version=\"1.0\" encoding=\"UTF-8\"?> <beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd\"> <!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name=\"hello-world-app\" /> <!-- 使用zookeeper注册中心暴露服务地址 --> <dubbo:registry address=\"zookeeper://10.130.41.36:2181\"/> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name=\"dubbo\" port=\"20880\" /> <!-- 声明需要暴露的服务接口 --> <!--samesessionloadbalance--> <dubbo:service interface=\"com.xxx.testdubbo.DemoService\" ref=\"demoService\" loadbalance=\"samesessionloadbalance\"/> <!-- 和本地bean一样实现服务 --> <bean id=\"demoService\" class=\"com.xxx.testdubbo.provider.DemoServiceImpl\" /> </beans>
Consumer启动
public class Customer { public static void main(String[] args){ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(\"classpath:customer.xml\"); DemoService ds = (DemoService) ctx.getBean(\"demoService\"); System.out.println(ds.saySomething(\"001\")); } }
customer.xml
<?xml version=\"1.0\" encoding=\"UTF-8\"?> <beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd\"> <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 --> <dubbo:application name=\"consumer-of-helloworld-app\" /> <!-- 使用zookeeper注册中心暴露发现服务地址 --> <dubbo:registry address=\"zookeeper://10.130.41.36:2181\" /> <!-- 生成远程服务代理,可以和本地bean一样使用demoService --> <dubbo:reference id=\"demoService\" interface=\"com.xxx.testdubbo.DemoService\" /> </beans>
七.启动实例测试
Dubbo使用一些容错机制,里面会有一些判断。如下图所示:
当invoker只有一个那么就直接返回
当invoker有两个那么使用轮序机制
当有三个或三个以上的invoker时,才会触发loadbalance机制。
所以我们要启动三个Provider
更改provider.xml中Dubbo的监听端口为20880,20881,20882分别启动实例
在DemoServiceImpl中,每启动一个Provider实例,该方法返回相应的ip+端口号信息。
最后启动Customer,观察端口号结果。
八. 调试自定义LoadBalance
在项目里面一定引用了Dubbo的jar包,找到SameSessionIdLoadBalance文件,下断点,Consumer调试运行就可以了。