SpringCloud学习之路(四)-Ribbon负载均衡

本文介绍如何使用Ribbon实现客户端负载均衡,包括配置Eureka服务发现、自定义负载均衡策略及脱离Eureka独立使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Ribbon是客户端实现负载均衡的一个组件,所以我们修改的是microcloud-consumer-80的相关配置,首先pom.xml追加相关Ribbon依赖以及Eureka服务相关依赖。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.jmx</groupId>
    <artifactId>microcloud</artifactId>
    <version>0.0.1</version>
  </parent>
  <artifactId>microcloud-consumer-80</artifactId>
  <name>microcloud-consumer-80</name>
  <url>http://maven.apache.org</url>
	<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  	</properties>
 	<dependencies>
 	  <!-- Eureka服务-->
 	    <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>
 	<!--客户端负载均衡Ribbon依赖包 -->
		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>com.jmx</groupId>
			<artifactId>microcloud-api</artifactId>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jetty</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>
</project>

修改application.yml,添加Eureka注册发现配置

server:
  port: 80
  
eureka:
  client:                      #客户端进行Eureka注册发现的配置
    register-with-eureka: false #该服务不能注册在Eureka注册中心
    service-url:
      defaultZone: http://edmin:jmxhello@eureka-7001.com:7001/eureka/,http://edmin:jmxhello@eureka-7002.com:7002/eureka/,http://edmin:jmxhello@eureka-7003.com:7003/eureka/
    

然后在启动类Consumer_80_StartSpringCloudApplication.java上添加Eureka客户端注解

package com.jmx.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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);
	}
}

修改RestConfig.java中Rest实现负载均衡Ribbon注解

package com.jmx.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
	//实现客户端负载均衡Ribbon
        @LoadBalanced
	public RestTemplate getRestTemplate() {
		return new RestTemplate() ;
	}
	
	//定义一个Bean修改头信息进行客户端认证
	@Bean
	public HttpHeaders getHeader() {
	    HttpHeaders headers=new HttpHeaders();
	    String auth="jmxjava:jmxhello";//认证的原始信息
	    byte[] encodeAuth=Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));//将原始认证信息进行Base64加密
	    String authHeader="Basic "+new String(encodeAuth);//加密后的认证信息要与Basic有个空格
	    headers.set("Authorization", authHeader);
	    return headers;
	}
}

最后修改控制层ConsumerDeptController.java,把原来的主机地址换成我们microcloud-provider-dept-8001的微服务在Eureka注册中心的微服务名。

package com.jmx.microcloud.controller;
import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
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 com.jmx.vo.Dept;



@RestController
public class ConsumerDeptController {
	public static final String DEPT_GET_URL = "http://PROVIDER-8001/dept/get/";
	public static final String DEPT_LIST_URL = "http://PROVIDER-8001/dept/list/";
	public static final String DEPT_ADD_URL = "http://PROVIDER-8001/dept/add";
	@Autowired
	private RestTemplate restTemplate;
	
	@Autowired
	private HttpHeaders headers;
	
	
	@RequestMapping(value = "/consumer/dept/get")
	public Dept getDept(long id) {
		Dept dept = restTemplate.exchange(DEPT_GET_URL+id, HttpMethod.GET,new HttpEntity<Object>(headers),Dept.class).getBody();
		return dept;
	}
	
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/consumer/dept/list")
	public List<Dept> listDept() {
		List<Dept> allDepts = restTemplate.exchange(DEPT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(headers),List.class).getBody();
		return allDepts;
	}
	@RequestMapping(value = "/consumer/dept/add")
	public boolean addDept(Dept dept) {
		Boolean flag = restTemplate.exchange(DEPT_ADD_URL,HttpMethod.POST,new HttpEntity<Object>(dept,headers),Boolean.class).getBody();
		return flag;
	}
}

接下来启动三个Eureka注册中心(microcloud-eureka-7001、microcloud-eureka-7002、microcloud-eureka-7003)、微服务(microcloud-provider-dept-8001)以及我们的客户端(microcloud-consumer-80)一共5个服务。全部启动完成后,打开浏览器输入http://client.com/consumer/dept/list


我们现在已经不在关注微服务所在的地址了直接从Eureka注册中心获取微服务名字直接调用就行,我们不在需要关注微服务所在的地址了.

2.Ribbon模拟实现负载均衡,将我们的微服务(microcloud-provider-dept-8001)复制2份(microcloud-provider-dept-8002、microcloud-provider-dept-8003)并分别执行不同的数据库脚本。分别修改pom.xml、各个Springboot启动类、application.yml以及相关数据库创建


microcloud-provider-dept-8002:

application.yml

server:
  port: 8002
  
eureka:
  client:         #客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://edmin:jmxhello@eureka-7001.com:7001/eureka/,http://edmin:jmxhello@eureka-7002.com:7002/eureka/,http://edmin:jmxhello@eureka-7003.com:7003/eureka/
  instance:
    lease-expiration-duration-in-seconds: 5 #设置心跳的周期间隔(默认90s)[如果5s没响应默认服务宕机]
    lease-renewal-interval-in-seconds: 2  #设置心跳时间间隔(默认30s)
    instance-id: dept-8002.com    #在信息列表时显示主机名称
    prefer-ip-address: true       #访问路径变为IP地址
    
info:
  app.name: jmx-microcloud
  company.name: www.52jmx.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$
  
  
  
  
  
mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml    # mybatis配置文件所在路径
  type-aliases-package: com.jmx.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:3307/jmx8002?useUnicode=true&characterEncoding=utf-8       # 数据库连接地址
    username: root                                  # 数据库用户名
    password: 123456                                # 数据库连接密码
    dbcp2:                                          # 进行数据库连接池的配置
      min-idle: 5                                   # 数据库连接池的最小维持连接数    
      initial-size: 5                               # 初始化提供的连接数
      max-total: 5                                  # 最大的连接数
      max-wait-millis: 200                          # 等待连接获取的最大超时时间
  application:                                      
    name: provider-8001                             # Eureka注册中心服务名

microcloud-provider-dept-8003:

application.yml

server:
  port: 8003
  
eureka:
  client:         #客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://edmin:jmxhello@eureka-7001.com:7001/eureka/,http://edmin:jmxhello@eureka-7002.com:7002/eureka/,http://edmin:jmxhello@eureka-7003.com:7003/eureka/
  instance:
    lease-expiration-duration-in-seconds: 5 #设置心跳的周期间隔(默认90s)[如果5s没响应默认服务宕机]
    lease-renewal-interval-in-seconds: 2  #设置心跳时间间隔(默认30s)
    instance-id: dept-8003.com    #在信息列表时显示主机名称
    prefer-ip-address: true       #访问路径变为IP地址
    
info:
  app.name: jmx-microcloud
  company.name: www.52jmx.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$
  
  
  
  
  
mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml    # mybatis配置文件所在路径
  type-aliases-package: com.jmx.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:3307/jmx8003?useUnicode=true&characterEncoding=utf-8       # 数据库连接地址
    username: root                                  # 数据库用户名
    password: 123456                                # 数据库连接密码
    dbcp2:                                          # 进行数据库连接池的配置
      min-idle: 5                                   # 数据库连接池的最小维持连接数    
      initial-size: 5                               # 初始化提供的连接数
      max-total: 5                                  # 最大的连接数
      max-wait-millis: 200                          # 等待连接获取的最大超时时间
  application:                                      
    name: provider-8001                             # Eureka注册中心服务名

接下来修改C:\Windows\System32\drivers\etc路径下的hosts最后添加两个地址用于模拟多个微服务的IP

127.0.0.1   dept-8001.com   #微服务端Ribbon负载均衡-0
127.0.0.1   dept-8002.com   #微服务端Ribbon负载均衡-1
127.0.0.1   dept-8003.com   #微服务端Ribbon负载均衡-2
127.0.0.1   client.com      #消费端 
127.0.0.1   eureka-7001.com #Eureka注册中心的集群-0
127.0.0.1   eureka-7002.com #Eureka注册中心的集群-1
127.0.0.1   eureka-7003.com #Eureka注册中心的集群-2

启动所有微服务服务以及Eureka注册中心,测试一下我们的微服务有没有作用



启动客户端microcloud-consumer-80



注意看我们的loc是不同的数据库所以我们实现了负载均衡

3.启用属于我们自己的自定义的Ribbon配置,写一个属于我们自己的Ribbon配置类


MyLoadBalanceConfig.java

package com.jmx.commons.config;
/**
 * 自定义Ribbon类,应该避免被我们的启动类扫描到,所以我们放在新包里
 * @author JMX
 *
 */

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();//随机的访问策略
	
    }

}

修改我们的启动类Consumer_80_StartSpringCloudApplication.java

package com.jmx.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

import com.jmx.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);
	}
}

修改我们的控制层ConsumerDeptController.java

package com.jmx.microcloud.controller;
import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
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 com.jmx.vo.Dept;



@RestController
public class ConsumerDeptController {
	public static final String DEPT_GET_URL = "http://PROVIDER-8001/dept/get/";
	public static final String DEPT_LIST_URL = "http://PROVIDER-8001/dept/list/";
	public static final String DEPT_ADD_URL = "http://PROVIDER-8001/dept/add";
	@Autowired
	private RestTemplate restTemplate;
	
	@Autowired
	private HttpHeaders headers;
	
	@Autowired
	private LoadBalancerClient loadBalancerClient;
	
	
	@RequestMapping(value = "/consumer/dept/get")
	public Dept getDept(long id) {
	      ServiceInstance serviceInstance=this.loadBalancerClient.choose("PROVIDER-8001");
	      System.out.print("【**ServiceInstance**】host="+serviceInstance.getHost()+"、post="+serviceInstance.getPort()+"、serviceId="+serviceInstance.getServiceId());
		Dept dept = restTemplate.exchange(DEPT_GET_URL+id, HttpMethod.GET,new HttpEntity<Object>(headers),Dept.class).getBody();
		return dept;
	}
	
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/consumer/dept/list")
	public List<Dept> listDept() {
		List<Dept> allDepts = restTemplate.exchange(DEPT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(headers),List.class).getBody();
		return allDepts;
	}
	@RequestMapping(value = "/consumer/dept/add")
	public boolean addDept(Dept dept) {
		Boolean flag = restTemplate.exchange(DEPT_ADD_URL,HttpMethod.POST,new HttpEntity<Object>(dept,headers),Boolean.class).getBody();
		return flag;
	}
}

启动微服务以及Eureka注册中心还有我们的客户端,打开浏览器http://client.com/consumer/dept/get?id=2刷新控制台打印


4.脱离Eureka注册中心使用Ribbon进行客户端负载均衡,将microcloud-consumer-80复制一份改名为microcloud-consumer-ribbon,修改所有关于Eureka的配置,启动类Consumer_80_StartSpringCloudApplication.java,RestConfig.java,ConsumerDeptController.java,application.yml。

Consumer_80_StartSpringCloudApplication.java

package com.jmx.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Consumer_80_StartSpringCloudApplication {
	public static void main(String[] args) {
		SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,
				args);
	}
}

RestConfig.java

public class RestConfig {
	@Bean
	//实现客户端负载均衡Ribbon
        //@LoadBalanced
	public RestTemplate getRestTemplate() {
		return new RestTemplate() ;
	}
	
	//定义一个Bean修改头信息进行客户端认证
	@Bean
	public HttpHeaders getHeader() {
	    HttpHeaders headers=new HttpHeaders();
	    String auth="jmxjava:jmxhello";//认证的原始信息
	    byte[] encodeAuth=Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));//将原始认证信息进行Base64加密
	    String authHeader="Basic "+new String(encodeAuth);//加密后的认证信息要与Basic有个空格
	    headers.set("Authorization", authHeader);
	    return headers;
	}
}

ConsumerDeptController.java

package com.jmx.microcloud.controller;
import java.net.URI;
import org.springframework.beans.factory.annotation.Autowired;
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 com.jmx.commons.config.MyLoadBalanceConfig;
import com.jmx.vo.Dept;



@RestController
@RibbonClient(name="provider-8001",configuration=MyLoadBalanceConfig.class)
public class ConsumerDeptController {
	public static final String DEPT_REST_TOPIC = "provider-8001";
	
	@Autowired
	private RestTemplate restTemplate;
	

	@Autowired
	private HttpHeaders headers;
	
	@Autowired
	private LoadBalancerClient loadBalancerClient;
	
	
	@RequestMapping(value = "/consumer/dept/get")
	public Dept getDept(long id) {
	      ServiceInstance serviceInstance=this.loadBalancerClient.choose(DEPT_REST_TOPIC);
	      System.out.println("【**ServiceInstance**】host="+serviceInstance.getHost()+"、post="+serviceInstance.getPort()+"、serviceId="+serviceInstance.getServiceId()+"、Uri="+serviceInstance.getUri());
	      URI deptUrl=URI.create(String.format("http://%s:%s/dept/get/"+id,serviceInstance.getHost(),serviceInstance.getPort()));
	       System.out.println("【**DeptUrl**】="+deptUrl);
	      Dept dept =this.restTemplate.exchange(deptUrl, HttpMethod.GET,new HttpEntity<Object>(headers),Dept.class).getBody();
		return dept;
	}
}

application.yml

server:
  port: 80

ribbon:
  eureka:
   enabled: false

provider-8001:
  ribbon:
    listOfServers: http://dept-8001.com:8001,http://dept-8002.com:8002,http://dept-8003.com:8003

启动所有微服务以及microcloud-consumer-ribbon这个客户端,浏览器输入http://client.com/consumer/dept/get?id=1,我们查看控制台。


可以看见,我们Ribbon负载均衡脱离了Eureka注册中心一样可以实现客户端的负载均衡。

项目Demo:点我下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值