一、什么是    ribbon?

        就是负载均衡!
nginx也是负载均衡 1.1 !!!!ribbon和nginx的区别是什么?
/* nginx:
正向代理(和客户端连在一起)
反向代理(和服务器端连在一起),nginx的负载均衡其实使用的就是反向代理 ribbon:
负载均衡是和客户端连在一起的,也就是说ribbon是客户端层面的负载均衡
负载均衡放在客户端的好处是什么?
可以让客户端非常直观的看到所有服务器的负载情况,
那么客户端一般情况下会选择负载比较少的服务器进行连接(选择游戏大区)
*/

二、consumer 开启负载均衡的配置

1.2 ribbon默认自带的有eureka的jar包,也就是如果需要使用ribbon的时候就必须要配置eureka,

            也就是说需要把自己托管给eureka,ribbon是客户端层面的负载均衡,那么ribbon是配置在consumer中还是provider中?
必须要配置在consumer上 /*
将 20190927-springcloud-consumer-6081 项目的jar包放在父级目录上,做jar包管理。
我的放在 新建项目 20190927-springcloud-consumer-ribbon-6082 做负载均衡。和另一项目一样,需要创建启动类,和配置文件。 */ 1.3 添加jar包
添加eureka的client端,ribbon的jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

  20190927-springcloud-consumer-management  父级jar包展示。

<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>20190927-springcloud-parent</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>20190927-springcloud-consumer-management</artifactId> <packaging>pom</packaging> <modules>
<module>20190927-springcloud-consumer-6081</module>
<module>20190927-springcloud-consumer-ribbon-6082</module>
</modules> <!--
消费者 依赖于 model 和页面交互
在20190927-springcloud-consumer-management项目下,建立多个子级项目,可以将这里的jar包直接放在
父级的项目的xml文件中。 我的放在这里 没有生效,还是在子级项目上添加的jar 包依赖。
--> <dependencies>
<dependency>
<groupId>com.aaa</groupId>
<artifactId>20190927-springcloud-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency> <!--
微服务,将 spring-boot-starter-web添加进来 需要修改默认的端口号。
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies> </project>
 20190927-springcloud-consumer-ribbon-6082 jar包依赖, 的配置文件,开启轮循,controller层。
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>20190927-springcloud-consumer-management</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <groupId>com.aaa</groupId>
<artifactId>20190927-springcloud-consumer-ribbon-6082</artifactId> <!--
添加jar包
添加eureka的client端,ribbon的jar包
--> <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency> <dependency>
<groupId>com.aaa</groupId>
<artifactId>20190927-springcloud-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency> <!--
微服务,将 spring-boot-starter-web添加进来 需要修改默认的端口号。
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies> </project>



1.配置文件
server.port=6082
server.servlet.context-path=/

#三、 设置eureka 不要将自己注册到注册中心里面。
eureka.client.register-with-eureka=false

# ribbon 负载均衡的配置,需要将自己分别在三个 eureka上去注册。
eureka.client.service-url.defaultZone=http://eureka01:7081/eureka,http://eureka02:7082/eureka,http://eureka03:7083/eureka
2.开启轮循
package com.aaa.zxf.config;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; @SpringBootApplication
public class ConfigRest { @Bean
@LoadBalanced //开启负载均衡 轮循的模式
public RestTemplate getRestTemplate(){
return new RestTemplate();
} }


3.controller层
package com.aaa.zxf.controller;

import com.aaa.zxf.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import java.util.List; @RestController
public class UserController { // private static final String URL = "http://USER-PROVIDER"; private static final String URL ="http://USER-PROVIDER"; @Autowired
private RestTemplate restTemplate; @RequestMapping("/userAll")
public List<User> selectAllUser(){
return restTemplate.getForObject(URL+"/userAll",List.class);
} }

三、provider 负载均衡的配置。


1.4 真正的负载均衡
需要创建provider-8082和8083项目 1.5 进行配置
8081,8082,8083三个项目中的所有的controller都必须要一致(@RequestMapping("/userAll"))

8081,8082,8083项目的application.properties配置文件必须要更改

【eureka的实例id:因为eureka的实例id是不能重复的,所以必须更改】
eureka.instance.instance-id=user-provider-8082

spring.application.name不能改变,也就是说8081,8082,8083三个项目的application.name都必须要一样 1.6 启动顺序
首先启动三台eureka(7081,7082,7083)
再启动三台provider(8081,8082,8083)
最后启动consumer(6082)

provider的配置文件,修改id  其他的都一样。从8081复制即可。

#四
#在eureka中配置实例, 就是eureka的status下显示的名字
# 不可以重复!!! 等同于mysql中表的id。
eureka.instance.instance-id=user-provider-8082

#四
#在eureka中配置实例, 就是eureka的status下显示的名字
# 不可以重复!!! 等同于mysql中表的id。
eureka.instance.instance-id=user-provider-8083
 

四、负载均衡的源码分析?
1.7 ribbon的负载均衡算法
如果不指定ribbon的算法,则ribbon使用的是轮询!!!
如何指定ribbon的算法? 1.8 负载均衡源码解析
IRule:接口
ILoadBalancer:接口
AbstractLoadBalancer(抽象类) --> 实现了ILoadBalancer接口
AbstractLoadBalancerRule(抽象类) --> 实现了IRule接口
有一个属性:ILoadBalance-->getter/setter方法
RandomRule(最终所实现随机算法的地方)--->继承了AbstractLoadBalancerRule
-->实现了IRule接口
RoundRobbinRule--->继承了AbstractLoadBalancerRule
-->实现了IRule接口 IRule:
public Server choose(Object key):选择出一个服务-->提供给consumer使用
public void setLoadBalancer(ILoadBalancer lb):ILoadBalancer-->实现类(AbstractLoadBalancer)
public ILoadBalancer getLoadBalancer()
ILoadBalancer:
!!其实就是和每一个服务打交道!!
getServer(Object key):所有的获取服务都必须要通过key来进行获取 虽然已经实现了ribbon算法自定义配置,但是ribbon框架是不知道的,但是自己已经实现了负载均衡算法,需要告诉ribbon,只需要在主启动类上添加注解@RibbonClient(name,configuration)
name:通过eureka的Application的值来映射到真正的provider(8081,8082,8083)
name = "USER-PROVIDER"
configuration:指向的是自己自定义的算法配置类 @Configuration
public class RibbonRuleMine { @Bean
public IRule randoms() {
return new RandomRule();
} }


算法?
package com.aaa.lee.springcloud.config;

import com.netflix.loadbalancer.ILoadBalancer;

import java.util.concurrent.ThreadLocalRandom;

public class Test {

    // 随机算法
public Server choose(ILoadBalancer lb, Object key) {
// 如果负载均衡器为null的时候,直接返回(其实就是标识了该consumer开启了负载均衡@LoadBalance)
if (lb == null) {
return null;
}
// 创建Server对象,没有初始化
Server server = null; // 循环进入条件是server为null-->也就是说第一次一定会进入循环
while (server == null) {
// Thread.interrupted():标识线程所处于的状态,如果线程的状态为存在,返回值就是true,如果不存在返回值就是false
// 什么时候线程会断开??-->网络故障,网络延迟,各种阻塞
if (Thread.interrupted()) {
return null;
}
// getReachableServers():获取当前正在存活的服务(一共有20个服务,其中有4个宕机,存活的服务就是16个)
// getAllServers():获取所有的服务个数(包含宕机的)
List<Server> upList = lb.getReachableServers();
List<Server> allList = lb.getAllServers(); // allList.size() == 0 说明没有服务,直接return null
int serverCount = allList.size();
if (serverCount == 0) {
return null;
} // serverCount:就是所有服务的个数(包含宕机的服务)
// 假设:30台
int index = chooseRandomInt(serverCount);
// upList:存活的服务
server = upList.get(index); if (server == null) { /**
* Thread.yield():线程谦让
* 什么叫多线程之间的谦让呢?
* 当并发出现的时候,线程和线程是互不相让的(线程阻塞),其中一个线程就会出现问题,就会处于等待状态(线程阻塞会更严重)
* 当调用yield()方法的时候,出现问题的线程就开始谦让,这个线程会再次被唤醒处于就绪状态,需要重新抢夺客户端所发送过来的并发
*/
Thread.yield();
continue;
} if (server.isAlive()) {
return (server);
} // Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
} return server; } protected int chooseRandomInt(int serverCount) {
// Math.random.nextInt(999):随机获取到从1到999的随机数
// ThreadLocalRandom.current().nextInt(30):就是获取的是随机数(从1到30进行随机数)
//
/*
* Random和ThreadLocalRandom都是随机数,那么为什么使用ThreadLocalRandom不使用Random?
* !!Random就是线程安全的!!
* ThreadLocalRandom:是jdk7的新特性!!
* 虽然random是线程安全的,但是在多线程的情况,Random效率就会非常低
* random在处理多线程的情况下是线程安全的,会受到线程保护,就会降低效率(队列)
* Random所随机出来的数字是可以预测的(Random有规律)
*
* TreadLocalRandom官方给出的解释,当项目期望在多线程中运行的时候,如果使用到了随机数,可以直接使用该类,因为该
* 类就是针对于并发所开发的,和Random相比TreadLocalRandom可以减少线程之间的竞争,性能可以达到最优!
*
*
*/
return ThreadLocalRandom.current().nextInt(serverCount);
} }

五、图解





springcloud 负载均衡之 ribbon。的更多相关文章

  1. SpringCloud系列之客户端负载均衡Netflix Ribbon

    1. 什么是负载均衡? 负载均衡是一种基础的网络服务,它的核心原理是按照指定的负载均衡算法,将请求分配到后端服务集群上,从而为系统提供并行处理和高可用的能力.提到负载均衡,你可能想到nginx.对于负 ...

  2. SpringCloud 客户端负载均衡:Ribbon

    目录 Ribbon 介绍 开启客户端负载均衡,简化 RestTemplate 调用 负载均衡策略 Ribbon 介绍 Ribbon 是 Netflix 提供的一个基于 Http 和 TCP 的客户端负 ...

  3. Spring Cloud之负载均衡组件Ribbon原理分析

    目录 前言 一个问题引发的思考 Ribbon的简单使用 Ribbon 原理分析 @LoadBalanced 注解 @Qualifier注解 LoadBalancerAutoConfiguration ...

  4. Spring Cloud官方文档中文版-客户端负载均衡:Ribbon

    官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#_spring_cloud_netflix 文中例子我做了一些测试在:h ...

  5. 【Spring Cloud】客户端负载均衡组件——Ribbon(三)

    一.负载均衡 负载均衡技术是提高系统可用性.缓解网络压力和处理能力扩容的重要手段之一. 负载均衡可以分为服务器负载均衡和客户端负载均衡,服务器负载均衡由服务器实现,客户端只需正常访问:客户端负载均衡技 ...

  6. 负载均衡框架 ribbon 二

    Ribbon 负载均衡机制 官方文档地址:https://github.com/Netflix/ribbon/wiki/Working-with-load-balancers 1. Ribbon 内置 ...

  7. SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)

    1.概念:Ribbon 负载均衡 2.具体内容 现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册的目的是希望所有的服务都统一归属到 Eureka 之中进 行处理,但是现 ...

  8. SpringCloud全家桶学习之客户端负载均衡及自定义负载均衡算法----Ribbon(三)

    一.Ribbon是什么? Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端  负载均衡的工具(这里区别于nginx的负载均衡).简单来说,Ribbon是Netf ...

  9. springCloud负载均衡Ribbon和Feign的区别

    1.什么是负载均衡: 负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据[均匀]分摊到多个操作单元上执行,负载均衡的关键在于[均匀]. 2.常见的负 ...

随机推荐

  1. 【LeetCode】647. Palindromic Substrings 解题报告(Python)

    [LeetCode]647. Palindromic Substrings 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/p ...

  2. 第四十个知识点 一般来说SPA和DPA的区别是什么

    第四十个知识点 一般来说SPA和DPA的区别是什么 原文地址:http://bristolcrypto.blogspot.com/2015/07/52-things-number-40-what-is ...

  3. spring boot 使用 mybatis 开启事务回滚 的总结

    1.前言 以前没有使用mybatis,可以关闭自动提交,然后做sql操作,对操作进行catch捕获异常, 如果没有异常则commit 提交 ,有异常则 rollback 回滚,新增的数据则删除 ,修改 ...

  4. Go语言系列之函数

    函数是组织好的.可重复使用的.用于执行指定任务的代码块.本文介绍了Go语言中函数的相关内容. 函数 Go语言中支持函数.匿名函数和闭包,并且函数在Go语言中属于"一等公民". 函数 ...

  5. Go语言系列之time

    time包是go语言的内置库,提供了时间的显示和测量用的函数.日历的计算采用的是公历. 一.时间类型 time.Time类型表示时间.我们可以通过time.Now()函数获取当前的时间对象,然后获取时 ...

  6. 微服务架构攀登之路(三)之gRPC入门

    一.gRPC入门 1. gRPC 简介 gRPC 由 google 开发,是一款语言中立.平台中立.开源的远程过程调用系统 gRPC 客户端和服务端可以在多种环境中运行和交互,例如用 java 写一个 ...

  7. vue爬坑之路(插件安装)

    npm install vue-table-with-tree-grid --save import ZkTable from 'vue-table-with-tree-grid' Vue.use(Z ...

  8. css编写规则BEM

    简单来说,格式如下: .block { /* styles */ } .block__element { /* styles */ } .block--modifier { /* styles */ ...

  9. js对象数组多字段排序

    来源:js对象数组按照多个字段进行排序 一.数组排序 Array.sort()方法可以传入一个函数作为参数,然后依据该函数的逻辑,进行数组的排序. 一般用法:(数组元素从小大进行排序) var a = ...

  10. Kotlin 协程一 —— 全面了解 Kotlin 协程

    一.协程的一些前置知识 1.1 进程和线程 1.1.1基本定义 1.1.2为什么要有线程 1.1.3 进程与线程的区别 1.2 协作式与抢占式 1.2.1 协作式 1.2.2 抢占式 1.3 协程 二 ...