Spring-Cloud-Ribbon -- 客户端负载均衡器

Ribbon是Netflix开源的一款用于客户端负载均衡的工具软件,目前ribbon是使用轮询的方式进行负载均衡的。


何为负载均衡?  可以参考我的一篇博文:CentOS 6.5 下 Nginx的反向代理和负载均衡的实现


上述的Nginx是基于服务端的反向代理+负载均衡器


基于前两篇,我用一张图来说明一下什么是eureka(服务注册+发现中心),其实我是想画个鱼塘的,哈哈




在上图中:


       处在顶层的是我们的eureka服务注册中心(省略发现,先服务注册,随后才有服务被发现,心知肚明,我这里就省略了)

       处在两边的是eureka的client部分,所谓的client就是服务的提供者,也就是要向服务中心发起服务注册的一方,这里我们只模拟了两个客户端,服务名都叫“hello-service”,为嘛叫一样的了?因为他俩本来就是一个模子刻出来的啊,这里等于做了一个service集群(集群就是相同的服务部署到不同的机子上,说白了就是这部分  localhost:port 不一样,也有可能环境不一样,项目中的配置文件也不一样,比如一个服务部署在Windows下,一个部署在Linux下),集群的好处就是,一个服务挂掉了,另一个服务可以顶上,不至于出现无服务可用的尴尬局面,就好好比连锁店一样,为什么会有那么多连锁店,还不是有大量消费者买单吗?另外,这里的eureka客户端也可以充当服务消费者的身份,也就是,它不仅自身提供服务,而且还可以通过服务注册中心的发现服务功能,去消费xxx服务。

       处在下面的,我用了一个笑脸来代替我们自己,因为服务是死的,不会开口说话,不会动脑筋,但是我们可以啊,我们作为服务消费方借助eureka的服务发现功能,成功的获取了服务列表,但是拿到服务,我们就傻眼了


“两个服务,我用哪个呢?”





于是我们思考了片刻,觉得看8022的服务比较顺眼,于是我们就使用了8022的服务





过了一会,我们又要消费服务了,这时候,我们又要思考片刻


“哎哟我去,要是服务中心每次在我使用服务的时候帮我选好服务了该多好啊?”


“算了,刚才用了8022,这次用8080的服务吧”


于是,我们又在浏览器中访问8080的服务






上面说过,对于人来说,我们有选择的能力,但是对于程序来说,它连思考的能力都没有,如何做出选择?


上面还说过,如果服务中心能为服务消费者在使用服务的时候(这里的消费者可不再是我们自己了)提供具体的某一项服务,而不是提供一个服务列表,如果这样的话,那就相当的嗨皮了,如果这样的话,我看eureka可以改名了,叫什么


“服务注册发现定项送货上门中心” --- 还不如干脆叫“服务一条龙中心”得了


现在知道ribbon为什么是客户端级别的了吧


好了,玩笑归玩笑,毕竟eureka能干好自己的事情就好了,我们就不调戏它了


回到本篇,ribbon才是我们今天的主角,有了它,我们再也不用担心该调哪个服务了,轻松消费服务,so easy!


关于ribbon,只要记住一点:在eureka server不给我们提供服务的负载均衡下,我们的ribbon担负起了这一职责,帮助eureka client选择(choose)服务并消费








最开始说过了,ribbon默认采用的方式是轮询方式(Ribbon提供了多重策略,例如轮询round robin、随机Random、根据相应时间加权等


所谓的轮询就是

“第一天我吃肉,第二天我吃青菜,第三天我吃肉,第四天我再吃青菜.....”一次类推,第五天显然我吃肉的(有迹可循,轮流着来)


所谓的随机就是

“第一天我吃青菜,第二天我吃肉,第三天我还吃肉,第四天我吃青菜....”一次类推,你根本无法断定第五天我是吃肉还是吃青菜


所谓的加权就是

“第一天我吃肉,第二天我吃肉,第三天我吃肉,第四天我吃青菜....”一次类推,你可能发现我比较喜欢吃肉,因此第五天吃肉的概率较大,那什么时候会出现加权的策略呢?比如服务所在的服务器性能比较优,那理所当然这个服务就应该被ribbon选择的多一些,如果这个服务所在的服务器是一台年代久远的PC机,你还让它访问的次数多,这不是自找麻烦吗?


OK,我们说的有点多了,我们直接进入demo案列演示部分




一、项目目录结构树





eureka-server :  服务注册发现中心(Spring-Cloud-Eureka服务注册发现中心server+client案列模拟说明

eureka-client: 服务提供者及消费者( Spring-Boot+Eureka服务注册发现中心server+client案列demo

service-ribbon:服务消费者+ribbon客户端负载均衡器提供服务选择功能



二、service-ribbon创建 ---Pom.xml依赖添加






(1)由于ribbon是提供服务选择的,因此,没有eureka的服务发现功能,ribbon也是无力可施啊,所以,pom如下


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.appleyk</groupId>
  <artifactId>service-ribbon</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>ribbon</name>
  <description>基于Spring-Boot快速开发模式的ribbon--客户端负载均衡</description>
  <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
	</parent>
	<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 添加Eureka依赖,启用服务发现功能,再结合ribbon使用 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>
		<!-- 监控 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<!-- ribbon -->
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
	</dependencies>	
</project>




二、service-ribbon创建 ---启用euraka服务发现功能


(1)Application.java


package com.appleyk;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

//@EnableDiscoveryClient: 客户端启用服务发现功能
@EnableDiscoveryClient
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

	/**
	 * 注入一个Bean name : "restTemplate"
	 * 
	 * @return
	 */
	@Bean
	@LoadBalanced//开启客户端负载均衡
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
}


什么是RestTemplate,待会在具体的demo中进行注释解释






使用ribbon的服务choose,真的很简单,简单的只是一个注解@LoadBalance就能搞定(可ribbon源码里面要干的事情是很多的)





Choose a ServiceInstance from the LoadBalancer for the specified service

从负载均衡器中为指定的服务选择一个实例(ribbon会向eureka服务中心发请求,获得相应服务实例的列表,随后choose一个)


@return a ServiceInstance that matches the serviceId

当然,返回的服务实例可不是乱来的,必须是serviceID能够匹配到的


choose之前,ribbon还是有很多工作要做的,再细点,就得研究源码了,我..........




三、service-ribbon创建 ---配置eureka客户端参数



(1)application.properties


server.port=8033
#当前项目也是一个服务提供者,给自身的serviceID起名
spring.application.name=service-ribbon
#指定eureka服务注册发现中心的访问地址
eureka.client.service-url.defaultZone=http://localhost:8011/eureka/



四、service-ribbon创建 ---创建service,实现负载均衡



(1)HelloService.java


package com.appleyk.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class HelloService {

	
	@Autowired
	private RestTemplate restTemplate;
	
	public String hiService(){
		/**
		 * restTemplate:简化了发起HTTP请求以及处理响应的过程,并且支持REST
		 * get请求
		 * getForObject(方法重载)
		 * 第一个参数:string url -- 格式 :  ..//eureka服务名称/RequestMapping....
		 * 第一个参数:支持字符串占位符 比如  ...//HELLO-SERVICE/hello/{name}/{age},name 和 age 都可以被替换成等价的变量
		 * 第二个参数:返回数据的类型
		 */
		return restTemplate.getForObject("http://HELLO-SERVICE/hello", String.class);
	}
}







由于我们在Spring-Boot的application.java里面开启了ribbon的客户端负载均衡功能(使用注解@LoadBalanced自动实现),因此,上述请求的地址,表面上看不合理,因为我们知道eureka服务注册中心有两个名称为“HELLO-SERVICE”的服务实例,但是不用担心,ribbon会帮我们选择一个进行请求,不信的话,我们继续往下走....





五、service-ribbon创建 ---创建Controller



(1)HelloController.java


package com.appleyk.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.appleyk.service.HelloService;

/**
 * @author yukun24@126.com
 * @blob   http://blog.csdn.net/appleyk
 * @date   2018年2月9日-下午4:38:26
 */
@RestController
public class HelloController {

	@Autowired
    HelloService helloService;
	
	
	@Autowired
	private LoadBalancerClient loadBalancerClient;
	
    @RequestMapping(value = "/hello")
    public String hi(){
        return helloService.hiService();
    }
    
    @RequestMapping("/service/get")
    public String GetService(){
    	ServiceInstance serviceInstance = loadBalancerClient.choose("hello-service");
    	String info = "猜猜我是哪个服务:"+serviceInstance.getHost()+":"+serviceInstance.getPort();
    	System.err.println(info);
    	return info;
    }
    
    

}


(2)





至此,一切就绪(eureka-server、eureka-client、service-ribbon),只差run






六、启动eureka-server



(1)






(2)浏览器访问eureka中心


目前,中心只有一个服务实例(Port:8080),部署在本机的虚拟机下







七、启动本地eureka-client



(1)





(2)刷新eureka服务注册中心






八、启动service-ribbon




(1)注意service-ribbon本身也是一个服务提供者






(2)因此,eureka服务注册中心的服务实例列表里也有我们刚刚注册的service-ribbon







九、利用LoadBalancerClient实例测试服务选择



(1)





(2) 测试工具Insomnia测试



A.






B.第一次







C.第二次





下面再调用,就是服务A和服务B的交替出现了,不再做演示




十、ribbon登场,隐式开启负载均衡功能




(1)







(2) 测试工具Insomnia测试






A.第一次







B.第二次







下面再调用,就是服务A和服务B的交替出现了,不再做演示



结束语

坚持写博客,你会发现,你善于搜集资料了,你善于思考了,你也善于整理了,你变得对某项技术不再只局限于使用那么简单了,你渴望去了解它、并用自己的理解去阐述它甚至还有种想要扒开源码一探究竟的欲望,只奈自身能力有限,暂时扒不动也没有足够的时间去细细研究,还是,多读书多学习吧!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值