看看大牛是怎么理解微服务网关与用户身份识别,创建Zuul网关服务

Zuul的基础使用

Zuul是Netflix公司的开源网关产品,可以和Eureka、Ribbon、Hystrix等组件配合使用。Zuul的规则引擎和过滤器基本上可以用任何JVM语言编写,内置支持Java和Groovy。

在Spring Cloud框架中,Zuul的角色是网关,负责接收所有的REST请求(如网页端、App端等),然后进行内部转发,是微服务提供者集群的流量入口。本书将Zuul称为内部网关,以便和Nginx外部网关相区分。

Zuul的功能大致有:

(1)路由:将不同REST请求转发至不同的微服务提供者,其作用类似于Nginx的反向代理。同时,也起到了统一端口的作用,将很多微服务提供者的不同端口统一到了Zuul的服务端口。

(2)认证:网关直接暴露在公网上时,终端要调用某个服务,通常会把登录后的token(令牌)传过来,网关层对token进行有效性验证。如果token无效(或没有token),就不允许访问REST服务。可以结合Spring Security中的认证机制完成Zuul网关的安全认证。

(3)限流:高并发场景下瞬时流量不可预估,为了保证服务对外的稳定性,限流成为每个应用必备的一道安全防火墙。如果没有这道安全防火墙,那么请求的流量超过服务的负载能力时很容易造成整个服务的瘫痪。

(4)负载均衡:在多个微服务提供者之间按照多种策略实现负载均衡。

创建Zuul网关服务

Spring Cloud对Zuul进行了整合与增强。Zuul作为网关层,自身也是一个微服务,跟其他服务提供者一样都注册在Eureka Server上,可以相互发现。Zuul能感知到哪些Provider实例在线,同时通过配置路由规则可以将REST请求自动转发到指定的后端微服务提供者。

新建Zuul网关服务项目时需要在启动类中添加注解@EnableZuulProxy,声明这是一个网关服务提供者。当然,也需要在pom.xml文件中手动添加如下依赖:

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

启动类的代码如下:

package com.crazymaker.springcloud.cloud.center.zuul;
...
@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class})
@SpringBootApplication(scanBasePackages =
 {"com.crazymaker.springcloud.cloud.center.zuul",
 "com.crazymaker.springcloud.standard",
 "com.crazymaker.springcloud.user.info.contract"
 })
@EnableScheduling
@EnableHystrix
@EnableDiscoveryClient
//开启网关服务
@EnableZuulProxy
@EnableCircuitBreaker
public class ZuulServerApplication {
 public static void main(String[] args) {
 SpringApplication.run(ZuulServerApplication.class, args);
 }
}

Zuul路由规则配置

作为反向代理,Zuul需要通过路由规则将REST请求转发到上游的微服务Provider。作为示例,下面列出crazy-springcloud脚手架中Zuul网关的路由规则配置:

#服务网关配置
zuul:
 ribbonIsolationStrategy: THREAD
 host:
 connect-timeout-millis: 600000
 socket-timeout-millis: 600000
 #路由规则
 routes:
 seckill-provider:
 path: /seckill-provider/**
 serviceId: seckill-provider
 strip-prefix: false
 message-provider:
 path: /message-provider/**
 serviceId: message-provider
 strip-prefix: false
 user-provider:
 path: /user-provider/**
 serviceId: user-provider
 strip-prefix: false
 backend-provider:
 path: /backend-provider/**
 serviceId: backend-provider
 strip-prefix: false
 generate-provider:
 path: /generate-provider/**
 serviceId: generate-provider
 strip-prefix: false
 sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization
 demo-provider:
 path: /demo-provider/**
 serviceId: demo-provider
 strip-prefix: false
 urlDemo:
 path: /blog/**
 url: https://www.cnblogs.com
 sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization

以上示例中,有两种方式的路由规则配置:

(1)路由到直接URL;

(2)路由到微服务提供者。

先看第一种方式的路由规则配置:路由到直接URL。在上述示例中,有一条名为urlDemo的路由规则,该规则匹配到格式为/blog/**的所有URL请求,直接转发到https://www.cnblogs.com的地址上。

比如,通过网关访问如下URL:

http://127.0.0.1:7799/blog/crazymakercircle/p/9904544.html

此URL满足/blog/**的匹配规则,将被Zuul直接转发到上游的URL地址:

https://www.cnblogs.com/crazymakercircle/p/9904544.html

修改地址为疯狂创客圈的社群博客的实际地址,在浏览器中看到的Zuul转发结果如图6-2所示。

图6-2 Zuul直接转发到上游的URL地址

再看第二种方式的路由规则配置:路由到微服务提供者。

比如在上述代码中,有一条名为user-provider的路由规则,该规则将匹配/user-provider/**的所有URL请求,直接路由到名为user-provider的某个微服务提供者。

两种方式的区别如下:

(1)第一种方式使用url属性来指定直接的上游URL的前缀;第二种方式使用serviceId属性来指定上游服务提供者的名称。

(2)第二种方式需要结合Eureka Client客户端来实现动态的路由转发功能,启动类需要加上注解@EnableDiscoveryClient,只能用于Spring Cloud架构中。其实该注解也可以不加,因为网关注解@EnableZuulProxy已经默认进行了导入。

使用第二种方式,配置文件中增加Eureka Client客户端的相关配置如下:

eureka:
 client:
 serviceUrl:
 defaultZone: http://${EUREKA_ZONE_HOST:localhost}:7777/eureka/
 instance:
 prefer-ip-address: true #访问路径可以显示IP地址
 instance-id: ${spring.cloud.client.ip-address}:${server.port}
 ip-address: ${spring.cloud.client.ip-address}

过滤敏感请求头部

在同一个系统中,在不同Provider之间共享请求头是可行的,但是,如果Zuul需要将请求转发到外部,可能不希望敏感的请求头泄露到外部的其他服务器。

防止请求头泄露的方式之一是,在Zuul的路由配置中指定要忽略的请求头列表,并且多个敏感头部之间可以用逗号隔开。下面是一个简单的实例:

spring:
 application:
 name: cloud-zuul
zuul:
 sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization

大家知道,Cookie经常用于在流量中缓存用户的会话、用户凭证等信息,对于外部系统而言是需要保密的,所以应该设置为敏感标题,不应该带往系统外部。

默认情况下,Zuul转发请求时会把header清空,如果在微服务集群内部转发请求,上游Provider就会收不到任何头部。如果需要传递原始的header信息到最终的上游,就需要添加如下敏感头部设置:

zuul.sensitive-headers=

上面配置了敏感头部为空,YML格式的配置也需要进行空配置,表示没有需要屏蔽的头部。上面是全局配置,也可对单个路由规则进行局部配置,格式如下:
zuul.routes.xxxapi-xxx.sensitiveHeaders=比如crazy-springcloud脚手架中专门对外部的转发规则urlDemo进行了请求头的屏蔽,它的配置如下:

#服务网关路由规则
zuul:
 routes:
 urlDemo:
 path: /blog/**
 url: https://www.cnblogs.com
 sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization

对于该规则自身而言,单个路由规则的局部配置会覆盖全局的设置。

 路径前缀的处理

如果不进行任何配置,默认情况下Zuul会去掉路由的路径前缀。

例如,从客户端发起一个请求:

http://crazydemo.com:7799/demo-provider/api/demo/hello/v1

在Zuul进行路由处理时,会去掉在路由规则清单中配置的路径前缀demo-provider。处理之后,转发到上游的服务提供者的URL将变成下面的样子:

http://{provider-ip}:{provider-port}/api/demo/hello/v1

如果上游的微服务提供者没有配置路径前缀,Zuul的这种默认处理和转发就不会有问题。但是,如果上游提供者配置了统一的路径前缀,而前缀被去掉,上游服务提供者就会报出404的错误,也就是找不到URL对应的资源。

比如,在crazy-springcloud脚手架中的所有服务提供者都是配有context-path路径前缀的,如此配置的优势之一是会使下游Nginx外部网关进行代理转发时更加灵活。

从微服务demo-provider的配置文件
src/main/resources/bootstrap.yml可以看出,它的context-path路径前缀为/demo-provider,具体配置内容如下:

server:
 port: 7700
 servlet:
 context-path: /demo-provider

在Zuul进行路由处理时,如何保留请求URL中的路径前缀呢?具体来说,可以设置配置项stripPrefix的值为false,确保路径前缀不会截取掉。stripPrefix的值默认为true。

demo-provider的路由规则具体如下:

#服务网关路由规则
zuul:
 routes:
 demo-provider:
 path: /demo-provider/**
 serviceId: demo-provider
 strip-prefix: false
全部评论

相关推荐

华为 优秀实习生 24k的基础薪资
牛客530051504号:转人工
点赞 评论 收藏
分享
牛客737698141号:他们可以看到在线简历的。。。估计不合适直接就拒了
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务