应用场景

微服务在真实应用中一般都会有N多个服务节点组成的服务集群,每个服务都可能依赖多个服务进行本身的业务处理,比如:用户登录操作可能会调用 账号验证服务、身份鉴别服务、生成日志服务、路由转向服务、受权服务等一系列服务才能完成一次登录操作。这样会带来几个问题:

  1. 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
  2. 登录信息认证繁琐,访问每个服务都要进行一次认证
  3. 每个服务都通过http访问,导致http请求次数增加,效率不高拖慢系统性能
  4. 多个服务存在跨域请求问题,处理起来比较复杂

我们需要解决这些问题,尝试想一下,不要让前端客户端直接调用后台诸多微服务,我们的服务集群从整个应用系统层面划分,不管大小服务都是服务层的系统元素,对服务管理而言业务被拆分成无数小颗粒度松耦合的独立服务,但对于前端调用服务的用户来说,所有服务是一个整体。对于前台客户端应用而言后台服务应该仍然类似于单体应用一样,要求只有一个服务调度入口即可,于是我们可以在客户端和服务端之间增加一个API网关,所有的外部请求先通过这个微服务网关。前台客户端只需跟网关进行交互,而由网关进行各个微服务的调用。熟悉面向对象设计模式的人应该很容易想到这是“门户模式”的典型应用。经“门户模式”的设计改良后有如下优点:

  1. 减少客户端与微服务之间的调用次数,提高效率
  2. 便于监控,可在网关中监控数据,可以做统一切面任务处理
  3. 便于认证,只需要在网关进行认证即可,无需每个微服务都进行认证
  4. 降低客户端调用服务端的复杂度

SpringCloud已经为我们考虑到这一点需求并提供解决方案,SpringCloud通集成Zuul组件完成对服务的路由功能。

概念简介

zuul是Netflix设计用来为所有面向设备、web网站提供服务的所有应用的门面,zuul可以提供动态路由、监控、弹性扩展、安全认证等服务,他还可以根据需求将请求路由到多个应用中。

搭配使用

当然在Netflix的使用中,zuul也结合了Netflix的其他微服务组件一起使用。
• Hystrix:用来服务降级及熔断
• Ribbon:用来作为软件的负载均衡,微服务之间相互调用是通过ribbon作为软件负载均衡使用负载到微服务集群内的不同的实例
• Turbin:监控服务的运行状况
• Feign:用作微服务之间发送rest请求的组件,可以将rest调用类似spring的其他bean一样直接注入使用功能
• Eureka:服务注册中心
入门示例
我们用Idea来创建测试项目,用Spring Initializr可以顺利完成创建过程。

最终的项目代码框架如下图。

引入依赖

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

系统配置

#访问端口
server:port: 8766
#服务名称
spring:application:name: routing.zull.web#安全认证信息security:user:name: adminpassword: 123456
#服务注册
eureka:server:register: localhost:8760client:serviceUrl:defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.server.register}/eureka/zuul:#如果是url的方式,则zuul.host开头的生效。host:connect-timeout-millis: 6000socket-timeout-millis: 6000#如果路由方式是serviceId的方式,那么ribbon的生效ribbon:ReadTimeout: 3000SocketTimeout: 3000routes:#路由节点aapi-a:path: /api-a/**serviceId: EUREKA.CLIENT.FIRST.WEBAPI#路由节点bapi-b:path: /api-b/**serviceId: EUREKA.CLIENT.FIRST.WEBAPI#路由节点capi-c:path: /api-c/**serviceId: EUREKA.CLIENT.FIRST.WEBAPI

启动类

@SpringBootApplication/*服务启动*/
@EnableZuulProxy/*服务路由*/
@EnableEurekaClient/*服务注册*/
@EnableDiscoveryClient/*服务发现*/
public class RoutingZullWebApplication {public static void main(String[] args) {SpringApplication.run(RoutingZullWebApplication.class, args);}
}

启动测试

反向代理

Spring-Zuul作为一款优秀的路由网关组件支持反向代理功能,通过添加路由配置项url来实现网络资源重定向功能。
路由节点api-d对https://blog.csdn.net反向代理

   api-d:path: /proxy/**url: https://blog.csdn.net

当客户端访问http://xxx.xxx.xxx.xxx:xx/proxy 的时候,网关路由自动重定向https://blog.csdn.net资源。
• api-d自定义的前缀
• path匹配的地址
• url路由到哪个服务

启动测试
http://localhost:8766/proxy/xxxlllbbb

过滤器

Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。
PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR:在其他阶段发生错误时执行该过滤器。
除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
Zuul中默认实现的Filter。
下面是最常用的Filter作用。

/*** 限流*/
@Component
public class AccessFilter extends MyFilter {// 每秒放多少个令牌 (100个)private static final RateLimiter rateLimiter = RateLimiter.create(1);public AccessFilter() {super(FilterType.PRE, 0);}@Overridepublic Object execute(HttpServletRequest request, RequestContext ctx) throws Exception {String msg = String.format("AccessFilter 流量限制>>%s: %s", request.getMethod(), request.getRequestURL().toString());System.out.println(msg);//限流、限速if (!rateLimiter.tryAcquire()) {String msgs="访问太频繁了,请稍后。。。";System.out.println(msgs);ctx.setSendZuulResponse(false);ctx.setResponseStatusCode(401);ctx.getResponse().setContentType("application/json; charset=UTF-8");BaseData bdata = BaseData.result(401, "访问限制", msgs);// 内容重新写入ctx.setResponseBody(JSON.toJSONString(bdata));return null;}return null;}
}
/*** @路由之前执行* token 身份验证*/
@Component
public class AuthenticateFilter extends MyFilter{public AuthenticateFilter() {super(FilterType.PRE, 1);}@Overridepublic Object execute(HttpServletRequest request, RequestContext ctx) throws Exception {String msg = String.format("PreFilter 权限验证>>%s: %s", request.getMethod(), request.getRequestURL().toString());System.out.println(msg);Object accessToken = request.getParameter("token");if (accessToken == null) {System.out.println("token is empty");ctx.setSendZuulResponse(false);ctx.setResponseStatusCode(401);ctx.getResponse().setContentType("application/json; charset=UTF-8");BaseData bdata = BaseData.result(401, "权限验证", "token is empty");ctx.setResponseBody(JSON.toJSONString(bdata));}return null;}
}
*** @发送错误调用* 路由容错处理*/
@Component
public class ErrorFilter extends MyFilter {public ErrorFilter() {super(FilterType.ERROR, -1);}@Overridepublic boolean shouldFilter() {return RequestContext.getCurrentContext().containsKey("throwable");}@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext();HttpServletResponse response = ctx.getResponse();String msg = String.format("ErrorFilter>>%s: %s", ctx.getRequest().getMethod(), ctx.getRequest().getRequestURL().toString());System.out.println(msg);Object e = ctx.get("throwable");if (e != null && e instanceof ZuulException) {ZuulException zuulException = (ZuulException) e;ctx.remove("throwable");ctx.setSendZuulResponse(false);ctx.getResponse().setContentType("application/json; charset=UTF-8");BaseData bdata = BaseData.result(401, "服务故障", zuulException.getMessage());ctx.setResponseBody(JSON.toJSONString(bdata));}return null;}
}
/*** @路由之后执行* 对服务接果进行统一处理*/
@Component
public class PostFilter extends MyFilter {public PostFilter() {super(FilterType.POST, 2);}@Overridepublic Object execute(HttpServletRequest request, RequestContext ctx) throws Exception {String msg = String.format("PostFilter 返回结果>>%s: %s", request.getMethod(), request.getRequestURL().toString());System.out.println(msg);// 获取返回值内容,加以处理InputStream stream = ctx.getResponseDataStream();String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));BaseData bdata = BaseData.result(ctx.getResponseStatusCode(), "请求成功", body);// 内容重新写入ctx.setResponseBody(JSON.toJSONString(bdata));return null;}
}

禁用指定的Filter
可以在application.yml中配置需要禁用的filter,格式:
zuul:
FormBodyWrapperFilter:
pre:
disable: true

的高可用

我们实际使用Zuul的方式如上图,不同的客户端使用不同的负载将请求分发到后端的Zuul,Zuul在通过Eureka调用后端服务,最后对外输出。因此为了保证Zuul的高可用性,前端可以同时启动多个Zuul实例进行负载,在Zuul的前端使用Nginx或者F5进行负载转发以达到高可用性。

至此关于SpringCloud-Zuul常用路由网关就介绍完了。

上一篇 SpringCloud-Hystrix 服务熔断器

下一篇 SpringCloud-Gatway高级路由网关

SpringCloud终极教程之核心讲解

源代码地址:https://github.com/crexlb/cre.springcloud.examples

SpringCloud-Zuul常用路由网关相关推荐

  1. SpringCloud之 Gateway路由网关

    文章目录 Gateway 路由网关 一.部署网关

  2. SpringCloud实战(五)-路由网关(zuul)

    本文是SpringCloud实战(五)-路由网关(zuul),若要关注前文,请点击传送门: SpringCloud实战(四)-断路器(Hystrix) 前文我们介绍了Hystrix断路器.在平常工作中 ...

  3. 史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)

    转:https://blog.csdn.net/forezp/article/details/69939114 最新版本: 史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)( ...

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

    前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...

  5. springcloud 之 路由网关 zuul

    话不多说,先上图(图是丑陋了点,大家别介意哈),这幅图是我根据公司现有的业务设计出来的一个简单的基于springcloud微服务架构图. 在springcloud微服务体系中,我们一般不对外直接暴露服 ...

  6. 跟着狂神学SpringCloud(Rest环境搭建+Eureka服务注册与发现+ribbon+Feign负载均衡+Hystrix+服务熔断+Zuul路由网关+SpringCloud config分布)

    跟着狂神学SpringCloud SpringCloud 回顾之前的知识- JavaSE 数据库 前端 Servlet Http Mybatis Spring SpringMVC SpringBoot ...

  7. SpringCloud微服务(05):Zuul组件,实现路由网关控制

    一.Zuul组件简介 1.基础概念 Zuul 网关主要提供动态路由,监控,弹性,安全管控等功能.在分布式的微服务系统中,系统被拆为了多个微服务模块,通过zuul网关对用户的请求进行路由,转发到具体的后 ...

  8. SpringCloud极简入门|zuul智能路由回退、认证、转发功能demo 第五讲

    开篇点题 在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统. 本章将讲解zuu ...

  9. SpringCloud Alibaba微服务实战(六) - 路由网关(Gateway)

    什么是 Spring Cloud Gateway? Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0,Spring Boot 2.0 和 Project Re ...

最新文章

  1. Nginx 学习总结(2) —— 基本配置
  2. setTimeout和setInterval方法
  3. optee内核中malloc函数的原理介绍
  4. [学习笔记]Event与Bindable
  5. 上线到凌晨4点半 pagehelper的bug?
  6. FC网络学习笔记02 -网络配置方法
  7. form表单间接提交方法
  8. 吴恩达深度学习——2.1 二分分类
  9. 【转】ASPxGridView 日期范围过滤扩展
  10. makefile:425: *** 遗漏分隔符
  11. 勤哲excel服务器自动计算工资,勤哲Excel服务器软件实现财务自动化管理系统
  12. u盘维护系统 linux,制作绝对pe+puppy U盘维护系统双系统(以下方法也可制作archlinux U盘安装)...
  13. linux recv函数 参数,linux send recv函数详解
  14. 基于MATLAB的手机定位精度评估算法的仿真
  15. html5脑图_HTML5 D3.js 树形结构动画示范(可绘制脑图)
  16. 棋盘算法c语言程序,C语言经典算法 - 骑士走棋盘
  17. 《自控力》第四章读书笔记
  18. Android Jetpack之DataBinding+ViewModel+LiveData+Room
  19. 做了五年Android,我顿悟了...
  20. ICIP2021:VVC RPR参考结构改进

热门文章

  1. C语言关于指针P、*P、P三者的区别
  2. java-php-python-ssm漠河旅游官网计算机毕业设计
  3. 计算机科学与技术脑电波,科学“读心术”,当脑电波扫描图遇到人工智能
  4. 排位赛2-I Would Walk 500 Miles
  5. 谷歌浏览器中英文切换
  6. mac系统从零开始配置若依框架后端运行环境
  7. obs源码二次开发,自定义插入SEI
  8. 吐血规劝!程序员防猝死终极指南
  9. 名悦集团分享纯电动汽车保养的几个小秘诀
  10. Android Studio 配置翻译工具