• 使用Dubbo的SPI扩展机制实现自定义LoadBalance——方法一 修改Dubbo源代码


    一. 拉取源码

    到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调试运行就可以了。

  • 相关阅读:
    12.Scala- 注解
    11.Scala-特质
    10.Scala-继承
    9.Scala- 包和引入
    8.Scala-对象
    7.Scala-类
    6.Scala-高阶函数
    5.Scala-匹配模式
    4.Scala-数据结构
    Ruby on Rails Tutorial 第四章 Rails背后的Ruby 之 类
  • 原文地址:https://www.cnblogs.com/Sicwen/p/10573617.html
Copyright © 2020-2023  润新知