getaway网关转发去前缀_服务网关Zuul

服务网关Zuul

(Spring Cloud高级)

一、什么是网关服务

zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用。

Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。

zuul的例子可以参考netflix在github上的 simple webapp,可以按照netflix 在github wiki 上文档说明来进行使用。

服务网关 = 路由转发 + 过滤器

1、路由转发:接收一切外界请求,转发到后端的微服务上去;

2、过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)。

1为什么要使用网关

上述所说的横切功能(以权限校验为例)可以写在三个位置:

  • 每个服务自己实现一遍
  • 写到一个公共的服务中,然后其他所有服务都依赖这个服务
  • 写到服务网关的前置过滤器中,所有请求过来进行权限校验

第一种,缺点太明显,基本不用;


第二种,相较于第一点好很多,代码开发不会冗余,但是有两个缺点:

由于每个服务引入了这个公共服务,那么相当于在每个服务中都引入了相同的权限校验的代码,使得每个服务的jar包大小无故增加了一些,尤其是对于使用docker镜像进行部署的场景,jar越小越好;

由于每个服务都引入了这个公共服务,那么我们后续升级这个服务可能就比较困难,而且公共服务的功能越多,升级就越难,而且假设我们改变了公共服务中的权限校验的方式,想让所有的服务都去使用新的权限校验方式,我们就需要将之前所有的服务都重新引包,编译部署。

而服务网关恰好可以解决这样的问题:

将权限校验的逻辑写在网关的过滤器中,后端服务不需要关注权限校验的代码,所以服务的jar包中也不会引入权限校验的逻辑,不会增加jar包大小;

如果想修改权限校验的逻辑,只需要修改网关中的权限校验过滤器即可,而不需要升级所有已存在的微服务。

所以,需要服务网关!!!

6e21140eeb031e598666a23c4d95745e.png

2 网关解决了什么问题

2c05062800bbdf40f45b4284798517cb.png

二、 编写网关服务入门案例

1 创建项目

fcc49b840bc64f040cbfffa4bc87d462.png

2修改pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.13.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>

<groupId>com.bjsxt</groupId>

<artifactId>zuul-gateway</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</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>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.SR5</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

3修改配置文件

spring.application.name=zuul-gateway

server.port=9020

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

4修改启动类

@EnableZuulProxy注解的作用是什么?

Sets up a Zuul server endpoint and installs some reverse proxy filters in it, so it can forward requests to backend servers. The backends can be registered manually through configuration or via DiscoveryClient.

package com.bjsxt;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy

@SpringBootApplication

public class ZuulApplication {

public static void main(String[] args) {

SpringApplication.run(ZuulApplication.class, args);

}

}

5通过网关请求服务

  • 启动该网关服务
  • 启动e-book-product-provider服务
  • 访问http://localhost:9001/product/findAll

e98d7f85830a597d0c6643c1a8b60c4b.png
  • 访问http://localhost:9020/e-book-product-provider/product/findAll

a4d0e45f01a03f80b40aaac39831a696.png

http://网关服务地址:网关服务端口/访问的服务的名称/访问的服务中的接口的地址

三、路由器的4种路由规则方法

1创建项目

79f01c697fc0b8000c6dff21bf81df7f.png

Pom文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.13.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>

<groupId>com.bjsxt</groupId>

<artifactId>zuul-gateway-route</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</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>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.SR5</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

启动类:

package com.bjsxt;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy

@SpringBootApplication

public class ZuulRouteApplication {

public static void main(String[] args) {

SpringApplication.run(ZuulRouteApplication.class, args);

}

}

2采用URL指定路由方式

2.1修改配置文件配置路由规则

spring.application.name=zuul-gateway-route

server.port=9030

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

# 1 ###################### 路由指定:URL指定 #############################

# URL匹配关键字,如果包含关键字就跳转到指定的URL中

# 下面第二个点到第三个点之间的是服务名

zuul.routes.e-book-product-provider.path=/e-book-product-provider/**

zuul.routes.e-book-product-provider.url=http://127.0.0.1:9001/

2.2测试

  • 启动zuul-gateway-route
  • 启动e-book-product-provider
  • 访问http://localhost:9030/e-book-product-provider/product/findAll

949d3fd25fa806b88e3a1dfa328fb3a5.png

2.3通配符含义

bf6b5181dfe6efd23061b36760aad681.png

3采用服务名称指定路由方式

方式一:

spring.application.name=zuul-gateway-route

server.port=9030

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

# 1 ###################### 路由指定:URL指定 #############################

# URL匹配关键字,如果包含关键字就跳转到指定的URL中

# 下面第二个点到第三个点之间的是服务名

#zuul.routes.e-book-product-provider.path=/e-book-product-provider/**

#zuul.routes.e-book-product-provider.url=http://127.0.0.1:9001/

## 2 ###################### 路由指定:服务指定1 #############################

##将路径的/suibian/引到eureka的e-book-product-provider服务上

##规则:zuul.routes.路径名.path 这个路径名可以随便,但是一般使用服务名

##规则:zuul.routes.路径名.serviceId=eureka的服务名

zuul.routes.e-book-product-provider.path=/suibian/**

zuul.routes.e-book-product-provider.serviceId=e-book-product-provider

测试:

  • 启动e-book-product-provider
  • 启动zuul-gateway-route
  • 访问http://localhost:9030/suibian/product/findAll

f67bf39f49b140181ea0acd167df3e4c.png

方式二:

spring.application.name=zuul-gateway-route

server.port=9030

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

# 1 ###################### 路由指定:URL指定 #############################

# URL匹配关键字,如果包含关键字就跳转到指定的URL中

# 下面第二个点到第三个点之间的是服务名

#zuul.routes.e-book-product-provider.path=/e-book-product-provider/**

#zuul.routes.e-book-product-provider.url=http://127.0.0.1:9001/

## 2 ###################### 路由指定:服务指定1 #############################

##将路径的/suibian/引到eureka的e-book-product-provider服务上

##规则:zuul.routes.路径名.path 这个路径名可以随便,但是一般使用服务名

##规则:zuul.routes.路径名.serviceId=eureka的服务名

#zuul.routes.e-book-product-provider.path=/suibian/**

#zuul.routes.e-book-product-provider.serviceId=e-book-product-provider

## 3 ###################### 路由指定:服务指定2 #############################

#zuul.routes后面跟着的是服务名,服务名后面跟着的是路径规则,这种配置方式更简单。

zuul.routes.e-book-product-provider.path=/suibian/*

测试:

  • 启动e-book-product-provider
  • 启动zuul-gateway-route
  • 访问http://localhost:9030/suibian/product/findAll

539ac7970110acfd86ae02d339a04d22.png

4路由的排除方法

排除路由,也就是该路由器会忽悠某几个服务,即使客户端发送了请求也访问不了

spring.application.name=zuul-gateway-route

server.port=9030

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

## 4 ###################### 路由排除:排除某几个服务#############################

##排除后,这个地址将为空http://127.0.0.1:9030/e-book-product-provider/product/findAll

## 多个服务逗号隔开

zuul.ignored-services=e-book-product-provider

测试:

  • 启动e-book-product-provider
  • 启动zuul-gateway-route
  • 访问http://localhost:9030/e-book-product-provider/product/findAll

d0f0ccc1f4114b668a9946c5c21aed5c.png

直接404,但是还是可以通过http://127.0.0.1:9001/product/findAll来直接访问原本的服务

949ad7ef37d658fe8b0733a57546f2de.png

如果有多个服务要排除,服务名称通过","连接

778ca18f09775aaa8faf0f35178f098f.png

由于服务太多,不可能手工一个个加,故路由排除所有服务,然后针对要路由的服务进行手工加

spring.application.name=zuul-gateway-route

server.port=9030

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

## 5 ###################### 路由排除:排除所有服务#############################

#由于服务太多,不可能手工一个个加,故路由排除所有服务,然后针对要路由的服务进行手工加

zuul.ignored-services=*

zuul.routes.e-book-order-provider.path=/e-book-order-provider/**

测试:

  • 启动e-book-product-provider
  • 启动e-book-order-provider
  • 启动zuul-gateway-route
  • 访问http://localhost:9030/e-book-product-provider/product/findAll

ca7e4e917ba8343c25151b8a164bff88.png

因为被屏蔽了,并且只开启了order服务

  • 访问http://localhost:9030/e-book-order-provider/order/findAll

ac8f8fbea0010d4bd11ff036724592ad.png

也可以通过排除指定关键字的路径

spring.application.name=zuul-gateway-route

server.port=9030

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

## 6 ###################### 路由排除:排除指定关键字的路径#############################

# 排除所有包括/list/的路径

zuul.ignored-patterns=/**/findAll/**

zuul.routes.e-book-order-provider.path=/suibian/**

测试:

  • 启动e-book-order-provider
  • 启动zuul-gateway-route
  • 访问http://localhost:9030/suibian/order/findAll

23b50520d4e65d867faaa0ed23ba8888.png
  • 访问http://localhost:9030/suibian/order/findOrderById?orderid=1011

63db20e68ff31a4e97a52d8c6b0e8350.png

5路由的添加前缀方法

修改zuul-gateway-route配置文件:

spring.application.name=zuul-gateway-route

server.port=9030

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

## 7 ############### 路由添加前缀,为所有路径添加前缀 ############

## http://127.0.0.1:9030/e-book-product-provider/product/findAll

## 得改为

## http://127.0.0.1:9030/api/e-book-product-provider/product/findAll

zuul.prefix=/api

zuul.routes.e-book-product-provider.path=/e-book-product-provider/**

测试:

  • 启动e-book-product-provider
  • 启动zuul-gateway-route
  • 访问http://127.0.0.1:9030/api/e-book-product-provider/product/findAll

06a574e30edf39258fddbf7320f446a9.png
  • 访问http://127.0.0.1:9030/e-book-product-provider/product/findAll

f5e68d863aa327c11fcaf886207d3a69.png

四、自定义网关过滤器

1编写网关过滤器

1.1创建项目

c157df7585b030fce6688cda0e17dab5.png

1.2修改pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.13.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>

<groupId>com.bjsxt</groupId>

<artifactId>zuul-gateway-filter</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</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>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.SR5</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

1.3修改配置文件

spring.application.name=zuul-gateway-filter

server.port=9020

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

1.4创建过滤器

package com.bjsxt.filter;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;

import com.netflix.zuul.context.RequestContext;

@Component

public class LogFilter extends ZuulFilter {

private Logger logger = LoggerFactory.getLogger(LogFilter.class);

//是否开启过滤器:默认为false不开启

@Override

public boolean shouldFilter() {

return true;

}

//过滤内容:在run方法编写过滤逻辑

@Override

public Object run() {

//

RequestContext currentContext = RequestContext.getCurrentContext();

HttpServletRequest request = currentContext.getRequest();

http://logger.info("LogFilter.....method={},url={}",request.getMethod(),request.getRequestURI());

return null;

}

//过滤器类型:通过过滤器类型决定了过滤器执行的时间

@Override

public String filterType() {

return "pre";

}

//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高

@Override

public int filterOrder() {

return 0;

}

}

1.5修改启动类

package com.bjsxt;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy

@SpringBootApplication

public class ZuulFilterApplication {

public static void main(String[] args) {

SpringApplication.run(ZuulFilterApplication.class, args);

}

}

1.6测试

  • 启动e-book-product-provider
  • 启动zuul-gateway-filter
  • 访问http://localhost:9020/e-book-product-provider/product/findAll

fb82a06f1b52888a32db96af287ae28a.png
  • 查看控制台

bc3acf425770ddfa48472bf1c612f7c2.png

2过滤器类型

4805bb7c012ad76feba0f15ec8c0d71f.png

Routing:路由规则去请求服务去了,这个时候就会执行

3 Zuul 请求的生命周期

b657f2e0ca9881458be036bf727d0608.png

4采用网关过滤器实现权限验证

需求:在网关过滤器中通过Token判断用户是否登录

再次:说一下token的原理:

Token就是你登陆的时候,我在redis或者其他分布式缓存中添加token的信息,并且将token的键作为cookie返回回去。下次请求时,先判断有没有token,然后去redis里面查询判断token对不对,然后决定是否要进行请求转发

4.1创建项目

263b5a1104adfc734dd4e141a5f47f6e.png

4.2修改pom文件添zuul坐标

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.13.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>

<groupId>com.bjsxt</groupId>

<artifactId>zuul-gateway-example</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</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>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.SR5</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

4.3修改配置文件

spring.application.name=zuul-gateway-example

server.port=9020

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

4.4创建AccessFilter

package com.bjsxt.filter;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;

import com.netflix.zuul.context.RequestContext;

@Component

public class AccessFilter extends ZuulFilter {

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

//是否开启过滤器:默认为false不开启

@Override

public boolean shouldFilter() {

return true;

}

//过滤内容:在run方法编写过滤逻辑

@Override

public Object run() {

//获取请求上下文

RequestContext currentContext = RequestContext.getCurrentContext();

HttpServletRequest request = currentContext.getRequest();

http://logger.info("--------------pre1--------------------");

//获取表单中的token

String token = request.getParameter("token");

//对token做判断

if(token==null) {

logger.warn("token is null..................");

//代表请求结束。不在继续向下请求

currentContext.setSendZuulResponse(false);

//添加一个响应的状态码

currentContext.setResponseStatusCode(401);

//响应内容

currentContext.setResponseBody("{result:"token is null"}");

//响应类型

currentContext.getResponse().setContentType("text/html;charset=utf-8");

}else {

//访问redis服务 进行验证(看看登陆是否过期)

http://logger.info("token is ok...................");

}

return null;

}

//过滤器类型:通过过滤器类型决定了过滤器执行的时间

@Override

public String filterType() {

return "pre";

}

//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高

@Override

public int filterOrder() {

return 0;

}

}

4.5修改启动类

package com.bjsxt;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy

@SpringBootApplication

public class ZuulExampleApplication {

public static void main(String[] args) {

SpringApplication.run(ZuulExampleApplication.class, args);

}

}

4.6测试

  • 启动zuul-gateway-example
  • 启动e-book-product-provider
  • 访问http://localhost:9020/e-book-product-provider/product/findAll

c29cb0fd89710d230fee190e2653ec5a.png
  • 访问http://localhost:9020/e-book-product-provider/product/findAll?token=sad

a5d436fa3e1eac41bed9c3c90d55f6fe.png

5网关过滤器执行顺序与post类型演示

5.1网关过滤器执行顺序演示

5.1.1AccessFilter

package com.bjsxt.filter;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;

import com.netflix.zuul.context.RequestContext;

@Component

public class AccessFilter extends ZuulFilter {

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

//是否开启过滤器:默认为false不开启

@Override

public boolean shouldFilter() {

return true;

}

//过滤内容:在run方法编写过滤逻辑

@Override

public Object run() {

//获取请求上下文

RequestContext currentContext = RequestContext.getCurrentContext();

HttpServletRequest request = currentContext.getRequest();

http://logger.info("--------------pre1--------------------");

//获取表单中的token

String token = request.getParameter("token");

//对token做判断

if(token==null) {

logger.warn("token is null..................");

//代表请求结束。不在继续向下请求

currentContext.setSendZuulResponse(false);

//添加一个响应的状态码

currentContext.setResponseStatusCode(401);

//响应内容

currentContext.setResponseBody("{result:"token is null"}");

//响应类型

currentContext.getResponse().setContentType("text/html;charset=utf-8");

}else {

//访问redis服务 进行验证(看看登陆是否过期)

http://logger.info("token is ok...................");

}

return null;

}

//过滤器类型:通过过滤器类型决定了过滤器执行的时间

@Override

public String filterType() {

return "pre";

}

//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高

@Override

public int filterOrder() {

return 0;

}

}

5.1.2AccessFilter2

package com.bjsxt.filter;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;

@Component

public class AccessFilter2 extends ZuulFilter {

private static final Logger logger = LoggerFactory.getLogger(AccessFilter2.class);

//是否开启过滤器:默认为false不开启

@Override

public boolean shouldFilter() {

return true;

}

//过滤内容:在run方法编写过滤逻辑

@Override

public Object run() {

logger.info("--------------pre2--------------------");

return null;

}

//过滤器类型:通过过滤器类型决定了过滤器执行的时间

@Override

public String filterType() {

return "pre";

}

//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高

@Override

public int filterOrder() {

return 1;

}

}

5.2post类型演示

package com.bjsxt.filter;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;

@Component

public class PostFilter extends ZuulFilter {

private static final Logger logger = LoggerFactory.getLogger(PostFilter.class);

//是否开启过滤器:默认为false不开启

@Override

public boolean shouldFilter() {

return true;

}

//过滤内容:在run方法编写过滤逻辑

@Override

public Object run() {

http://logger.info("--------------post--------------------");

return null;

}

//过滤器类型:通过过滤器类型决定了过滤器执行的时间

@Override

public String filterType() {

return "post";

}

//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高

@Override

public int filterOrder() {

return 1;

}

}

测试前面三个filter:

  • 启动zuul-gateway-example
  • 启动e-book-product-provider
  • 访问http://localhost:9020/e-book-product-provider/product/findAll?token=sad
  • 查看后台

92ca1151d56243a6db7a96ee3bc8e76d.png

总结一下执行顺序就是:

先分好过滤器类型,然后在类型之上分顺序

6采用网关过滤器对系统异常同一处理

6.1创建ErrorFilter

package com.bjsxt.filter;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;

@Component

public class ErrorFilter extends ZuulFilter {

private static final Logger logger = LoggerFactory.getLogger(ErrorFilter.class);

//是否开启过滤器:默认为false不开启

@Override

public boolean shouldFilter() {

return true;

}

//过滤内容:在run方法编写过滤逻辑

@Override

public Object run() {

http://logger.info("--------------error--------------------");

return null;

}

//过滤器类型:通过过滤器类型决定了过滤器执行的时间

@Override

public String filterType() {

return "error";

}

//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高

@Override

public int filterOrder() {

return 1;

}

}

6.2创建处理异常响应的控制器

package com.bjsxt.filter;

import org.springframework.boot.autoconfigure.web.ErrorController;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class ExceptionHandler implements ErrorController {

@Override

public String getErrorPath() {

return "/error";

}

@GetMapping("/error")

public String error() {

return "你的服务出错了,哈哈哈哈哈哈哈哈哈!";

}

}

因为出错时,SpringBoot项目会自动地去寻找页面/error,所以我们 哈哈哈

6.3修改AccessFilter2

让它抛出一个异常

package com.bjsxt.filter;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;

@Component

public class AccessFilter2 extends ZuulFilter {

private static final Logger logger = LoggerFactory.getLogger(AccessFilter2.class);

//是否开启过滤器:默认为false不开启

@Override

public boolean shouldFilter() {

return true;

}

//过滤内容:在run方法编写过滤逻辑

@Override

public Object run() {

http://logger.info("--------------pre2--------------------");

throw new RuntimeException("error");

}

//过滤器类型:通过过滤器类型决定了过滤器执行的时间

@Override

public String filterType() {

return "pre";

}

//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高

@Override

public int filterOrder() {

return 1;

}

}

6.4测试

  • 启动zuul-gateway-example
  • 启动e-book-product-provider
  • 访问http://localhost:9020/e-book-product-provider/product/findAll?token=sad
  • 查看后台

6eae1dae9e1fe1c67b31bda9d9bb5c73.png

一堆异常信息

93f331f2884ff5e29c7ede64cab86d93.png

五、网关容错

1zuul和hystrix无缝结合

在zuul的jar包中包含了hystrix的jar包。所以我们不需要在项目中添加Hystrix的坐

2访问网关服务的数据监控流

  • 启动zuul-gateway
  • 启动e-book-product-provider
  • 启动srpingcloud-eureka-consumer-ribbon-dashboard-view
  • 访问http://localhost:9020/e-book-product-provider/product/findAll

861560fd788026b79130d13150d4addf.png
  • 访问http://localhost:9020/hystrix.stream

6c2d17e23b4d41d75a425a26d90645bf.png

3启动dashboard-view服务通过可视化界面查看监控数据

  • 访问http://localhost:1001/hystrix

9101ad957f6f2096c35fadfb3549124f.png

4在网关中实现对服务降级处理

4.1创建项目

98d78a36fcc635b367485181f1aab882.png

4.2修改pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.13.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>

<groupId>com.bjsxt</groupId>

<artifactId>zuul-gateway-fallback</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</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>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.SR5</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

4.3修改配置文件

spring.application.name=zuul-gateway-fallback

server.port=9020

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

4.4添加ProviderProductFallback类

package com.bjsxt;

import java.io.ByteArrayInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.nio.charset.Charset;

import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;

import org.springframework.http.HttpHeaders;

import org.springframework.http.HttpStatus;

import org.springframework.http.MediaType;

import org.springframework.http.client.ClientHttpResponse;

import org.springframework.stereotype.Component;

@Component

public class ProductProviderFallback implements ZuulFallbackProvider {

//给定对哪个服务做降级处理

@Override

public String getRoute() {

return "e-book-product-provider";

}

//当服务无法执行时,该方法返回托底信息

@Override

public ClientHttpResponse fallbackResponse() {

return new ClientHttpResponse() {

//设置响应的头信息

@Override

public HttpHeaders getHeaders() {

HttpHeaders httpHeaders = new HttpHeaders();

MediaType mt = new MediaType("application", "json", Charset.forName("utf-8"));

httpHeaders.setContentType(mt);

return httpHeaders;

}

//设置响应体

@Override

public InputStream getBody() throws IOException {

String content = "商品服务不可用,请与管理员联系";

return new ByteArrayInputStream(content.getBytes());

}

//ClientHttpResponse的fallback的状态码 返回String

@Override

public String getStatusText() throws IOException {

return getStatusCode().getReasonPhrase();

}

//ClientHttpResponse的fallback的状态码 返回HttpStatus

@Override

public HttpStatus getStatusCode() throws IOException {

return HttpStatus.OK;

}

//ClientHttpResponse的fallback的状态码 返回int

@Override

public int getRawStatusCode() throws IOException {

return getStatusCode().value();

}

@Override

public void close() {

}

};

}

}

4.5修改启动类

package com.bjsxt;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy

@SpringBootApplication

public class ZuulFallbackApplication {

public static void main(String[] args) {

SpringApplication.run(ZuulFallbackApplication.class, args);

}

}

4.6测试

  • 启动e-book-product-provider
  • 启动zuul-gateway-fallback
  • 访问http://localhost:9020/e-book-product-provider/product/findAll

688caac7df525cd98bc034b0c494b26d.png
  • 关闭e-book-product-provider
  • 再次访问http://localhost:9020/e-book-product-provider/product/findAll

7f188f8986fb1db97d24ead70eea3a57.png

如果要对多个服务做降级处理,只需要创建多个这样地类即可

六、在高并发情况下,网关实现限流达到自我保护

1创建项目

eaab20c7f0df5b9a9b9f16d7b17a2f03.png

2修改pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.13.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>

<groupId>com.bjsxt</groupId>

<artifactId>zuul-gateway-ratelimit</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>com.marcosbarbero.cloud</groupId>

<artifactId>spring-cloud-zuul-ratelimit</artifactId>

<version>1.3.4.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</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>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.SR5</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

3修改配置文件

3.1修改一下启动类

package com.bjsxt;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy

@SpringBootApplication

public class ZuulRateLimitApplication {

public static void main(String[] args) {

SpringApplication.run(ZuulRateLimitApplication.class, args);

}

}

3.2全局限流

针对每一个服务都有效果

spring.application.name=zuul-gateway-ratelimit

server.port=9020

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

zuul.routes.e-book-product-provider.path=/product/**

zuul.routes.e-book-product-provider.serviceId=e-book-product-provider

zuul.routes.e-book-order-provider.path=/order/**

zuul.routes.e-book-order-provider.serviceId=e-book-order-provider

#全局配置限流

zuul.ratelimit.enabled=true

##60s 内请求超过 3 次,服务端就抛出异常,60s 后可以恢复正常请求

zuul.ratelimit.default-policy.limit=3

zuul.ratelimit.default-policy.refresh-interval=60

##针对 IP 进行限流,不影响其他 IP

zuul.ratelimit.default-policy.type=origin

测试:

  • 启动e-book-order-provider
  • 启动e-book-product-provider
  • 启动zuul-gateway-ratelimit
  • 连续访问http://localhost:9020/product/product/findAll
  • 连续访问http://localhost:9020/order/order/findAll

皆会出现:

e7846a890c5f000e9661e9c06a51fb12.png

3.3局部限流

spring.application.name=zuul-gateway-ratelimit

server.port=9020

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

zuul.routes.e-book-product-provider.path=/product/**

zuul.routes.e-book-product-provider.serviceId=e-book-product-provider

zuul.routes.e-book-order-provider.path=/order/**

zuul.routes.e-book-order-provider.serviceId=e-book-order-provider

#全局配置限流

#zuul.ratelimit.enabled=true

##60s 内请求超过 3 次,服务端就抛出异常,60s 后可以恢复正常请求

#zuul.ratelimit.default-policy.limit=3

#zuul.ratelimit.default-policy.refresh-interval=60

##针对 IP 进行限流,不影响其他 IP

#zuul.ratelimit.default-policy.type=origin

# 局部限流:针对某个服务进行限流

##开启限流

zuul.ratelimit.enabled=true

##60s 内请求超过 3 次,服务端就抛出异常,60s 后可以恢复正常请求

zuul.ratelimit.policies.e-book-product-provider.limit=3

zuul.ratelimit.policies.e-book-product-provider.refresh-interval=60

##针对某个 IP 进行限流,不影响其他 IP

zuul.ratelimit.policies.e-book-product-provider.type=origin

以上配置只针对e-book-product的服务一分钟内最多访问3次,超过就会限流,对其他服务就没有影响

测试:

  • 启动e-book-order-provider
  • 启动e-book-product-provider
  • 启动zuul-gateway-ratelimit
  • 连续访问http://localhost:9020/product/product/findAll
  • 连续访问http://localhost:9020/order/order/findAll

46aa338e86cd1f1dd201bb92dc5bac70.png

这个三次之后就会这样,另外的不会

4网关限流参数

a3bed293ca42169256a942855a4110f4.png

限流信息的存储

七、zuul性能调优:网关的2层超时调优

1创建项目

01c3dd80100ac833f31c5e97e56b8190.png

2修改pom文件添加zuul依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.13.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>

<groupId>com.bjsxt</groupId>

<artifactId>zuul-gateway-timeout</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</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>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Dalston.SR5</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

3修改e-book-product-provider的ProductServiceImpl

package com.book.product.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.book.product.mapper.ProductMapper;

import com.book.product.pojo.Product;

import com.book.product.pojo.ProductExample;

@Service

public class ProductServiceImpl {

@Autowired

private ProductMapper productMapper;

/**

* 查询所有商品

*/

public List<Product> findProductAll(){

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

ProductExample example = new ProductExample();

List<Product> list = productMapper.selectByExampleWithBLOBs(example);

return list;

}

}

4测试一波

  • 启动e-book-product-provider
  • 启动zuul-gateway-timeout
  • 访问http://localhost:9020/e-book-product-provider/product/findAll

335386a05a94d4bda9daf5f2bfe59f5c.png

5修改zuul-gateway-timeout的配置文件

spring.application.name=zuul-gateway

server.port=9020

#设置服务注册中心地址,指向另一个注册中心

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

#第一层 hystrix 超时时间设置

#默认情况下是线程池隔离,超时时间 1000ms

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=8000

#第二层 ribbon 超时时间设置:设置比第一层小

# 请求连接的超时时间: 默认 5s

ribbon.ConnectTimeout=5000

# 请求处理的超时时间: 默认 5s

ribbon.ReadTimeout=5000

刚创建时只有上面的未红色标注的

6测试2

  • 重启zuul-gateway-timeout
  • 启动e-book-product-provider
  • 访问http://localhost:9020/e-book-product-provider/product/findAll

6a16cc5875bbb719853954b1e8fc8886.png

然后访问:虽然卡顿了2秒,但是之后还是访问到了请求

7超时调优图解

d0808bd34084ad57d632817efe3ede94.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值