Java Spring Cloud:(三)Spring Cloud Netflix Ribbon-8800字匠心出品

1.Ribbon 简介

  • Ribbon 是一个基于 Http 和 TCP 的客服端负载均衡工具,它是基于 Netflix Ribbon 实现的。它不像 spring cloud 服务注册中心、配置中心、API 网关那样独立部署,但是它几乎存在于每个 spring cloud 微服务中。
  • 包括 feign 提供的声明式服务调用也是基于该 Ribbon 实现的。Ribbon 默认提供很多种负载均衡算法,例如 轮询、随机 等等。甚至包含自定义的负载均衡算法。Ribbon 可以用于解决并提供微服务的负载均衡的问题。

2.使用 Ribbon 开发微服务

  • 在 Spring Cloud 中,使用 Ribbon 技术开发 Eureka Client 组件还是非常方便的。我们在开发过程中,不需要像 Dubbo 那样关注服务的角色。无论是 Provider 还是 Consumer 都是一个微服务客户端,只是在编码层面上,服务消费者代码的开发相对比较麻烦。我们通过简单案例测试一下 Spring Cloud 中的微服务开发过程。
  • 因为现在的 Eureka Server 部署在 Linux 中,并已为 Linux 定义了新的主机域名,需要先修改开发测试环境中的 hosts 文件 。 windows 中的 hosts 文件位于:C:\windows\system32\dirvers\etc\hosts。新增内容如下:(IP 根据具体情况配置)
192.168.2.115 eureka1 
192.168.2.116 eureka2

2.1 创建 Eureka Client 工程

设置

2.1.1 POM 依赖
<?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">

	<modelVersion>4.0.0</modelVersion>
	<packaging>pom</packaging>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.2.RELEASE</version>
	</parent>
	<groupId>com.dqcgm</groupId>
	<artifactId>cloud</artifactId>
	<version>1.0-SNAPSHOT</version>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Hoxton.SR1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>

2.2 创建 Application Service 服务提供者 Module

设置

2.3 开发服务提供者 - Application Service

2.3.1 POM 依赖
<?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>cloud</artifactId>
		<groupId>com.dqcgm</groupId>
		<version>1.0-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>

	<artifactId>applicationservice</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
	</dependencies>
</project>
2.3.2 服务提供者代码
package com.dqcgm.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ServiceController {
	@GetMapping
	public Object first(){
		return "测试 Spring Cloud Netflix Ribbon 开发服务提供者";
	}
}
2.3.3 配置文件 application.yml
server:
	port: 8081
spring:
	application:
		name: application-service
eureka:
	client:
		service-url:
			# 配置注册中心地址。如果注册中心为多个,则配置多行地址。
			# 注册中心地址格式为: http://ip:port/eureka/
			defaultZone:
				- http://eureka1:8761/eureka/
				- http://eureka2:8761/eureka/
2.3.4 启动类
package com.dqcgm;

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

//@EnableEurekaClient 注解 - 在 Spring Cloud 低版本开发中,每个 Eureka Client 应用启动类上都必须增加此注解。
//代表当前应用是一个 Eureka Client 应用,即需要通过 Eureka Server 注册或发现服务
@SpringBootApplication
public class ServiceApp {
	public static void main(String[] args) {
		SpringApplication.run(ServiceApp.class, args);
	}
}
2.3.5 检查 Eureka Server 中的服务注册情况

sz

2.4 创建 Application Client 服务消费者 Module

sz

2.5 开发服务消费者 - Application Client

2.5.1 POM 依赖
<?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>cloud</artifactId>
		<groupId>com.dqcgm</groupId>
		<version>1.0-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>

	<artifactId>applicationclient</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
	</dependencies>
</project>
2.5.2 服务消费者代码
2.5.2.1 服务接口
package com.dqcgm.service;

public interface ClientService {
	String first();
}
2.5.2.2 服务实现
package com.dqcgm.service.impl;

import com.dqcgm.service.ClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ClientServiceImpl implements ClientService {

	@Autowired
	private LoadBalancerClient loadBalancerClient;
	
	//ribbon 负载均衡器,其中记录了从 Eureka Server 中获取的所有服务信息
	@Override
	public String first() {
		//ServiceInstance 封装了服务的基本信息,如 IP,端口
		//在 Spring Cloud 中,对所有注册到 Eureka Server 中的服务都称为一个 service instance 服务实例
		//一个服务实例,就是一个有效的,可用的,服务单体实例或集群实例。
		//每个 service instance 都和 spring application name 对应
		//可以通过 spring application name 查询 service instance
		ServiceInstance si = this.loadBalancerClient.choose("application-service");
		// 拼接访问服务的 URL http://ip:port/
		StringBuilder sb = new StringBuilder();
		sb.append("http://").append(si.getHost()) .append(":").append(si.getPort()).append("/");
		System.out.println("本次访问的 service 是: " + sb.toString());
		RestTemplate rt = new RestTemplate();
		ParameterizedTypeReference<String> type = new ParameterizedTypeReference<String>() { };
		ResponseEntity<String> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
		String result = response.getBody();

		return result;
	}
}
2.5.2.3 控制器
package com.dqcgm.controller;

import com.dqcgm.service.ClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ClientController {
	@Autowired
	private ClientService clientService;

	@GetMapping
	public Object first(){
		return this.clientService.first();
	}
}
2.5.3 配置文件 application.yml
server: 
	port: 8082

spring: 
	application: 
		name: application-client

eureka: 
	client: 
		service-url: 
			defaultZone: 
				- http://eureka1:8761/eureka/ 
				- http://eureka2:8761/eureka/
2.5.4 启动类
package com.dqcgm;

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

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

3.集中式与进程内负载均衡区别

  • 业界主流的负载均衡解决方案有:集中式负载均衡和进程内负载均衡

3.1 集中式负载均衡

  • 即在客户端和服务端之间使用独立的负载均衡设施(可以是硬件,如 F5, 也可以是软件,如 nginx), 由该设施负责把访问请求通过某种策略转发至服务端
    sz

3.2 进程内负载均衡

  • 将负载均衡逻辑集成到客户端组件中,客户端组件从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务端发起请求。Ribbon 就是一个进程内的负载均衡实现。
    sz

4.Ribbon 常见的负载均衡策略

  • Ribbon 就属于进程内负载均衡,它只是一个类库,集成于 Eureka Client 进程,Eureka Client进程通过访问注册中心Eureka Server发现服务列表,发现的服务列表信息是由ribbon 来管理的。当访问 Application Service 的时候,Application Client 会通过 ribbon 来找到合适的 Application Service 地址信息,并发起远程调用请求。

4.1Ribbon 中的常用负载均衡简介

  • ribbon 的负载均衡策略是通过不同的类型来实现的,下表详细介绍一些常用负载均衡策略及对应的 Ribbon 策略类。
id策略名称策略对应的类名实现原理
1轮询策略(默认)RoundRobinRule轮询策略表示每次都顺序取下一个 provider,比如一共有 5 个 provider,第 1 次取第 1 个,第 2 次取第 2 个,第 3 次取第 3 个,以此类推
2权重轮询策略(常用)WeightedResponseTimeRule1. 根据每个 provider 的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性越低。 2.原理:一开始为轮询策略,并开启一个计时器,每 30 秒收集一次每个 provider 的平均响应时间,当信息足够时,给每个 provider 附上一个权重,并按权重随机选择 provider,高权越重的 provider 会被高概率选中。
3随机策略(不推荐)RandomRule从 provider 列表中随机选择一个 provider
4最少并发数策略 应用在硬件软件环境一致的情况下)BestAvailableRule选择正在请求中的并发数最小的 provider,除非这个 provider 在熔断中。
5在“选定的负载均 衡策略”基础上进行重试机制RetryRule1.“选定的负载均衡策略”这个策略是轮询策略 RoundRobinRule 2.该重试策略先设定一个阈值时间段,如果在这个阈值时间段内当选择 provider 不成功,则一直尝试采 用“选定的负载均衡策略:轮询策略”最后选择一个可用的 provider
6可用性敏感策略 (一般在同区域内服务集群环境中使用)AvailabilityFilteringRule过滤性能差的 provider, 有 2 种:第一种:过滤掉在 eureka 中处于一直连接失败 provider 第二种:过滤掉高并发的 provider
7区域敏感性策略(应用在大型的,物理隔离分布式环境中)ZoneAvoidanceRule1.以一个区域为单位考察可用 性,对于不可用的区域整个丢弃,从 剩下区域中选可用的 provider 2.如果这个 ip 区域内有一个或多个实例不可达或响应变慢,都会降低该 ip 区域内其他 ip 被选中的权重。

4.2 配置负载均衡策略

  • 可以通过修改Application Client应用的全局配置文件来改变当前环境中使用的Ribbon 负载均衡策略
server: 
	port: 8082

spring: 
	application: 
		name: application-client

eureka: 
	client: 
		service-url: 
			defaultZone:
				- http://eureka1:8761/eureka/ 
				- http://eureka2:8761/eureka/

# 设置负载均衡策略。application-service 为设置负载均衡的服务名称
application-service: 
	ribbon:
		NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

5.Ribbon 的点对点直连

  • Ribbon 也可以脱离 Eureka Server 注册中心,通过配置的方式指定要调用的远程服务信息,实现 Ribbon 点对点直连。修改的配置内容如下:
server: 
	port: 8082

spring: 
	application: 
		name: application-client

# application-service : 要点对点直连的远程服务命名
application-service:
	ribbon:
		# 远程服务地址
		listOfServers: localhost:8081

# 关闭 ribbon 自动访问 eureka server 的功能
ribbon:
	eureka:
		enabled: false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

地球村公民

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值