SpringCloud(六):服务网关zuul-API网关

什么是API网关:

在微服务架构中,通常会有多个服务提供者。设想一个电商系统,可能会有商品、订单、支付、用户等多个类型的服务,而每个类型的服务数量也会随着整个系统体量的增大也会随之增长和变更。作为UI端,在展示页面时可能需要从多个微服务中聚合数据,而且服务的划分位置结构可能会有所改变。网关就可以对外暴露聚合API,屏蔽内部微服务的微小变动,保持整个系统的稳定性。

Zuul是Spring Cloud全家桶中的微服务API网关。

所有从设备或网站来的请求都会经过Zuul到达后端的Netflix应用程序。作为一个边界性质的应用程序,Zuul提供了动态路由、监控、弹性负载和安全功能。Zuul底层利用各种filter实现如下功能:

  • 认证和安全   识别每个需要认证的资源,拒绝不符合要求的请求。
  • 性能监测    在服务边界追踪并统计数据,提供精确的生产视图。
  • 动态路由    根据需要将请求动态路由到后端集群。
  • 压力测试    逐渐增加对集群的流量以了解其性能。
  • 负载卸载    预先为每种类型的请求分配容量,当请求超过容量时自动丢弃。
  • 静态资源处理   直接在边界返回某些响应。

在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(Ngnix),再到达服务网关(zuul集群),然后再到具体的服务。服务统一注册到高可用的服务注册中心集群(eureka, consul),服务的所有的配置文件由配置服务管理,配置服务的配置文件放在git仓库,方便开发人员随时改配置。
————————————————

二、动态路由

 pom.xml:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>
    </dependencies>

application.properties:

spring.application.name=service-zuul
server.port=8061
## 注册服务中心的配置
eureka.client.service-url.defaultZone=http://localhost:8001/eureka/
#zuul.routes.<route>.path配置拦截请求的路径
#zuul.routes.<route>.serviceId配置拦截之后路由到的指定的eureka服务
#这里除了能结合eureka服务,指定serviceId使用,还可以指定为一个url地址,比如zuul.routes.hello-service.path=http://localhost:8011
zuul.routes.user-service.path=/user-service/**
zuul.routes.user-service.serviceId=USER-SERVICE
# 注释上面,改成user-service.url直接访问百度
#zuul.routes.user-service.url=http://pay.weixin.qq.com/partner/public/home
#zuul.routes.user-service.url=http://localhost:8011

zuul.routes.<route>.path与zuul.routes.<route>.serviceId分别配置zuul拦截请求的路径,以及拦截之后路由到的指定的eureka服务

这里除了能结合eureka服务,指定serviceId使用,还可以指定为一个url地址,比如zuul.routes.hello-service.path=http://localhost:8011

application.yml:

##timeout config
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 60000
ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 1
  eureka:
    enabled: true

zuul:
  max:
    host:
      connections: 500
  host:
    socket-timeout-millis: 60000
    connect-timeout-millis: 60000

启动类 Application.java:

package cn.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class ServiceZuulApplication {

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

这里使用@EnableZuulProxy表示开启zuul网关。

@EnableEurekaClient为了结合eureka,调用注册在eureka中的服务,所以zuul这里也是作为eureka的客户端。当然这里也可以使用@EnableDiscoveryClient,可以发现@EnableEurekaClient注解实现包含了@EnableDiscoveryClient,这里只用来调用eureka服务的话,两个都可以使用,如果要使用其他的,比如consul,那就只能用@EnableDiscoveryClient了。

测试:

启动eureka:8001, hello-service:8011,8012,zuul-service:8061

我们访问:http://localhost:8061/user-service/hello?name=zuul

表示路由成功。而且重复访问还可以发现默认使用了ribbon负载均衡。

接下来我们改成:

zuul.routes.user-service.path=/user-service/**
zuul.routes.user-service.url=http://localhost:8011

同样的,访问:http://localhost:8061/hello-service/hello?name=zuul

当然如果我们把连接改成百度网址,那么就直接跳转到百度去了。

既然在SpringCloud生态体系使用zuul,那么最好结合eureka ribbon使用。

三、网关过滤--(登录,权限校验)
如果在整个体系中,每个微服务都自己去管理用户状态,那显然是不可取的,所以一般都是放在服务网关中的。那么我们就需要在服务网关中统一处理用户登录状态,是否放行用户请求。

这里我们来实现zuul网关过滤器,实现每个接口获取参数中的access_token, 判断是否合法,合法则放行,不合法则拦截并提示错误。

package cn.demo.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 服务请求过滤器
 */
@Component
public class AccessFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);

    //路由之前
    @Override
    public String filterType() {
        return "pre";
    }

    //过滤的顺序
    @Override
    public int filterOrder() {
        return 0;
    }

    //这里可以写逻辑判断,是否要过滤,本文true,永远过滤
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        log.info("{} >>> {}", request.getMethod(), request.getRequestURL().toString());

        String access_token = request.getParameter("access_token");
        if(StringUtils.isBlank(access_token) || !"test".equals(access_token)){
            // zuul过滤该请求
            requestContext.setSendZuulResponse(false);//表示不继续转发该请求。
            requestContext.setResponseStatusCode(401);//返回的状态码,这里为401
            requestContext.setResponseBody("token invide无效");//返回的内容,可以指定为一串json
            log.info("the request {} is fail, the token is invide无效", request.getRequestURL().toString());
        } else {
            log.info("the request {} is ok", request.getRequestURL().toString());
        }
        return null;
    }
}

filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:

pre:路由之前
routing:路由之时
post: 路由之后
error:发送错误调用
filterOrder:过滤的顺序

shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。

run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

上面指定filterType:pre表示在路由之前拦截请求,shouldFilter始终为true,表示永远过滤,并执行run方法。

requestContext.setSendZuulResponse(false);表示不继续转发该请求。
requestContext.setResponseStatusCode(401);返回的状态码,这里为401
requestContext.setResponseBody("token is invalid");返回的内容,可以指定为一串json

测试
重新启动 zuul-service:8061

访问:http://localhost:8061/hello-service/hello?name=zuul

浏览器返回401

console 控制台日志输出:

接下来我们访问:http://localhost:8061/hello-service/hello?name=zuul&access_token=test

表示校验过滤,放行请求。

四、请求生命周期

从图中,我们可以看到,当外部HTTP请求到达API网关服务的时候,首先它会进入第一个阶段pre,在这里它会被pre类型的过滤器进行处理,该类型的过滤器主要目的是在进行请求路由之前做一些前置加工,比如请求的校验等。在完成了pre类型的过滤器处理之后,请求进入第二个阶段routing,也就是之前说的路由请求转发阶段,请求将会被routing类型过滤器处理,这里的具体处理内容就是将外部请求转发到具体服务实例上去的过程,当服务实例将请求结果都返回之后,routing阶段完成,请求进入第三个阶段post,此时请求将会被post类型的过滤器进行处理,这些过滤器在处理的时候不仅可以获取到请求信息,还能获取到服务实例的返回信息,所以在post类型的过滤器中,我们可以对处理结果进行一些加工或转换等内容。另外,还有一个特殊的阶段error,该阶段只有在上述三个阶段中发生异常的时候才会触发,但是它的最后流向还是post类型的过滤器,因为它需要通过post过滤器将最终结果返回给请求客户端

原文地址:https://www.cnblogs.com/2019lgg/p/11793051.html

时间: 2024-08-02 14:59:16

SpringCloud(六):服务网关zuul-API网关的相关文章

.Net微服务架构:API网关

本人建立了个人技术.工作经验的分享×××号,计划后续公众号同步更新分享,比在此更多具体.欢迎有兴趣的同学一起加入相互学习.基于上篇微服务架构分享,今天分享其中一个重要的基础组件"API网关". 一.引言 随着互联网的快速发展,当前以步入移动互联.物联网时代.用户访问系统入口也变得多种方式,由原来单一的PC客户端,变化到PC客户端.各种浏览器.手机移动端及智能终端等.同时系统之间大部分都不是单独运行,经常会涉及与其他系统对接.共享数据的需求.所以系统需要升级框架满足日新月异需求变化,支持

谈谈微服务中的 API 网关(API Gateway)

转载至:http://www.cnblogs.com/savorboard/p/api-gateway.html 背景 我们知道在微服务架构风格中,一个大应用被拆分成为了多个小的服务系统提供出来,这些小的系统他们可以自成体系,也就是说这些小系统可以拥有自己的数据库,框架甚至语言等,这些小系统通常以提供 Rest Api 风格的接口来被 H5, Android, IOS 以及第三方应用程序调用. 但是在UI上进行展示的时候,我们通常需要在一个界面上展示很多数据,这些数据可能来自于不同的微服务中,举

.NET微服务架构及API网关

一.MSA简介 1.1.MSA是什么 微服务架构MSA是Microservice Architecture的简称,它是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相通讯.互相配合,为用户提供最终价值.它与SOA之间的区别如下: SOA实现 微服务架构实现   企业级,自顶向下开展实施 团队级,自底向上开展实施   粒度大:服务由多个子系统组成 粒度细:一个系统被拆分成多个服务,且服务的定义更加清晰   重ESB:企业服务总线,集中式的服务架构 轻网关:无集中式总线,松散的服务

SpringCloud微服务负载均衡与网关

1.使用ribbon实现负载均衡ribbon是一个负载均衡客户端 类似nginx反向代理,可以很好的控制htt和tcp的一些行为.Feign默认集成了ribbon. 启动两个会员服务工程,端口号分别为8762.8763,订单服务使用负载均衡策略轮训到会员服务接口. 在上一篇SpringCloud微服务基础上修改Service_Menber项目代码区分端口项目 package com.zhang.controller; import org.springframework.beans.factor

SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理

前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由网关的过滤器Filter以及异常处理的教程. SpringCloud Zuul Filter 介绍 过滤器概述 Zuul的中心是一系列过滤器,能够在HTTP请求和响应的路由过程中执行一系列操作. 以下是Zuul过滤器的主要特征: 类型:通常在应用过滤器时在路由流程中定义阶段(尽管它可以是任何自定义字

微服务:服务注册发现+ API 网关+配置中心+配置中心+服务跟踪

服务注册发现服务注册就是维护一个登记簿,它管理系统内所有的服务地址.当新的服务启动后,它会向登记簿交待自己的地址信息.服务的依赖方直接向登记簿要 Service Provider 地址就行了.当下用于服务注册的工具非常多 ZooKeeper,Consul,Etcd, 还有 Netflix 家的 eureka 等.服务注册有两种 形式:客户端注册和第三方注册. 客户端注册(zookeeper) 客户端注册是服务自身要负责注册与注销的工作.当服务启动后向注册中心注册自身,当服务下线时注销自己.期间还

来自京东、唯品会对微服务编排、API网关、持续集成的实践分享(上)

架构师小组交流会:每期选一个时下最热门的技术话题进行实践经验分享. 第三期:微服务.微服务架构以其高度的弹性.灵活性和效率的巨大提升,快速受到各领域架构师和技术决策者的关注.它的基本理念是将一个肥大的系统拆分成若干小的服务组件,组件之间的通讯采用轻量的协议完成.我们本期小组交流会来探讨一下,现在互联网公司的微服务实践情况. 嘉宾:京东章耿.原唯品会石廷鑫.七牛陈爱珍 本文是对此次交流的整理,分了上下两篇文章. 第一轮:自由交流 京东章耿:大家好,我是京东基础架构部平台中间件的章耿,主要负责京东的

Net分布式系统之六:微服务之API网关

本人建立了个人技术.工作经验的分享微信号,计划后续公众号同步更新分享,比在此更多具体.欢迎有兴趣的同学一起加入相互学习.基于上篇微服务架构分享,今天分享其中一个重要的基础组件“API网关”. 一.引言 随着互联网的快速发展,当前以步入移动互联.物联网时代.用户访问系统入口也变得多种方式,由原来单一的PC客户端,变化到PC客户端.各种浏览器.手机移动端及智能终端等.同时系统之间大部分都不是单独运行,经常会涉及与其他系统对接.共享数据的需求.所以系统需要升级框架满足日新月异需求变化,支持业务发展,并

API网关性能比较:NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd(转)

前几天拜读了 OpsGenie 公司(一家致力于 Dev & Ops 的公司)的资深工程师 Turgay ?elik 博士写的一篇文章(链接在文末),文中介绍了他们最初也是采用 Nginx 作为单体应用的网关,后来接触到微服务架构后开始逐渐采用了其他组件. 我对于所做的工作或者感兴趣的技术,喜欢刨根问底,所以当读一篇文章时发现没有看到我想要看到的设计思想,我就会四处搜集资料,此外这篇文章涉及了我正在捣鼓的 Spring Cloud,所以我就决定写一篇文章,争取能从设计思路上解释为什么会有这样的性

微服务API网关

当你选择采用微服务构建自己的程序,则你需要考虑客户端怎样与后端服务交互.对于一个单体应用,仅有一个服务群提供服务(通过负载均衡器实现).在微服务架构里面,每一个服务都暴漏了一个服务器集群.本篇文章我们讨论它对于客户端通讯的影响和提出通过API网关的解决办法. 背景介绍 首先让我们想象一下一个购物的移动程序.它需要实现产品详情页展示,例如产品信息.库存信息.订单信息.购物车等.例如,下图显示了你将看到的产品信息: 尽管它仅仅是一个手机程序的详情页,它也显示了产品的一些信息.它不仅展示了一些产品的基