什么是负载均衡
1. LB,即负载均衡(Load Balance),负载均衡是微服务架构中经常使用的一种技术。 负载均衡是我们处理高并
发、缓解网络压力和进行服务端扩容的重要手段之一,简单的说就是将用户的请求平摊的分配到多个服务
上,从而实现系统的高可用性集群。
2. 负载均衡可通过 硬件设备 及 软件 进行实现,软件比如:Nginx等,硬件比如:F5等
3. 负载均衡相应的在中间件,例如:Dubbo 和 SpringCloud 中均给我们提供了负载均衡组件
用户请求先到达负载均衡器(也相当于一个服务),负载均衡器根据负载均衡算法将请求转发到微服务。负载均衡器维护一份服务端列表,根据负载均衡算法 将请求转发到相应的微服务上,负载均衡 算法有:轮训、随机、加权轮训、加权随机、地址哈希等方法,所以负载均衡可以为微服务集群分担请求,降低系统的压力。
Ribbon 服务调用配置实战
无需新增新服务,在消费者端通过 Ribbon 进行实现负载均衡即可
修改消费者服务的POM文件
由于依赖了spring-cloud-starter-netflix-eureka-client,会自动添加spring-cloud-starter-netflix-ribbon依赖
<!-- Ribbon 相关依赖,eureka会自动引入Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
修改消费者服务的application.yml
eureka:
client:
registerWithEureka: false # 服务注册,false表示不将本消费者注册到 Eureka 服务器
fetchRegistry: true # 服务发现,true从 Eureka 服务器中获取注册信息
serviceUrl:
defaultZone:http://eureka6001.com:6001/eureka/,http://eureka6002.com:6002/eureka/
修改消费者的configbean
添加注解@Configuration
///@LoadBalanced表示这个RestTemplate开启负载均衡,在调用服务提供者的接口时,
//可使用 服务名称 替代真实IP地址。服务名称 就是服务提供者在application.yml中
//配置的spring.application.name属性的值。
@LoadBalanced
@Bean // 向容器中添加 RestTemplate 组件,直接通过此组件可调用 REST 接口
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
修改消费者控制层 ProductController_Consumer
package com.sjf.controller;
import com.sjf.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* <p>
*
* </p>
* @creation 2020/3/14 11:38
* @author sjf
*/
@RestController
public class ProductController_Consumer {
//private static final String REST_URL_PREFIX = "http://localhost:8001";
//修改为商品提供者向Eureka服务器中注册的地址,服务提供着的applicationname
private static final String REST_URL_PREFIX = "http://server02-product";
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/consumer/product/add")
public boolean add(Product product) {
return restTemplate.postForObject(REST_URL_PREFIX + "/product/add", product, Boolean.class);
}
@RequestMapping(value = "/consumer/product/get/{id}")
public Product get(@PathVariable("id") Long id) {
return restTemplate.getForObject(REST_URL_PREFIX + "/product/get/" + id, Product.class);
}
@RequestMapping(value = "/consumer/product/list")
public List<Product> list() {
return restTemplate.getForObject(REST_URL_PREFIX + "/product/list", List.class);
}
}
在主启动类 MicroserviceProductConsumer_80 上添加注解 @EnableEurekaClient
@EnableEurekaClient //标识 是一个Eureka客户端
@SpringBootApplication
public class ProductConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(ProductConsumer_80.class, args);
}
}
功能测试
启动2个Eureka集群后,
再启动 8001 并注册进 eureka
接着启动 80
访问:
http://localhost/consumer/product/get/1
http://localhost/consumer/product/list
Ribbon 负载均衡实战
Ribbon 负载均衡架构
Ribbon 在工作时分成两步:
第1步先选择 Eureka Server ,它优先选择在同一个区域内负载较少的server
第2步再根据用户指定的策略,在从 Eureka Server 获取的服务注册列表中选择一个地址。 其中Ribbon提供
了多种策略:比如轮询、随机和根据响应时间加权等
再新建一个提供者服务
复制8001服务为8002服务,8002服务访问得数据库是另外一个
8002服务与8001区别在于端口,与访问得数据库不一致。其他都一致
8002的application.yml
server:
port: 8002
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.sjf # 所有Entity别名类所在包
mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
#应用名称
application:
name: server02-product #这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name
#连接数据库设置
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # mysql驱动包
url: jdbc:mysql://127.0.0.1:3306/springcloud_db02?serverTimezone=GMT%2B8 # 数据库名称
username: root
password: 123456
dbcp2:
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化连接数
max-total: 5 # 最大连接数
max-wait-millis: 150 # 等待连接获取的最大超时时间
eureka:
client:
registerWithEureka: true # 服务注册开关
fetchRegistry: true # 服务发现开关
serviceUrl: # 客户端(服务提供者)注册到哪一个Eureka Server服务注册中心,多个用逗号分隔
defaultZone: http://eureka6001.com:6001/eureka,http://eureka6002.com:6002/eureka
instance:
instanceId: ${spring.application.name}:${server.port} # 指定实例ID,就不会显示主机名了
hostname: localhost
prefer-ip-address: true #访问路径就会显示成IP地址
功能测试
多次访问消费端服务,查询出来的结果不一致,其实就是消费端的请求负载均衡。
项目上,可以起端口不一样,访问数据库一致的多个服务来缓解服务端的压力。