什么是API网关:

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

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

主要功能是对请求的路由和过滤。

1.整体资源不够的情况下,需要关掉一些服务,待稳定了,再重启。2.校验token的情况。

所有从设备或网站来的请求都会经过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过滤器将最终结果返回给请求客户端

SpringCloud(六):服务网关zuul-API网关(服务降级和过滤)的更多相关文章

  1. spring cloud+dotnet core搭建微服务架构:Api网关(三)

    前言 国庆假期,一直没有时间更新. 根据群里面的同学的提问,强烈推荐大家先熟悉下spring cloud.文章下面有纯洁大神的spring cloud系列. 上一章最后说了,因为服务是不对外暴露的,所 ...

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

    前言 又是很久没写博客了,最近一段时间换了新工作,比较忙,所以没有抽出来太多的时间写给关注我的粉丝写一些干货了,就有人问我怎么最近没有更新博客了,在这里给大家抱歉. 那么,在本篇文章中,我们就一起来探 ...

  3. spring cloud+.net core搭建微服务架构:Api网关(三)

    前言 国庆假期,一直没有时间更新. 根据群里面的同学的提问,强烈推荐大家先熟悉下spring cloud.文章下面有纯洁大神的spring cloud系列. 上一章最后说了,因为服务是不对外暴露的,所 ...

  4. 微服务中的 API 网关(API Gateway)

    API 网关(API Gateway)提供高性能.高可用的 API 托管服务,帮助用户对外开放其部署在 ECS.容器服务等云产品上的应用,提供完整的 API 发布.管理.维护生命周期管理.用户只需进行 ...

  5. Spring Cloud 微服务三: API网关Spring cloud gateway

    前言:前面介绍了一款API网关组件zuul,不过发现spring cloud自己开发了一个新网关gateway,貌似要取代zuul,spring官网上也已经没有zuul的组件了(虽然在仓库中可以更新到 ...

  6. Chris Richardson微服务翻译:构建微服务之使用API网关

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关(本文) 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服 ...

  7. .NET微服务架构及API网关

    一.MSA简介 1.1.MSA是什么 微服务架构MSA是Microservice Architecture的简称,它是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相通讯.互相配合, ...

  8. SpringCloud微服务项目实战 - API网关Gateway详解实现

    前面讲过zuul的网关实现,那为什么今天又要讲Spring Cloud Gateway呢?原因很简单.就是Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用 ...

  9. Spring Cloud 微服务二:API网关spring cloud zuul

    前言:本章将继续上一章Spring Cloud微服务,本章主要内容是API 网关,相关代码将延续上一章,如需了解请参考:Spring Cloud 微服务一:Consul注册中心 Spring clou ...

  10. spring cloud微服务快速教程之(五) ZUUL API网关中心

    0-前言 我们一个个微服务构建好了,外部的应用如何来访问内部各种各样的微服务呢?在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服务.当添加API网 ...

随机推荐

  1. 如何快速将多个excel表格的所有sheet合并到一个sheet中

    1.将需要合并的excel文件放在同一个文件夹下: 2.新建一个excel表格并打开,右键sheet1,查看代码,然后复制下方的代码到代码框里,点击菜单栏中的“运行”–“运行子过程/用户窗体”,等待程 ...

  2. .NET Core和无服务器框架

    无服务器框架是一个云提供商无关的工具包,旨在帮助构建,管理和部署无服务器组件的操作,以实现完整的无服务器架构或不同功能即服务(FaaS).无服务器框架的主要目标是为开发人员提供一个界面,该界面抽象出云 ...

  3. XNginx升级记录

    之前的博文提到过,XNginx - nginx 集群可视化管理工具, 开发完成后一直稳定运行,直到前面因为一个站点的proxy站点配置问题,导致需要修改nginx 配置文件模板,因此借此机会对系统做了 ...

  4. CAD制图初学入门如何学好CAD?CAD大神总结5点诀窍,必须收藏

    现在有很多的小伙伴们都加入到了CAD这个大家庭中,一开始都是都是一脸懵的状态,更不知要从何入手! 小编才开始也是,但是只要掌握好CAD的技巧和脊髓,一切都不是事.CAD大神总结5点诀窍,悄悄告诉你,必 ...

  5. JavaScript定时器(Timer)

    版权声明:本文为博主原创文章,未经博主允许不得转载.https://www.cnblogs.com/gaoguowen/p/11119088.html 什么是定时器 简单来说就是在一段时间间隔后执行一 ...

  6. ionic项目打包+部署

    环境: 1.ionic 2.angular-cli  开发 1.CTRL C + CTRL V 2.图片路径的问题 使用‘assets/xxxxx.jpg’,而不使用‘../../assets/xxx ...

  7. axios统一接口管理及优化

    之前我写了一篇文章,分享了自己的项目中对于接口管理的方法.总结下来就是:定义接口文件--withAxios导出--调用接口方法.这样实现了接口的统一管理和调用接口的语义化与简单化. 根据在项目的使用, ...

  8. C lang:Pointer operation

    Xx_Pointer opteration Do not dereference initialized Pointers Ax_Code #include<stdio.h> int ma ...

  9. arcgis api 4.x for js 结合 Echarts4 实现散点图效果(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 4.x for js:esri 官网 api,里面详细的介绍 arcgis api 4.x 各个类 ...

  10. 基于Python和Xtrbackup的自动化备份与还原实现

    xtrabackup是一个MySQL备份还原的常用工具,实际使用过程应该都是shell或者python封装的自动化脚本,尤其是备份.对还原来说,对于基于完整和增量备份的还原,还原差异备份需要指定增量备 ...