百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

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

bigegpt 2024-08-10 11:58 5 浏览

一. 拉取源码

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

欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 721575865

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

相关推荐

10w qps缓存数据库——Redis(redis缓存调优)

一、Redis数据库介绍:Redis:非关系型缓存数据库nosql:非关系型数据库没有表,没有表与表之间的关系,更不存在外键存储数据的形式为key:values的形式c语言写的服务(监听端口),用来存...

Redis系列专题4--Redis配置参数详解

本文基于windowsX64,3.2.100版本讲解,不同版本默认配置参数不同在Redis中,Redis的根目录中有一个配置文件(redis.conf,windows下为redis.windows....

开源一夏 | 23 张图,4500 字从入门到精通解释 Redis

redis是目前出场率最高的NoSQL数据库,同时也是一个开源的数据结构存储系统,在缓存、数据库、消息处理等场景使用的非常多,本文瑞哥就带着大家用一篇文章入门这个强大的开源数据库——Redis。...

redis的简单与集群搭建(redis建立集群)

Redis是什么?是开源免费用c语言编写的单线程高性能的(key-value形式)内存数据库,基于内存运行并支持持久化的nosql数据库作用主要用来做缓存,单不仅仅是做缓存,比如:redis的计数器生...

推荐几个好用Redis图形化客户端工具

RedisPlushttps://gitee.com/MaxBill/RedisPlusRedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件,支持Windows、Linux...

关于Redis在windows上运行及fork函数问题

Redis在将数据库进行持久化操作时,需要fork一个进程,但是windows并不支持fork,导致在持久化操作期间,Redis必须阻塞所有的客户端直至持久化操作完成。微软的一些工程师花费时间在解决在...

你必须懂的Redis十大应用场景(redis常见应用场景)

Redis作为一款高性能的键值存储数据库,在互联网业务中有着广泛的应用。今天,我们就来详细盘点一下Redis的十大常用业务场景,并附上Golang的示例代码和简图,帮助大家更好地理解和应用Redis。...

极简Redis配置(redis的配置)

一、概述Redis的配置文件位于Redis安装目录下,文件名为redis.conf(Windows名为redis.windows.conf,linux下的是redis.conf)你可以通过C...

什么是redis,怎么启动及如何压测

从今天起咱们一起来学习一下关于“redis监控与调优”的内容。一、Redis介绍Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。...

一款全新Redis UI可视化管理工具,支持WebUI和桌面——P3X Redis UI

介绍P3XRedisUI这是一个非常实用的RedisGUI,提供响应式WebUI访问或作为桌面应用程序使用,桌面端是跨平台的,而且完美支持中文界面。Githubhttps://github....

windows系统的服务器快速部署java项目环境地址

1、mysql:https://dev.mysql.com/downloads/mysql/(msi安装包)2、redis:https://github.com/tporadowski/redis/r...

window11 下 redis 下载与安装(windows安装redis客户端)

#热爱编程是一种怎样的体验#window11下redis下载与安装1)各个版本redis下载(windows)https://github.com/MicrosoftArchive/r...

一款轻量级的Redis客户端工具,贼好用!

使用命令行来操作Redis是一件非常麻烦的事情,我们一般会选用客户端工具来操作Redis。今天给大家分享一款好用的Redis客户端工具TinyRDM,它的界面清新又优雅,希望对大家有所帮助!简介Ti...

一个.NET开发且功能强大的Windows远程控制系统

我们致力于探索、分享和推荐最新的实用技术栈、开源项目、框架和实用工具。每天都有新鲜的开源资讯等待你的发现!项目介绍SiMayRemoteMonitorOS是一个基于Windows的远程控制系统,完...

Redis客户端工具详解(4款主流工具)

大家好,我是mikechen。Redis是大型架构的基石,也是大厂最爱考察内容,今天就给大家重点详解4款Redis工具@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题合集...