Zuul解决的问题

  • 作为系统的统一入口,屏蔽了系统内部各个微服务的细节
  • 可以与微服务治理框架结合,实现自动化的服务实例维护以及负载均衡的路由转发
  • 实现接口权限校验与微服务业务逻辑的解耦

搭建Zuul服务

zuul maven依赖

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

spring-cloud-starter-zuul包含zuul-core、spring-cloud-starter-hystrix、spring-cloud-starter-ribbon、spring-cloud-starter-actrator

主类上开启API网关服务功能

//@SpringCloudApplication = @SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
@EnableZuulProxy
@SpringCloudApplication
public class ApiGatewayApplication
{
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}

配置application.properties

spring.application.name=api-gateway
server.port=5555

实现简单的传统路由转发功能

只需要加入

#实现传统的路由转发功能
zuul.routes.api-a-url.path=/api-a-url/**
zuul.routes.api-a-url.url=http://localhost:8080/

所有符合/api-a-url/**规则的访问都将被路由转发到http://localhost:8080/地址上,也就是说当我们访问http://localhost:5555/api-a-url/hello的时候,

API网关服务会将该请求路由到http://localhost:8080/hello提供的微服务上

面向服务的路由

  • 加入Eureka依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
  • 配置路由
spring.application.name=api-gateway
server.port=5555 #实现传统的路由转发功能
#zuul.routes.api-a-url.path=/api-a-url/**
#zuul.routes.api-a-url.url=http://localhost:8080/ zuul.routes.api-a.path=/api-a/**
zuul.routes.api-a.serviceId=eureka-client zuul.routes.api-b.path=/api-b/**
zuul.routes.api-b.serviceId=feign-consumer #eureka.instance.hostname=localhost
#注册服务的注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/

注意与传统路由的区别,一个是面向url的,一个是面向服务的

请求过滤

请求过滤解决的问题

  • 将鉴权校验的非业务部分剥离出来,形成独立的业务服务
  • 微服务中不需要调用此业务服务进行鉴权校验

简单的示例

  • 创建过滤器
public class AccessFilter extends ZuulFilter
{
private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
//filterType:过滤器的类型,他决定过滤器会在请求的哪个生命周期中执行,pre代表会在请求被路由之前执行
@Override
public String filterType()
{
return "pre";
} //filterOrder过滤器执行顺序
@Override
public int filterOrder()
{
return 0;
}
//shouldFilter执行生效的条件
@Override
public boolean shouldFilter()
{
return true;
}
//过滤器的具体逻辑
@Override
public Object run()
{
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest(); log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString()); Object accessToken = request.getParameter("accessToken");
if(null == accessToken)
{
log.warn("access token is empty.");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
return null;
}
log.info("access token ok.");
return null;
}
}
  • 在主类中创建具体的bean,实例化过滤器
@EnableZuulProxy
@SpringCloudApplication
public class ApiGatewayApplication
{
@Bean
public AccessFilter accessFilter()
{
return new AccessFilter();
} public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}

访问http://localhost:5555/api-a/hello?accessToken=token返回hello world,访问http://localhost:5555/api-a/hello返回401错误

注意细节

  • 简化path与serviceId组合

    zuul.rotes.=.

    eg:zuul.routes.feign-consumer=/feign-consumer/**
  • zuul默认为每一个服务实例使用其服务名自动创建映射关系进行路由

    例如不配置路由的情况下,访问http://localhost:5555/eureka-client/hello?accessToken=token,可以返回hello world
  • 使用zuul.ignored-services=/user-service/**,可以跳过该服务,不创建改服务的路由

    例如:zuul.ignored-services=*,对所有服务不自动创建路由

自定义路由映射规则

eg: 想要将名称userService-v1的服务映射为/v1/userService/的路由

在主类中加入自定义规则

@Bean
public PatternServiceRouteMapper serviceRouteMapper()
{
return new PatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}"
);
}

当匹配表达式的时候,使用此映射规则;不匹配时,采用默认的映射规则

路径匹配

Ant风格

?:匹配任意单个字符

*:匹配任意数量的字符

**:匹配任意数量的字符,支持多级目录

匹配的顺序

路由的规则是通过LinkedHashMap保存的,是有序依次加入的,所以是按照配置的先后顺序匹配的。但是properties文件是无序的,如果要想按照先后顺序匹配,可以使用YAML配置文件

忽略表达式

使用zuul.ignored-patterns可以忽略掉API网关对路由的限制,eg:

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

表示任何访问//hello/的路由都不会得到映射,得不到返回内容

路由前缀

zuul.prefix=/api

Cookie与头信息

在请求路由时,zuul会默认过滤掉HTTP请求头信息中的一些敏感信息,防止他们被传递到下游的外部服务器。默认的敏感头信息通过zuul.sensitiveHeaders参数定义,

包括Cookie、Set-Cookie、Authorization三个属性

  • 全局为空覆盖默认值,不推荐
zuul.sensitiveHeaders=
  • 指定路由参数配置,推荐
#方法1:对指定路由开启自定义敏感头
zuul.routes.<router>.customSensitiveHeaders=true
#方法2:将指定路由的敏感头设置为空
zuul.routes.<router>.sensitiveHeaders=

重定向的问题

从访问的路由可以看出,访问成功后,http的url仍然是路由跳转前的web应用实例地址,而不是路由的地址,此问题导致spring security和shiro在登陆完成后,请求头信息中的状态码为302,请求响应头信息中的Location指向了具体的服务实例地址,而请求中的host信息缺指向了路由前的host。故网管进行路由转发前的Host信息没有设置正确。

解决方法:

zuul.addHostHeader=true

此解决方案适版本而定

Hystrix和Ribbon支持

Zuul天生拥有线程隔离和断路器的自我保护功能,以及对服务调用的客户端负载均衡功能。但是使用path与url的映射的路由转发不会采用HystrixCommand来包装,不具备线程隔离和断路器的保护功能,也不具备负载均衡的能力

参数配置

  • API网关路由转发请求的HystrixCommand执行超时时间的设置,单位为毫秒
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
  • 设置路由请求转发,创建请求连接的超时时间
ribbon.ConnectTimeout=2000

当此超时时间小于上面的超时时间时,会自动进行重试路由请求

当大于时,不会断路重连

  • 建立连接后的转发请求时间
ribbon.ReadTimeout=3000

短路重连规则同上

  • 关闭重试机制
#全局关闭
zuul.retryable=false
#指定路由关闭
zuul.routes.<route>.retryable=false

Spring cloud学习--Zuul01的更多相关文章

  1. spring cloud 学习(9) - turbine stream无法在eureka注册的解决办法

    turbine是啥就不多解释了,初次接触的可以移步spring cloud 学习(4) - hystrix 服务熔断处理 拉到最后看一下,turbine stream默认情况下启动成功后,eureka ...

  2. Spring Cloud学习(一):Eureka服务注册与发现

    1.Eureka是什么 Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的. Eureka ...

  3. spring cloud 学习资料

    spring cloud 学习资料 网址 拜托!面试请不要再问我Spring Cloud底层原理 https://mp.weixin.qq.com/s/ZH-3JK90mhnJPfdsYH2yDA

  4. Spring Boot和Spring Cloud学习资源推荐

    Spring Boot和Spring Cloud学习资源推荐   比较好的学习资源,分享一下. 1.Spring Boot官方文档:http://projects.spring.io/spring-b ...

  5. Spring Cloud 学习 之 Spring Cloud Eureka(源码分析)

    Spring Cloud 学习 之 Spring Cloud Eureka(源码分析) Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 ...

  6. 推荐几个Spring Cloud学习资料

    研究Spring Cloud也有一段时间了,手头上有一点收集的资料,分享给小伙伴们学习. 博客 1.跟我学Spring Cloud 2.周立|Spring Cloud 3.Spring Cloud基础 ...

  7. .net core+Spring Cloud学习之路 二

    前言: 原本计划这次写一下搭建eureka群集.但是发现上次写的只是服务的注册,忘了写服务的发现,所以这次先把服务发现补上去. 我们基于上篇文章,再新建两个.net core web api项目,分别 ...

  8. .net core+Spring Cloud学习之路 一

    文章开头唠叨两句. 2019年了,而自己参加工作也两年有余了,用一个词来概括这两年多的生活,就是:“碌碌无为”. 也不能说一点收获都没有,但是很少.2019来了,我立志要打破现状,改变自己,突破自我. ...

  9. spring cloud学习填坑笔记

    最近在学习spring cloud,由于学习资料具有普遍性,部分应个人原因导致的小细节问题,往往很难找到解决的办法.这特别记录一下自己遇到的一些问题. 一.eureka-server加入securit ...

随机推荐

  1. vue访问外部接口设置代理,解决跨域(vue-cli3.0)

    vue-cli3.0搭建的项目,平时访问内部接口配置了拦截器,今天需要调用天气预报的外部接口,发现跨域问题,通过配置代理解决. 1.在vue.config.js中配置代理 module.exports ...

  2. VS #include 【bits/bstdc++.h】出错

    目录 1. 本文地址 2. 按 3. 操作步骤 1. 本文地址 博客园:https://www.cnblogs.com/coco56/p/11163142.html 简书:https://www.ji ...

  3. linux创建相关待同步目录

    [root@rsync-server-1 ~]# mkdir /data/{web,web_data}/redhat.sx -p [root@rsync-server-1 ~]# tree /data ...

  4. 动态规划—triangle

    题目: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjace ...

  5. 二、冯式结构与哈佛结构及ARM处理器状态和处理器模式

    2.1 冯式结构与哈佛结构 2.1.1 两者的区别 如果是独立的存储架构和信号通道那就是哈佛结构,否则就是冯式结构 结构与是否统一编址没有关系,也与 CPU 没有关系,与计算机的整体设计有关 CACH ...

  6. group_by

    1.按照一个列或者多个列对数据分组 2.对每个组进行聚合操作 3. 对聚合后的结果进行判断 1. select avg(score) as score from teacher 2. select   ...

  7. java并发学习--第一章 线程的创建

    所谓的并发就是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行.所以我们看似几个线程在同时进行,其实在操作系统中 ...

  8. 传统IO拷贝与零拷贝技术比较

    1. 传统IO 由上面图知,传统io需要经过4次copy, 3次状态切换 第一次: 从硬盘 经过 DMA 拷贝 到 kernel buffer (内核buferr) 第二次: 从kernel buff ...

  9. 将HTML转IMAGE

    chrome --enable-logging --headless --disable-gpu --screenshot=d:\chrome.jpg --hide-scrollbars --wind ...

  10. MVC 无法将带 [] 的索引应用于“System.Dynamic.DynamicObject”类型的表达式

    无法将带 [] 的索引应用于“System.Dynamic.DynamicObject”类型的表达式 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代 ...