`
raymond.chen
  • 浏览: 1436909 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

服务网关Spring Cloud Zuul

 
阅读更多

Zuul是Netflix开源的微服务网关,Spring Cloud对Zuul进行了整合和增强。在Spring Cloud体系中,Zuul担任着网关的角色,对发送到服务端的请求进行一些预处理,比如安全验证、动态路由、负载均衡等。

 

Zuul(1.x) 基于Servlet,使用阻塞 API,它不支持任何长连接,如 WebSocket。

 

Netflix使用Zuul进行以下操作:认证、洞察、压力测试、金丝雀测试、动态路由、服务迁移、负载脱落、安全、静态响应处理、主动/主动流量管理等。

 

Zuul的主要功能是路由转发和过滤器。

    路由:

         负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。

    过滤器:

         负责对请求的拦截与过滤,是实现请求校验、权限控制、服务聚合、监控、压力测试、请求限流等功能的基础。

         是Zuul实现API网关功能最为核心的部件,每一个进入Zuul的HTTP请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端。

 

zuul默认和Ribbon结合实现了负载均衡的功能。

 

Hystrix和Ribbon支持

        Zuul中包含了Hystrix和Ribbon的依赖,所以Zuul拥有线程隔离和断路器的自我保护功能,以及对服务调用的客户端负载均衡。传统路由也就是使用path与url映射关系来配置路由规则的时候,对于路由转发的请求不会使用HystrixCommand来包装,所以没有线程隔离和断路器的保护,并且也不会有负载均衡的能力。

 

 Zuul中默认实现的Filter

    pre:

        ServletDetectionFilter          用来检测当前请求是通过Spring的DispatcherServlet处理运行,还是通过ZuulServlet来处理运行的。

        Servlet30WrapperFilter       将原始的HttpServletRequest包装成Servlet30RequestWrapper对象。

        FormBodyWrapperFilter     将符合要求的请求体包装成FormBodyRequestWrapper对象。该过滤器仅对两种类请求生效,第一类是Content-Type为application/x-www-form-urlencoded的请求,第二类是Content-Type为multipart/form-data并且是由Spring的DispatcherServlet处理的请求。

        PreDecorationFilter            处理请求上下文供后续使用。

 

    route:

        RibbonRoutingFilter            该过滤器只对请求上下文中存在serviceId参数的请求进行处理,即只对通过serviceId配置路由规则的请求生效。它通过使用Ribbon和Hystrix来向服务实例发起请求,并将服务实例的请求结果返回。

        SimpleHostRoutingFilter    该过滤器只对请求上下文中存在routeHost参数的请求进行处理,即只对通过url配置路由规则的请求生效。该请求是直接通过httpclient包实现的,而没有使用Hystrix命令进行包装,所以这类请求并没有线程隔离和断路器的保护。

        SendForwardFilter             该过滤器只对请求上下文中存在forward.to参数的请求进行处理,即用来处理路由规则中的forward本地跳转配置。

 

    post:

        SendErrorFilter                    该过滤器仅在请求上下文中包含error.status_code参数并且还没有被该过滤器处理过的时候执行。

        SendResponseFilter           该过滤器会检查请求上下文中是否包含请求响应相关的头信息、响应数据流或是响应体,只有在包含它们其中一个的时候就会执行处理逻辑。

 

 创建Zuul服务网关工程

    pom.xml文件的关键配置:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.0.7.RELEASE</version>
	<relativePath/>
</parent>

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-zuul</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-actuator</artifactId>
	</dependency>
</dependencies>

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>Finchley.RELEASE</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

 

    application.properties文件的配置:

spring.application.name=service-zuul
server.port=3001

eureka.instance.hostname=${spring.cloud.client.ip-address}
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
eureka.instance.prefer-ip-address=true

#注册中心地址
eureka.client.service-url.defaultZone=http://root:123456@${eureka.instance.hostname}:7001/eureka/

#服务路由规则配置
zuul.routes.a.path=/api-a/**
zuul.routes.a.serviceId=service-consumer-1
#zuul.routes.a.url=http://localhost:9002/

zuul.routes.b.path=/api-b/**
zuul.routes.b.serviceId=service-consumer-2
#zuul.routes.service-consumer-2=/api-b/**

 

规则配置详解:

        格式: zuul.routes.<路由名>.属性名 ,路由名可随意定义

 

        对于面向服务的路由配置有一种更简单的方式:zuul.routes.<服务名>=<映射地址>

 

        path: 定义一个用来匹配客户端请求的路径表达式

        serviceId: 指定请求表达式映射具体的服务名。服务路由配置时使用该属性

               当同一服务名下有多个服务实例时,默认是采用轮询的负载均衡策略,通过在启动类配置负载均衡Bean类可以更改默认策略。

        url: 指定请求表达式映射具体的实例地址。传统路由配置时使用该属性

 

        假如网关根地址是http://localhost:3001,微服务根地址是http://localhost:9002,那么请求地址http://localhost:3001/api-b/addUser会路由到http://localhost:9002/addUser微服务地址。

 

    启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy //开启zuul功能
public class Main {
	public static void main(String[] args) {
		SpringApplication.run(Main.class, args);
	}
}
	
/**
 * 更改zull服务路由的负载均衡策略
 */
@Bean
public IRule feignRule(){
	return new RandomRule(); //随机
}

 

忽略指定路径

        设置不希望被API网关进行路由的URL表达式

        zuul.ignored-patterns=/**/hello/**    #忽略所有包含/hello/的路径

 

忽略服务路由的默认配置

        Zuul注册到Eureka服务中心后,它会为Eureka中的每个服务都创建一个默认的路由规则,默认规则的path会使用serviceId配置的服务名作为请求前缀,如http://localhost:9002/service-consumer-2/addUser

 

       可以使用zuul.ignored-services参数来设置一个不自动创建该服务的默认路由,多个服务名之间用逗号分隔。如

               zuul.ignored-services=service-consumer-1,service-consumer-2

 

        忽略所有服务

                zuul.ignored-services=*

 

路由前缀

         默认情况下,路径表达式的前缀会被移除掉。可以使用zuul.strip-prefix=false来关闭移除前缀的动作,也可以通过zuul.routes.<路由名>.strip-prefix=false来指定服务关闭移除前缀的动作

 

本地跳转

         zuul.routes.<路由名>.url=forward:/<要跳转到的端点>

 

禁用过滤器

         zuul.<过滤器名>.<过滤器类型>.disable=true

 

 自定义过滤器

        Zuul服务网关的很多基础功能都可以通过自定义过滤器来实现。自定义过滤器需要继承ZuulFilter类。

@Component
public class DefaultZuulFilter extends ZuulFilter {
	/**
	 * 过滤器类型,它决定过滤器在请求的哪个生命周期中执行。
	 * 		pre:路由之前
	 * 		route:路由之时
	 * 		post: 路由之后
	 * 		error:处理请求发生错误时调用
	 */
	@Override
	public String filterType() {
		return FilterConstants.PRE_TYPE;
	}
	
	/**
	 * filter执行顺序
	 * 数字越大,优先级越低
	 */
	@Override
	public int filterOrder() {
		return 0;
	}
	
	/**
	 * 判断该过滤器是否需要被执行。
	 */
	@Override
	public boolean shouldFilter() {
		return true;
	}
	
	/**
	 * 过滤器的具体逻辑:可以查询数据库判断是否有访问权限
	 */
	@Override
	public Object run() {
		RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        
        Object token = request.getParameter("token");
        if(token == null) {
            requestContext.setSendZuulResponse(false); //过滤该请求,不对其进行路由
            requestContext.setResponseStatusCode(401); //返回的错误码
            
            try {
                requestContext.getResponse().getWriter().write("token is empty");
            }catch (Exception ex){
            	ex.printStackTrace();
            }
            
            return null;
        }
        
        return null;
	}
}

 

 路由熔断处理

      默认情况下,当Zuul调用后端服务出现异常时,异常会抛出给最外层。 为了避免这种情况的发生,可以通过自定义Fallback类来处理。自定义Fallback类需要实现FallbackProvider接口类。

    Consumer1FallbackProvider类:

/**
 * 回退类:Zuul路由熔断时调用
 * 		Zuul目前只支持服务级别的熔断,不支持具体到某个URL进行熔断。
 */
@Component
public class Consumer1FallbackProvider implements FallbackProvider{
//	private String serviceName = "service-consumer-1"; //为指定微服务提供回退
	private String serviceName = "*"; //为所有微服务提供回退
	
	/**
	 * 表明是为哪个微服务提供回退
	 */
	@Override
	public String getRoute() {
		return serviceName;
	}
	
	/**
	 * 回退的响应对象
	 */
	@Override
	public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
		return new DefaultClientHttpResponse(route);
	}
}

 

    DefaultClientHttpResponse类:

public class DefaultClientHttpResponse implements ClientHttpResponse {
	private String route;
	
	public DefaultClientHttpResponse(String route){
		this.route = route;
	}
	
	/**
	 * 响应体
	 */
	@Override
	public InputStream getBody() throws IOException {
		String result = "";
		try {
			JSONObject object = new JSONObject();
			object.put("code", "999");
			object.put("message", route + " 不可用!");
			result = object.toString();
			
		} catch (JSONException e) {
			e.printStackTrace();
		}
		
		return new ByteArrayInputStream(result.getBytes());
	}

	@Override
	public HttpHeaders getHeaders() {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		return headers;
	}

	@Override
	public HttpStatus getStatusCode() throws IOException {
		//fallback时的状态码
        return HttpStatus.OK;
	}

	@Override
	public int getRawStatusCode() throws IOException {
		//数字类型的状态码
        return this.getStatusCode().value();
	}

	@Override
	public String getStatusText() throws IOException {
		//状态文本
		return this.getStatusCode().getReasonPhrase();
	}

	@Override
	public void close() {
		
	}
}

 

 

分享到:
评论

相关推荐

    springcloud zuul网关服务

    SpringCloud Zuul是基于Spring Cloud框架的一个核心组件,它扮演着API网关的角色,负责路由转发、过滤器处理以及安全控制等任务。Zuul的主要功能包括动态路由、过滤器机制、安全控制、负载均衡、健康检查等。下面将...

    springcloud zuul gateway 服务网关

    SpringCloud Zuul Gateway 服务网关是Spring Cloud生态系统中的一个重要组件,它主要负责微服务架构中的路由转发和过滤器功能。Zuul是Netflix开源的一个边缘服务,而Gateway则是Spring Cloud针对Zuul进行的升级版,...

    《深入理解Spring Cloud与微服务构建》学习笔记(十七)~路由网关Spring Cloud Zuul~负载均衡

    在本篇学习笔记中,我们将深入探讨Spring Cloud框架中的一个重要组件——Spring Cloud Zuul,它作为微服务架构中的路由网关和负载均衡器。Spring Cloud是基于Java的微服务工具集,它为开发者提供了在分布式系统(如...

    《深入理解Spring Cloud与微服务构建》学习笔记(十六)~路由网关Spring Cloud Zuul

    在本篇学习笔记中,我们将深入探讨Spring Cloud框架中的一个重要组件——Spring Cloud Zuul,它是一个强大的路由网关。Zuul的主要职责是为微服务架构提供统一的入口,进行请求过滤、路由转发等操作,使得后端服务对...

    《深入理解Spring Cloud与微服务构建》学习笔记(十八)~路由网关Spring Cloud Zuul~熔断器

    首先,Spring Cloud Zuul是Spring Cloud生态中的一个边缘服务工具,它作为一个API网关,负责处理所有客户端的请求。作为前端和后端服务之间的桥梁,Zuul可以实现动态路由、过滤、安全控制、负载均衡等功能,简化了...

    SpringCloud zuul jar包

    SpringCloud Zuul是Spring Cloud生态系统中的一个边缘服务和API网关组件。它的主要功能是作为微服务架构中的统一入口,负责路由转发、过滤器处理、负载均衡以及安全控制等任务。Zuul允许开发者在微服务架构中实现...

    spring cloud zuul

    **Spring Cloud Zuul** 是一个基于 Spring Framework 和 Netflix Zuul 的边缘服务工具,它作为微服务架构中的边缘服务器,提供动态路由、流量控制、安全、监控等功能。Zuul 主要是作为 API 网关,它负责处理所有来自...

    springcloud zuul 网关实现源码

    springcloud zuul 网关开发实践,模拟了在Spring Cloud微服务系统中,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服的实现过程。

    Springcloud Zuul config eureka ribbon实例

    接下来,Zuul是Spring Cloud的边缘服务,也是一个API网关。`demo-zuul-master.zip`中的代码展示了如何设置和使用Zuul。Zuul可以处理所有来自客户端的请求,执行如认证、路由、过滤等操作。它将请求转发到合适的...

    06Spring Cloud Zuul:API网关服务1

    Spring Cloud Zuul:API网关服务详解 Spring Cloud Zuul 是 Spring Cloud Netflix 子项目的核心组件之一,可以作为微服务架构中的 API 网关使用,支持动态路由与过滤功能。API 网关为微服务架构中的服务提供了统一...

    第六章 SpringCloud Zuul网关.pdf

    Spring Cloud Zuul网关 Spring Cloud Zuul网关是微服务架构中的一种网关解决方案,主要用于解决微服务之间的调用和路由问题。在本章节中,我们将了解Zuul网关的基本概念和使用方法,以及如何将其应用于微服务架构...

    SpringCloud Zuul网关功能实现解析

    SpringCloud Zuul网关功能实现解析 SpringCloud Zuul网关功能实现解析是基于 SpringCloud 生态系统的微服务架构中的一种网关解决方案。 Zuul 是 Netflix 公司开源的一个基于 Java 的 API Gateway 项目,旨在提供一...

    Spring Cloud Zuul动态路由demo

    在"Spring Cloud Zuul动态路由demo"中,我们将看到如何创建Config Server项目,配置Eureka,然后编写Zuul服务,实现动态路由配置的加载和变更。同时,你还可以学习如何编写自定义过滤器,以及如何测试动态路由功能...

    spring cloud 使用Zuul 实现API网关服务问题

    Spring Cloud 使用 Zuul 实现 API 网关服务问题 在本文中,我们将主要介绍如何使用 Spring Cloud 的 Zuul 组件来实现 API 网关服务问题。 Zuul 是一个基于 Netflix Zuul 的 API 网关组件,它可以解决路由规则和服务...

    微服务 Springcloud Zuul

    Zuul是Spring Cloud生态中的一个关键组件,它扮演着边缘服务的角色,负责微服务间的路由转发和过滤器功能。本文将深入探讨Spring Cloud Zuul在微服务架构中的应用和重要性。 1. **Zuul简介** Zuul是Netflix开源的...

    spring cloud zuul 使用

    Spring Cloud Zuul是Spring Cloud生态系统中的一个边缘服务和API网关组件。它作为一个过滤器路由,为微服务架构提供统一的入口,同时处理预处理、安全、限流等功能。这篇博客文章“Spring Cloud Zuul使用”可能详细...

    spring-cloud-zuul(包含注册中心、服务生产者、服务消费者、zuul网关路由).zip

    SpringCloud-2.0-service-zuul-80 代表了Zuul服务网关,它是所有微服务请求的统一入口。Zuul的主要职责有: 1. 路由转发:根据请求路径将请求转发到对应的服务提供者,实现服务间的解耦。 2. 访问过滤:Zuul提供了...

    Spring Cloud Zuul带注册中心Consul

    Spring Cloud Zuul是基于Spring Boot实现的微服务网关,它提供路由转发、过滤器等功能,使得客户端可以方便地访问到后端微服务。在这个示例中,Zuul与Consul结合,使得Zuul能够动态地发现注册在Consul中的服务,实现...

    使用SpringCloud Zuul Proxy构建API网关.docx

    Spring Cloud Zuul 是一个基于 Java 的边缘服务,它可以作为 API 网关,对微服务架构中的所有请求进行路由。Zuul 提供了过滤器机制(Zuul Filters),类似于 Spring 的面向切面编程(AOP),可以实现预处理、路由、...

Global site tag (gtag.js) - Google Analytics