RPC框架之-DUBBO(二)负载均衡

来源:互联网 发布:java 连接池框架 编辑:程序博客网 时间:2024/05/21 16:59

最新的项目用了dubbo框架,原来只有一台provider机器提供服务,但是现在需要扩展到多台provider机,并且由于业务逻辑涉及到了文件加密解密操作,而密钥又是由客户提供的,因此出现了第二次请求过来会由dubbo分发到文件所在位置以外的服务机上,就出现了找不到文件的情况。

ok,作为supportor,开始解决,方案1是直接增加文件服务器来进行,但是由于项目已经上线,改起来麻烦,于是果断pass;

这样就有了方案2,修改dubbo的负载均衡策略,使得每次的业务逻辑在一条流水线上进行。

本文会持续更新,来介绍负载均衡

1. consistenthash--一致性hash算法

使用方式,在服务端注册的时候提供配置

<!-- 声明需要暴露的服务接口 -->    <dubbo:service interface="DemoService" ref="demoService" loadbalance="consistenthash" />
dubbo对于该算法默认比较的是第一个请求参数,即相同的请求参数会分发到同一台服务机上。

最开始看到这个解释的时候瞬间迷茫了(原谅我的理解力),度娘了一下发现也没有demo,官网也没有提供,好吧,只能让我这种懒人自己来写了。

相关代码已在上面提供下载,这里启动了两台服务机,server 1 和server 2

服务端

public static void main(String[] args) throws Exception {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "classpath:consumer.xml" });context.start();DemoService demoService = (DemoService) context.getBean("demoService");while(true){String hello = demoService.sayHello("word", "1");String hello1 = demoService.sayHello("word", "2");System.out.println(hello);System.out.println(hello1);}}

这里我们看到,demoSerivce.sayHello()方法的第一个参数相同。

直接启动,结果如下,可以看到,所有的服务都是由机器2来提供的(也有可能都是1,主要看第一次是由那台服务机提供服务)

server 2 say: Hello word, today is 1server 2 say: Hello word, today is 2server 2 say: Hello word, today is 1server 2 say: Hello word, today is 2server 2 say: Hello word, today is 1server 2 say: Hello word, today is 2server 2 say: Hello word, today is 1server 2 say: Hello word, today is 2


第二个参数默认上不会对负载结果产生影响(可以通过配置文件来设置对比几个参数,默认是第一个)

因此开始考虑,一致性是通过什么来比对呢?看了一致性算法,果然没看懂,那只能试一试了。。。

开始考虑普通pojo

创建一个Students类,只有两个属性,name和age

Students s1 = new Students();s1.setName("dog");s1.setAge(1);Students s2 = new Students();s2.setName("cat");s2.setAge(2);DemoService demoService = (DemoService) context.getBean("demoService");while (true) {String hello = demoService.sayHello(s1);String hello1 = demoService.sayHello(s2);System.out.println(hello);System.out.println(hello1);}
运行结果如下,server 1 处理所有的cat,server2处理所有的dog

server 1 say: Hello cat, age is 2server 2 say: Hello dog, age is 1server 1 say: Hello cat, age is 2server 2 say: Hello dog, age is 1server 1 say: Hello cat, age is 2server 2 say: Hello dog, age is 1server 1 say: Hello cat, age is 2server 2 say: Hello dog, age is 1
修改代码位置,把students对象的创建移动到for循环内

测试结果,说明对比的不是元素属性是否一致,而是和对象地址有关

server 1 say: Hello dog, age is 1server 2 say: Hello cat, age is 2server 2 say: Hello dog, age is 1server 2 say: Hello cat, age is 2server 2 say: Hello dog, age is 1

修改Students类的序列化参数,发现结果还是与地址有关

因此,最后项目修改如下,

第一次请求-->随机生成一个token-->服务机创建临时文件-->返回文件位置及token

第二次请求,携带token和文件位置-->通过token找到对应服务机-->文件加密-->业务结束

PS,由于比对的是地址值,因此需要设置一个web容器级别的token池,以保证对象一致

不过也有缺点,当消费机也是集群模式的时候,该配置无效。。。因为不同消费机的token地址不一致...

因此,如果是nginx做的前端负载均衡, 需要通过sticky来实现负载均衡(基于cookie),基本上由同一消费机提供服务,这样就能保证token同一了


最后,还是用文件服务器比较好,一劳永逸。




1 0
原创粉丝点击