Spring Cloud网关Zuul介绍

本文详细介绍了SpringCloud Zuul作为微服务网关的作用,包括动态路由、身份验证、压力测试等功能。并通过代码示例展示了如何将Zuul与Eureka结合使用,以及如何自定义过滤器进行用户名验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Spring Cloud网关是什么

在微服务框架下,单体应用会被切割成多个微服务,如果将所有的微服务直接对外暴露会引发如下类似问题:

  • 客户端需求和每个微服务暴露的细粒度API不匹配。
  • 部分服务使用的协议不是Web友好协议。可能使用Thrift二进制RPC,也可能使用AMQP消息传递协议。
  • 微服务难以重构。如果合并两个服务,或者将一个服务拆分成两个或更多服务,这类重构就非常困难了。
  • 对客户端的访问进行安全性验证,防止爬虫,以及限制IP在一定时间内的请求数。

解决上述问题的方法是使用API网关,API网关是一个微服务框架的唯一入口。从设计模式上来看,它与外观模式类似。下图是一个微服务框架图,其中API网关结合有鉴权和授权认证的业务逻辑。
在这里插入图片描述

二 Spring Cloud网关Zuul

目前Spring Cloud网关可采用的方案和框架包括有Zuul、Nginx、Spring Cloud Gateway和Linkerd。
Zuul是Netflix开源的微服务网关,可以和Eureka、Ribbon,Hystrix等组件配合使用。Zuul组件的核心是一系列的过滤器,通过过滤器可以完成以下功能:

  • 1.身份认证和安全:识别每一个资源的验证要求、审查和监控
  • 2.动态路由:动态将请求路由到不同后端集群
  • 3.压力测试:组建增加指定集群流量,检测性能
  • 4.负载分配:为不同负载类型分配对应容器量
  • 5.静态响应处理:边缘位置响应,避免转发到内部集群
  • 6.多区域弹性
    下面将从Zuul结合其它组件,来介绍Zuul的应用。

2.1 Zuul和Eureka的结合使用

在构建的项目中添加依赖,pom.xml文件中添加如下如下内容
pom.xml的配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    <version>1.4.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>1.4.3.RELEASE</version>
</dependency>
<!--整合达到安全控制-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

application.yml文件配置

server:
  port: 10900 #程序启动端口,tomcat端口(可自定义)
spring:
  application:
    name: api-gateway-zuul #应用名称(别名)
eureka:
  client:
    serviceUrl:
      defaultZone: http://user:user@localhost:8888/eureka
  instance:
    prefer-ip-address: true #显示 ip
security:  #配置访问 zuul 的 routes 的时候使用
  user:
    name: zuul
    password: zuul
zuul:
  routes: #配置路由映射
    provider-user: /route-map1/** #给指定的服务做映射, 当前配置给provider-user添加映射地址为/route-map1

Zuul模块的代码
在Zuul模块的代码中添加注解@EnableZuulProxy和@EnableDiscoveryClient。使用@EnableZuulProxy将这个类指示为Zuul Server, @EnableDiscoveryClient将这个类指示为Eureka的客户端。在部分Zuul版本中,@EnableZuulProxy可能包含@EnableDiscoveryClient注解。

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

Eureka模块的代码

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(EurekaApplication.class).web(true).run(args);
    }
}

客户端模块的代码

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class ControllerApplicationA {

    public static void main(String[] args) {
        new SpringApplicationBuilder(ControllerApplicationA.class).web(true).run(args);
    }
}

上述代码就实现了,客户端和Zuul网关代码向Eureka注册,并通过访问Zuul来访问客户端的大概框架。

2.2 Zuul中的过滤器(filter)

Zuul过滤器(filter)是Zuul的两大核心功能之一(另一核心功能是路由器router),过滤器(filter)可以在真正进行请求之前进行必要的业务操作,比如说验证。从业务逻辑上来看,Zuul本身也是一系列过滤器集成,Zuul提供了四种类型过滤器:前置过滤器,路由过滤器,错误过滤器和简单过滤器。Zuul过滤器最核心的接口为IZuulFilter,该接口的定义非常简单,参考如下:

/*
 * Copyright 2013 Netflix, Inc.
 *
 *      Licensed under the Apache License, Version 2.0 (the "License");
 *      you may not use this file except in compliance with the License.
 *      You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 *      Unless required by applicable law or agreed to in writing, software
 *      distributed under the License is distributed on an "AS IS" BASIS,
 *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *      See the License for the specific language governing permissions and
 *      limitations under the License.
 */
package com.netflix.zuul;

import com.netflix.zuul.exception.ZuulException;

/**
 * BAse interface for ZuulFilters
 *
 * @author Mikey Cohen
 *         Date: 10/27/11
 *         Time: 3:03 PM
 */
public interface IZuulFilter {
    /**
     * a "true" return from this method means that the run() method should be invoked
     *
     * @return true if the run() method should be invoked. false will not invoke the run() method
     */
    boolean shouldFilter();

    /**
     * if shouldFilter() is true, this method will be invoked. this method is the core method of a ZuulFilter
     *
     * @return Some arbitrary artifact may be returned. Current implementation ignores it.
     * @throws ZuulException if an error occurs during execution.
     */
    Object run() throws ZuulException;

}

抽象类ZuulFilte,ZuulFilter实现了接口IZuulFilter,在接口的基础上添加了抽象方法

/**
     * to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering,
     * "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.
     * We also support a "static" type for static responses see  StaticResponseFilter.
     * Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)
     *
     * @return A String representing that type
     */
    abstract public String filterType();

    /**
     * filterOrder() must also be defined for a filter. Filters may have the same  filterOrder if precedence is not
     * important for a filter. filterOrders do not need to be sequential.
     *
     * @return the int order of a filter
     */
    abstract public int filterOrder();

该抽象类的方法解释如下:
filterType:定义过滤器的类型,常见的有pre(预处理阶段)post(请求原始服务之前)error(发生错误以后)route(请求原始服务之后)

自定义过滤器
实现用户名验证

package com.zhibo.springcloud.zuul;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class ValidateUserZuulFilter extends ZuulFilter {

    /**
     *
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String loginName = request.getParameter("loginName");
        if (loginName == null || !"admin".equals(loginName)) {
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(500);
            Gson gson = new GsonBuilder().create();
            requestContext.addZuulResponseHeader("content-type", "application/json;charset=utf-8");
            requestContext.setResponseBody(gson.toJson(new ResponseEntity("没有登录名", HttpStatus.CONFLICT)));
            return null;
        }
        return null;
    }
}

在Zuul模块的代码中,注册进行生效,代码如下:

@EnableZuulProxy
@SpringBootApplication
public class ApiGatewayApplication {

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

    @Bean
    public TokenFilter tokenFilter() {
        return new TokenFilter();
    }
}

三、总结

上述对spring cloud zuul在功能上进行简介,在zuul的实际使用方面,比如结合Eureka模块的使用和过滤器方面,用代码进行了说明。但是上述并没有覆盖到Zuul的所有知识点,后续有时间在做整理。

参考博客

  1. 微服务网关netflix-zuul
  2. 微服务网关Zuul迁移到Spring Cloud Gateway
  3. 微服务API网关NGINX、ZUUL、Spring Cloud Gateway与Linkerd
  4. Spring Cloud-Zuul 路由器和过滤器
  5. spring cloud使用zuul实现反向代理和负载均衡
  6. SpringCloud学习之zuul
  7. Spring Cloud(十一):服务网关 Zuul(过滤器)【Finchley 版】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值