微信公众号:[0error] 关注可了解更多的知识干货,也可看看生活杂谈。如有问题或建议,欢迎在公众号留言。
今天继续学习SpringCloud。
上篇我们讲了Eureka和服务提供者、消费者
这一篇针对服务网关和负载均衡详细说说
以下代码皆用最简单的代码示例,并非真正的业务代码
学习中用到的学习资料如下:
文章:SpringCloud极简入门
https://gitbook.cn/gitchat/column/5e38e68dec8d9033cf91a047
视频:Spring Cloud从入门到实战
https://www.bilibili.com/video/BV1p4411K7pz?spm_id_from=333.999.0.0
服务网关的概念
在分布式项目架构中,会将服务进行拆分,不同的微服务负责各自的业务功能,实现软件架构层面的解耦合。但是如果拆分之后的微服务数量太多,是不利于系统开发的,因为每个服务都有不同的网络地址,客户端多次请求不同的微服务需要调用不同的 URL,如果同时去维护多个不同的 URL 无疑会增加开发的成本。
如下图所示,一个订餐系统,需要调用多个微服务接口才能完成一次订餐的业务流程,如果能有一种解决方案可以统一管理不同的微服务 URL,肯定会增强系统的维护性,提高开发效率。
这个解决方案就是 API 网关,API 网关可以对所有的 API 请求进行管理维护,相当于为系统开放出一个统一的接口,所有的外部请求只需要访问这个统一入口即可,系统内部再通过 API 网关去映射不同的微服务。对于开发者而言就不需要关注具体的微服务 URL 了,直接访问 API 网关接口即可,API 网关的结构如下图所示。
如此一来我们就解决了上述问题,开发变得更加简单方便。
Zuul
什么是 Zuul?
Zuul 是 Netflix 提供的一个开源的 API 网关服务器,是客户端和网站后端所有请求的中间层,对外开放一个 API,将所有请求导入统一的入口,屏蔽了服务端的具体实现逻辑,Zuul 可以实现反向代理的功能,在网关内部实现动态路由、身份认证、IP 过滤、数据监控等。我们可以使用 Zuul 来实现微服务网关,Spring Cloud 集成了 Zuul。
代码实现
-
创建 Maven 工程,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
-
创建配置文件 application.yml
server:
port: 8030
spring:
application:
name: gateway
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
provider: /p/**
属性说明:
zuul.routes.provider
:给服务提供者 provider 设置映射
-
创建启动类
package com.janeroad;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@EnableAutoConfiguration
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class,args);
}
}
注解说明:
@EnableZuulProxy
:包含了 @EnableZuulServer
,设置该类是网关的启动类。
@EnableAutoConfiguration
:可以帮助 Spring Boot 应用将所有符合条件的 @Configuration
配置加载到当前 Spring Boot 创建并使用的 IoC 容器中。
-
Zuul 自带了负载均衡功能,修改 provider 的代码。
package com.janeroad.controller;
import com.janeroad.entity.Student;
import com.janeroad.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
@RestController
@RequestMapping("/student")
public class StudentHandler {
@Autowired
private StudentRepository studentRepository;
@Value("${server.port}")
private String port;
@GetMapping("/findAll")
public Collection findAll(){
return studentRepository.findAll();
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return studentRepository.findById(id);
}
@PostMapping("/save")
public void save(@RequestBody Student student){
studentRepository.saveOrUpdate(student);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
studentRepository.saveOrUpdate(student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
studentRepository.deleteById(id);
}
@GetMapping("/index")
public String index(){
return "当前端口:"+this.port;
}
}
服务网关zuul启动效果
可以看到注册中心多了GATEWAY
访问8030/p/student/findAll 相当于访问服务提供者 8010/student/findAll,因为配置文件做了相关的映射
同时 Zuul 自带了负载均衡功能,在EurekaClient中的Handler里面增加一个返回当前服务端口的方法,重启EurekaServer和EurekaClient 然后修改 provider 的端口为 8011,创建一个新的 provider 启动类并启动,最后重新启动 gateway,访问 http://localhost:8761 可以看到有两个provider
访问两次 http://localhost:8030/p/student/index,分别请求了端口为 8010 和 8011 的 provider 微服务,实现了负载均衡。
Ribbon 负载均衡
RestTemplate 的调用只是实现了最基本的需求,如果在某个具体的业务场景下,对于某服务的调用需求激增,这时候在一个大型的分布式应用系统中,负载均衡(Load Balancing)是必备的。
什么是 Ribbon?
Spring Cloud 提供了实现负载均衡的解决方案:Spring Cloud Ribbon,Ribbon 是 Netflix 发布的负载均衡器,而 Spring Cloud Ribbon 则是基于 Netflix Ribbon 实现的,是一个用于对 HTTP 请求进行控制的负载均衡客户端。
Spring Cloud Ribbon 官网地址:
http://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-ribbon.html
Ribbon 的使用同样需要结合 Eureka Server,即需要将 Ribbon 在 Eureka Server 进行注册,注册完成之后,就可以通过 Ribbon 结合某种负载均衡算法,如轮询、随机、加权轮询、加权随机等帮助服务消费者去调用接口。除了 Ribbon 默认提供的这些负载均衡算法外,开发者也可以根据具体需求来设计自定义的 Ribbon 负载均衡算法。实际开发中,Spring Cloud Ribbon 需要结合 Spring Cloud Eureka 来使用,Eureka Server 提供所有可调用的服务提供者列表,Ribbon 基于特定的负载均衡算法从这些服务提供者中挑选出要调用的实例,如下图所示。
Ribbon 常用的负载均衡策略有以下几种:
-
随机:访问服务时,随机从注册中心的服务列表中选择一个。 -
轮询:当同时启动两个服务提供者时,客户端请求会由这两个服务提供者交替处理。 -
加权轮询:对服务列表中的所有微服务响应时间做加权处理,并以轮询的方式来访问这些服务。 -
最大可用:从服务列表中选择并发访问量最小的那个微服务。
代码实现
-
创建 Module,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
-
创建配置文件 application.yml
server:
port: 8040
spring:
application:
name: ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
-
创建启动类
package com.janeroad;
import org.springframework.boot.SpringApplication;
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 RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@LoadBalanced
:声明一个基于 Ribbon 的负载均衡。
-
Handler
package com.janeroad.controller;
import com.janeroad.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/ribbon")
public class RibbonHandler {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/findAll")
public Collection findAll(){
return restTemplate.getForObject("http://provider/student/findAll",Collection.class);
}
@GetMapping("/index")
public String index(){
return restTemplate.getForObject("http://provider/student/index",String.class);
}
}
打开浏览器,访问 http://localhost:8761,看到如下界面
可以看到 Provider 和 Ribbon 已经在注册中心完成注册,接下来用 Postman 工具测试 Ribbon 相关接口,如下图所示。
-
findAll 接口
-
findById 接口
-
save 接口
添加完成之后再来查询,调用 findAll 接口,可以看到新数据已经添加成功。
-
update 接口
修改完成之后再来查询,调用 findAll 接口,可以看到修改之后的数据。
-
deleteById 接口
删除完成之后再来查询,调用 findAll 接口,可以看到数据已经被删除。
接下来测试 Ribbon 的负载均衡,在 RibbonHandler 中添加如下代码
@RequestMapping("/ribbon")
@RestController
public class RibbonHandler {
@GetMapping("/index")
public String index(){
return restTemplate.getForObject("http://provider/student/index",String.class);
}
}
分别启动注册中心,端口为 8010 的 Provider,端口为 8011 的 Provider、Ribbon。
打开浏览器,访问 http://localhost:8761
可以看到两个 Provider 和 Ribbon 已经在注册中心完成注册,访问 http://localhost:8040/ribbon/index,交替出现下图所示情况,实现了负载均衡。
原文始发于微信公众号(JaneRoad):SpringCloud-Zuul服务网关与Ribbon负载均衡
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/23013.html