1、概念:Ribbon 负载均衡

2、具体内容

现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册的目的是希望所有的服务都统一归属到 Eureka 之中进 行处理,但是现在的问题,所有的微服务汇集到了 Eureka 之中,而客户端的调用也应该通过 Eureka 完成。而这种调用就可以利用 Ribbon 技术来实现。

Ribbon 是一个服务调用的组件,并且是一个客户端实现负载均衡处理的组件。服务器端实现负载均衡可以使用 Nginx、 HAProxy、LVS 等。

2.1、Ribbon 基本使用

1、 【microcloud-consumer-80】修改 pom.xml 配置文件,追加 Ribbon 相关依赖支持包:

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

2、 【microcloud-consumer-80】修改 RestConfig 配置类,在获取 RestTemplate 对象的时候加入 Ribbon 的配置注解@LoadBalanced。

package cn.study.microcloud.config;

import java.nio.charset.Charset;
import java.util.Base64; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate; @Configuration
public class RestConfig {
@Bean
public HttpHeaders getHeaders() { // 要进行一个Http头信息配置
HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息
String auth = "studyjava:hello"; // 认证的原始信息
byte[] encodedAuth = Base64.getEncoder()
.encode(auth.getBytes(Charset.forName("US-ASCII"))); // 进行一个加密的处理
// 在进行授权的头信息内容配置的时候加密的信息一定要与“Basic”之间有一个空格
String authHeader = "Basic " + new String(encodedAuth);
headers.set("Authorization", authHeader);
return headers;
} @Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

3、 【microcloud-consumer-80】修改 aplication.yml 配置文件,追加 Eureka 的服务注册地址配置。

server:
port: 80 eureka:
client:
register-with-eureka: false #客户端不注册到eureka,只是进行服务的调用
service-url:
defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka

4、 【microcloud-consumer-80】修改项目的启动类,追加 Eureka 客户端的配置注解:

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class Consumer_80_StartSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,
args);
}
}

5、 【microcloud-consumer-80】修改控制器调用类;

· 现在在 eureka 之中注册的所有服务的名称都是大写字母:MICROCLOUD-PROVIDER-DEPT;

package cn.study.microcloud.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import cn.study.vo.Dept; @RestController
public class ConsumerDeptController {
public static final String DEPT_GET_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/get/";
public static final String DEPT_LIST_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/list/";
public static final String DEPT_ADD_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/add?dname=";
@Resource
private RestTemplate restTemplate;
@Resource
private HttpHeaders headers;
@RequestMapping(value = "/consumer/dept/get")
public Object getDept(long id) {
Dept dept = this.restTemplate
.exchange(DEPT_GET_URL + id, HttpMethod.GET,
new HttpEntity<Object>(this.headers), Dept.class)
.getBody();
return dept;
}
@SuppressWarnings("unchecked")
@RequestMapping(value = "/consumer/dept/list")
public Object listDept() {
List<Dept> allDepts = this.restTemplate
.exchange(DEPT_LIST_URL, HttpMethod.GET,
new HttpEntity<Object>(this.headers), List.class)
.getBody();
return allDepts;
}
@RequestMapping(value = "/consumer/dept/add")
public Object addDept(Dept dept) throws Exception {
Boolean flag = this.restTemplate.exchange(DEPT_ADD_URL, HttpMethod.POST,
new HttpEntity<Object>(dept, this.headers), Boolean.class)
.getBody();
return flag;
}
}

访问地址:http://client.com/consumer/dept/list。这个时候有了 Ribbon 与 Eureka 整合之后用户不再去关注具体的 Rest 服务的地 址与端口号了,所有的信息获取都通过 Eureka 完成。

 2.2、Ribbon 负载均衡

通过上面的代码可以发现在 Ribbon 里面有一个负载均衡的注解:@LoadBalanced,那么就意味着现在就可以实现负载均衡的处理了。ribbon负载均衡的原理图如下

所有的服务都注册到eureka中心,并且都是同一个名字microcloud-provider-dept,用户通过eureka找到服务microcloud-provider-dept,然后通过ribbon负载均衡进行调用

1、 【microcloud-provider-dept-8001】将此项目复制为两份“microcloud-provider-dept-8002”、 “microcloud-provider-dept-8003”;

2、 【microcloud-provider-dept-*】执行各自的数据库脚本,随后修改各自的数据库连接配置;

3、 【microcloud-provider-dept-*】修改各自服务的 application.yml 配置文件;

server:
port: 8001 eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: dept-8001.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址 info:
app.name: study-microcloud
company.name: www.study.cn
build.artifactId: $project.artifactId$
build.version: $project.verson$ mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: cn.study.vo # 定义所有操作类的别名所在包
mapper-locations: # 所有的mapper映射文件
- classpath:mybatis/mapper/**/*.xml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 配置当前要使用的数据源的操作类型
driver-class-name: org.gjt.mm.mysql.Driver # 配置MySQL的驱动程序类
url: jdbc:mysql://localhost:3306/study8001 # 数据库连接地址
username: root # 数据库用户名
password: mysqladmin # 数据库连接密码
dbcp2: # 进行数据库连接池的配置
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化提供的连接数
max-total: 5 # 最大的连接数
max-wait-millis: 200 # 等待连接获取的最大超时时间
application:
name: microcloud-provider-dept

 千万记住,现在所有的服务名字一定要保持一致,如果不一致则会认为是两个服务,无法进行负载均衡。

4、 修改项目中的 hosts 配置文件,在这个配置文件之中追加新的域名:

127.0.0.1 dept-8001.com
127.0.0.1 dept-8002.com
127.0.0.1 dept-8003.com

5、 【microcloud-provider-dept-*】在保证 Eureka 已经正确启动之后启动所有的部门微服务信息;

6、 【microcloud-consumer】启动消费端,消费端在 RestTemplate 配置的时候使用了负载均衡的注解。

· 访问地址:http://client.com/consumer/dept/list;

现在发现每一次获取数据都是通过不同的微服务获得的,所以现在同一个消费端就可以通过 Ribbon 实现了负载均衡配置处理。

 2.3、自定义 Ribbon 配置

在之前使用了一个“@LoadBalanced”注解,该注解描述的是一个负载均衡,但是对于负载均衡也是可以由用户修改负载均衡策略的。那么如果说现在要想去修改这样的策略,也是可以的,可以使用自定义的 LoadBalacne 的配置类。

1、 【microcloud-consumer-80】追加一个 LoadBalance 的配置类,这个类应该放在 SpringCloud 启动后找不到的位置上,所以应该 做一个新的包;

package cn.study.commons.config;

import org.springframework.context.annotation.Bean;

import com.netflix.loadbalancer.IRule;

public class MyLoadBalanceConfig {
@Bean
public IRule ribbonRule() { // 其中IRule就是所有规则的标准
return new com.netflix.loadbalancer.RandomRule() ;
}
}

2、 【microcloud-consumer-80】修改程序主类,追加 Ribbon 的配置操作:

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient; import cn.study.commons.config.MyLoadBalanceConfig;
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name="ribbonClient",configuration=MyLoadBalanceConfig.class)
public class Consumer_80_StartSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,
args);
}
}

那么此时就实现了负载均衡的配置处理操作。

3、 【microcloud-consumer-80】修改控制器程序类,在这个程序类之中可以通过负载均衡的客户端获取服务器的相关信息。

package cn.study.microcloud.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import cn.study.vo.Dept; @RestController
public class ConsumerDeptController {
public static final String DEPT_GET_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/get/";
public static final String DEPT_LIST_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/list/";
public static final String DEPT_ADD_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/add?dname=";
@Resource
private RestTemplate restTemplate;
@Resource
private HttpHeaders headers;
@Resource
private LoadBalancerClient loadBalancerClient ;
@RequestMapping(value = "/consumer/dept/get")
public Object getDept(long id) {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("MICROCLOUD-PROVIDER-DEPT") ;
System.out.println(
"【*** ServiceInstance ***】host = " + serviceInstance.getHost()
+ "、port = " + serviceInstance.getPort()
+ "、serviceId = " + serviceInstance.getServiceId());
Dept dept = this.restTemplate
.exchange(DEPT_GET_URL + id, HttpMethod.GET,
new HttpEntity<Object>(this.headers), Dept.class)
.getBody();
return dept;
} }

那么此时后台通过指定的负载均衡的配置程序,就可以取得即将操作的主机的信息。

 2.4、禁用 Eureka 实现 Ribbon 调用

在之前使用的技术都是通过 Eureka 访问了 Eureka 之中的指定名称的服务而获得了所需要的数据,但是在 Ribbon 设计的时候 考虑到了一个脱离 Eureka 使用的环境。如果要真进行了 Eureka 的脱离,代码将变为如下的形式。

1、 【microcloud-consumer-ribbon】修改 application.yml 配置文件:

server:
port: 80 ribbon:
eureka:
enabled: false microcloud-provider-dept:
ribbon:
listOfServers: http://dept-8001.com:8001,http://dept-8002.com:8002,http://dept-8003.com:8003

2、 【microcloud-consumer-ribbon】修改 RestConfig 配置程序类,不再需要使用“@LoadBalanced”注解:

package cn.study.microcloud.config;

import java.nio.charset.Charset;
import java.util.Base64; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate; @Configuration
public class RestConfig {
@Bean
public HttpHeaders getHeaders() { // 要进行一个Http头信息配置
HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息
String auth = "studyjava:hello"; // 认证的原始信息
byte[] encodedAuth = Base64.getEncoder()
.encode(auth.getBytes(Charset.forName("US-ASCII"))); // 进行一个加密的处理
// 在进行授权的头信息内容配置的时候加密的信息一定要与“Basic”之间有一个空格
String authHeader = "Basic " + new String(encodedAuth);
headers.set("Authorization", authHeader);
return headers;
} @Bean
// @LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

3、 【microcloud-consumer-ribbon】修改 ConsumerDeptController控制器,直接通过获取主机和端口调用后台微服务:

package cn.study.microcloud.controller;

import java.net.URI;

import javax.annotation.Resource;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import cn.study.commons.config.MyLoadBalanceConfig;
import cn.study.vo.Dept; @RestController
@RibbonClient(name = "microcloud-provider-dept", configuration = MyLoadBalanceConfig.class)
public class ConsumerDeptController {
public static final String DEPT_REST_TOPIC = "microcloud-provider-dept";
@Resource
private RestTemplate restTemplate;
@Resource
private HttpHeaders headers;
@Resource
private LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/consumer/dept/get")
public Object getDept(long id) {
ServiceInstance serviceInstance = this.loadBalancerClient
.choose(DEPT_REST_TOPIC);
System.out.println(
"【*** ServiceInstance ***】host = " + serviceInstance.getHost()
+ "、port = " + serviceInstance.getPort()
+ "、serviceId = " + serviceInstance.getServiceId()
+ "、uri = " + serviceInstance.getUri());
URI deptUri = URI.create(String.format("http://%s:%s/dept/get/" + id,
serviceInstance.getHost(), serviceInstance.getPort()));
Dept dept = this.restTemplate
.exchange(deptUri, HttpMethod.GET,
new HttpEntity<Object>(this.headers), Dept.class)
.getBody();
return dept;
}
}

这种模式并不标准,只能够说是 Ribbon 自己所具备的一项功能而已,实际之中如果不是非常必要,不建议使用。

 

SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)的更多相关文章

  1. springcloud系列五 feign远程调用服务

    一:Feign简介 Feign 是一种声明式.模板化的 HTTP 客户端,在 Spring Cloud 中使用 Feign,可以做到使用 HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完 ...

  2. SpringCloud系列五:为Eureka Server添加用户认证及元数据

    1. 回顾 上一篇博客讲解了Eureka集群及将微服务注册到集群上.在前面的讲解中,Eureka Server都是允许匿名访问的,本次将讲解如何构建一个需要登录才能访问的Eureka Server. ...

  3. Mysql系列五:数据库分库分表中间件mycat的安装和mycat配置详解

    一.mycat的安装 环境准备:准备一台虚拟机192.168.152.128 1. 下载mycat cd /softwarewget http:-linux.tar.gz 2. 解压mycat tar ...

  4. SpringCloud系列十:使用Feign实现声明式REST调用

    1. 回顾 前文的示例中是使用RestTemplate实现REST API调用的,代码大致如下: @GetMapping("/user/{id}") public User fin ...

  5. VSTO之旅系列(五):创建Outlook解决方案

    原文:VSTO之旅系列(五):创建Outlook解决方案 本专题概要 引言 Outlook对象模型 自定义Outlook窗体 小结 一.引言 在上一个专题中,为大家简单介绍了下如何创建Word解决方案 ...

  6. SpringCloud系列——Ribbon 负载均衡

    前言 Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制.我们在上篇(猛戳:SpringCloud系列——Feign 服务调用)已经实现了多个服务之间的Feign调用 ...

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

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

  8. SpringCloud系列七:使用Ribbon实现客户端侧负载均衡

    1. 回顾 在前面,已经实现了微服务的注册与发现.启动各个微服务时,Eureka Client会把自己的网络信息注册到Eureka Server上. 但是,在生成环境中,各个微服务都会部署多个实例,因 ...

  9. SpringCloud学习笔记(8)----Spring Cloud Netflix之负载均衡-Ribbon的负载均衡的策略

    一. 内置 负载均衡策略的介绍的 IRule的实现类 2. 通过代码实现负载均衡 在第六节Riddom的使用的工程中,随机策略配置类 package com.wangx.cloud.springclo ...

随机推荐

  1. eclipse运行无错的ssm项目,迁移到idea出错

    我的报错信息为mapper绑定相关错误,是因为idea在构建项目时,target/classes目录下不存在mapper.xml文件 解决方法: <!-- 在maven中添加以下配置,它的父标签 ...

  2. usg6000

    USG6000密码恢复 1.如果某个管理员遗忘了密码,可以使用其它高权限的管理员账号登录设备,然后修改密码.例如,管理员admin1的密码遗忘,此时可以由管理员admin登录设备,然后修改admin1 ...

  3. Spark:DataFrame批量导入Hbase的两种方式(HFile、Hive)

    Spark处理后的结果数据resultDataFrame可以有多种存储介质,比较常见是存储为文件.关系型数据库,非关系行数据库. 各种方式有各自的特点,对于海量数据而言,如果想要达到实时查询的目的,使 ...

  4. How to run Python code from Sublime

    How to run Python Code from Sublime,and How to run Python Code with input from sublime Using Sublime ...

  5. 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?

    https://blog.csdn.net/Iperishing/article/details/86674084

  6. 命令生成所有数据库表模型以及 CRUD

    将下列代码写到文件复制到项目 console\controller 目录下: <?php namespace console\controllers; use Yii; use yii\cons ...

  7. QCAD 修改默认的线宽

    QCAD 修改默认的线宽 默认的宽度实在是太宽了,把一些细节给掩盖了. 可以按以下方法找到修改默认宽度. 在 Layer -> Edit Layer 中. 最开始找了好久好久. 最开始在这里找了 ...

  8. 左耳听风-ARTS-第1周

    Algorithm https://leetcode.com/problems/longest-common-prefix/ class Solution { public String longes ...

  9. TCP连接异常:broken pipe 和EOF

    本文介绍3种TCP连接异常的情况. 1.server端没有启动,client尝试连接 ./client dial failed: dial tcp 127.0.0.1:8080: connect: c ...

  10. Go外包 Go语言外包 Golang外包商 浅谈Go的全局变量和生命周期

    最近做Go语言开发,有些心得分享下: Go语言全局var不同于PHP里的全局var,最大区别session 还是app,app 所有人都可以改.session自己改.不同过程之间通用   比如我php ...