关于dubbo里面的负载均衡部分,实际上是可以通过一定的配置来进行设置的。
关于负载均衡的案例我们还是使用之前的消费者,生产者案例来进行说明:
我们在之前的基础上模拟一下开启两个服务提供者:
分别是服务开关Application1:
package com.lh.pro.server; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; /** * 作者:idea * 日期:2018/8/11 * 描述: */ public class Application { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"application-context.xml"}); context.start(); System.out.println("dubbo的服务生产者1开启了"); //长期开启应用 System.in.read(); } } 复制代码
服务开关Application2
package com.lh.pro.server; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; /** * 作者:idea * 日期:2018/8/11 * 描述:服务开关2 */ public class Application2 { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"application-context.xml"}); context.start(); System.out.println("dubbo的服务生产者2开启了"); //长期开启应用 System.in.read(); } } 复制代码
注意,两者在开启的时候要调整dubbo的服务端口号。同时在开启
<!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> 复制代码
创建好了相应的服务之后,我们就可以进入相应的测试环节了:
首先在服务Application1开启的时候我们对于UserRpcService接口的实现如下:
package com.lh.pro.rpc; import com.sise.service.UserRpcService; import org.springframework.stereotype.Service; /** * 作者:idea * 日期:2018/8/11 * 描述:用户service服务调度 */ @Service("userService") public class UserService implements UserRpcService{ /** * 返回用户名的服务 * @param username * @return */ public String getUserName(String username) throws InterruptedException { return username+" hello !"; } } 复制代码
服务开关2开启的时候,UserRpcService的实现改为以下内容:
package com.lh.pro.rpc; import com.sise.service.UserRpcService; import org.springframework.stereotype.Service; /** * 作者:idea * 日期:2018/8/11 * 描述:用户service服务调度 */ @Service("userService") public class UserService implements UserRpcService{ /** * 返回用户名的服务 * @param username * @return */ public String getUserName(String username) throws InterruptedException { return username+" hello ! cluster test"; } } 复制代码
这个时候就呈现了这么一种情况,同一个服务有两个服务提供者来提供。
修改服务实现的好处就在于 能够区分出不同服务的提供方
这个时候我们开启消费者一方,为了能够模拟负载均衡,我们对消费者一方进行了一个服务的循环访问来模拟高压场景:
package com.lh.consume; import com.sise.service.UserRpcService; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; /** * 作者:idea * 日期:2018/7/29 * 描述:消费者测试 */ public class ConsumerTest { public static void main(String[] args) throws InterruptedException { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"classpath:application-consumer.xml"}); context.start(); // //这里开始模拟疯狂调用服务进行增加压力 for(int i=0;i<100;i++){ UserRpcService userService= (UserRpcService) context.getBean("userService"); System.out.println(userService.getUserName("this is "+i)); } try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } } 复制代码
开启两个生产者开关后,在进行消费者的调用,
这个时候我们果然能够通过控制台里面打印的内容看到不一样的效果:
接下来我们去到dubbo-admin平台中心里面进行权重划分,重新调整压力分配的形式:
这个时候就会出现服务端口号为20881的一方负载能力增强。
16:1的负载分配情况截图
在集群负载均衡时,Dubbo提供了多种均衡策略,默认情况下为random随机调用。
Random LoadBalance
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
RoundRobin LoadBalance
轮循,按公约后的权重设置轮循比率。
存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
ConsistentHash LoadBalance
一致性Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
举个例子:
假设要采用轮训的方式来进行负载均衡,需要添加以下配置:
这样子的情况下,接口的响应内容如下: