1.1Zull的概述
我们通过前面的内容,已经可以搭建简单的微服务架构系统并实现各个服务之间的调用,但是不同的微服务架构一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求。例如一个电商的APP,可能会调用多个微服务架构的接口才能完成一次购票业务流程,但同样也会出现许多问题:
(1)客户端会多次请求不同的微服务架构,是客户端变得复杂。
(2)存在跨域请求,在一定的场景下处理相对复杂。例如重定向或js发起ajax请求时,会因为域名不同,二级域名不同,子域名不同或端口号不同等因素,是处理变得复杂
(3)项目难以重构。随着项目的迭代,可能需要重新划分微服务架构。
(4)某些微服务架构可能会设置防火墙等不友好协议,难以做到直接访问。
针对上述的问题,可以使用网关解决,服务网关是相当于介于客户端和服务器之间的中间层,所有的外部请求都会经过服务网关进行调度和过滤。服务网关除了要实现请求路由,负载均衡,过滤等功能之外,还要实现更多的功能,例如与服务相关的框架整合,将服务请求熔断等。
总的来说,Zuul是netflix的一个开源组件,是通过Servlet实现的。Zuul作为SpringCloud的服务网关组件,能够通过与Eureka进行整合,将自身注册到Eureka Server中,与Eureka,Ribbon,hystrix等进行整合,同时从Eureka中获得其他微服务架构实例信息。这样的设计通过把网关和服务管理整合到一起,让Zuul可以获取到服务注册信息,结合Ribbon,Hystrix等更好地实现路由转发,负载均衡等功能。
二、Zuul快速入门
对Zuul的工作机制有所了解后,下面通过一个构建网关的实例来介绍Zuul的功能:
2.1 搭建Eureka Server
这里我们无需再去进行Springboot项目eureka-server的搭建,直接使用搭建Eureka所用到的Eureka-server
2.2 创建服务提供者
(1)使用SpringInitiazr的方式创建一个服务提供者的项目,命名为demo-provider,添加Test,Eureka client,Web依赖。
(2)引入依赖后,在全局配置问件application.yml中进行相关配置
spring:
application:
name: demo-provider
server:
port: 7006
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka
instance:
hostname: localhost
(3)创建controller包,并在controller包下创建HystrixController类,类中创建一个hi()方法
package com.example.demoprovider.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Title: HystrixController
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/6/12 17:10
*/
@RestController
public class HystrixController {
@RequestMapping("/hi")
public String hi(String id){
return "hi,访问成功!"+id;
}
}
(4)启动类上添加@EnableEurekaClient注解,开启EurekaClient功能
2.3 创建服务消费者
(1)使用SpringInitiazr的方式创建一个服务提供者的项目,命名为demo-consumer,添加Test,Eureka client,Web依赖。
(2)引入依赖后,在全局配置问件application.yml中进行相关配置
spring:
application:
name: demo-consumer
server:
port: 7864
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka
(3)创建config包,在config包下新建配置类RextConfig,并添加@Configuration注解。在类中创建一个Bean实例方法restTemplate(),并在方法上添加@LoadBalanced注解,使RestTemplate实例对象处理请求时拥有客户端负载均衡的能力,具体如下:
package com.example.democonsumer.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @Title: RestConfig
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/6/12 17:18
*/
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
(4)创建service包,在service包下创建LocalItemService类,并添加@Service注解,在类中注入RestTemplate对象,并添加一个hi()方法,在hi()中对eureka-provider服务提供者进行调用,具体如下:
注:service包要创建在demo-consumer目录下,并与启动类同级
package com.example.democonsumer.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateRequestCustomizer;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
/**
* @Title: LocalItemService
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/6/12 17:20
*/
@Service
public class LocalItemService {
@Autowired
RestTemplate restTemplate;
public String hi(@RequestParam(value = "id")String id){
return restTemplate.getForObject(
"http://eureka-provider/hi?id="+id,String.class);
}
}
(5)创建controller包,在controller包下新建LocalItemController类,并添加Controller注解。在类中注入LocalItemService实例化对象,创建一个hi()方法
package com.example.democonsumer.controller;
import com.example.democonsumer.service.LocalItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Title: LocalItemController
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/6/12 17:26
*/
@RestController
public class LocalItemController {
@Autowired
LocalItemService localItemService;
@GetMapping("/hi")
public String hi(String id){
return localItemService.hi(id);
}
}
(6)启动类中添加上@EnableEurekaClient注解,开启Eureka Client功能
2.4 创建网关服务
(1)使用SpringInitiazr的方式创建一个服务提供者的项目,命名为demo-consumer,添加Test,Eureka client,Web依赖。
在这里我们手动添加Zuul依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
(2)在项目gateway-zuul的启动类GatewayZuulApplication中添加@EnableZuulProxy注解,开启服务网关Zuul功能
package com.example.demogatewayzuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@SpringBootApplication
public class DemoGatewayZuulApplication {
public static void main(String[] args) {
SpringApplication.run(DemoGatewayZuulApplication.class, args);
}
}
(3)在项目gateway-zuul的全局配置文件中配置Zuul的相关信息。
server:
port: 8835
spring:
application:
name: demo-gateway-zuul
eureka:
client:
sevice-url:
defaultZone: http://localhost:7000/eureka/
zuul:
routes:
demo-consumer:
path: /eureka-consumer/**
(4)依次启动项目demo-server,demo-provider,demo-consumer,gateway-zuul,启动成功后访问浏览器http://localhost7000,会显示Eureka注册的服务项目:
1.3 Zuul的过滤器
Zuul是Netflix开源的一个微服务网关,用于在微服务架构中进行路由、负载均衡、服务过滤等功能。Zuul的过滤器是它的核心功能之一,可以通过过滤器实现请求的路由、日志记录、安全验证、错误处理等。
Zuul的过滤器分为四种类型:
1。前置过滤器(Pre Filters):在请求被路由之前执行,可以进行身份验证、参数校验、请求限流等操作。
2.路由过滤器(Route Filters):用于将请求路由到具体的服务实例上,可以实现负载均衡等功能。
3.后置过滤器(Post Filters):在请求被路由到服务实例之后执行,可以进行响应的格式化、日志记录、统计信息收集等操作。
4.错误过滤器(Error Filters):当在上述过程中发生错误时执行,可以进行异常处理、错误日志记录等操作。
1.4 自定义Zuul过滤器
Zuul的过滤器可以通过实现ZuulFilter接口来自定义,或者使用预定义的过滤器。通过配置路由规则和相应的过滤器,可以灵活的控制请求的处理流程。
1.filterType()方法:返回一个字符串代表过滤器的类型。在这里写“pre”,表示过滤器为pre过滤器。
2.filterOrder()方法:返回一个整数表示过滤器的执行顺序。数值越小,优先级越高。
3.shouldFilter()方法:返回一个boolean值,表示该过滤器是否需要执行。可以在这里实现一些条件判断,如果满足条件,返回true,否则返回false。
4.run()方法:过滤器的具体逻辑实现。在这里可以对响应内容进行修改或添加头部信息等操做