SpringCloud(六)之 网关概念、Zuul项目搭建-(利用Zuul 实现鉴权和限流实战)
一、网关概念
1、什么是路由网关
网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能。它将"1对N"问题转换成了"1对1”问题。
通过服务路由的功能,可以在对外提供服务时,只暴露 网关中配置的调用地址,而调用方就不需要了解后端具体的微服务主机。
2、为什么要使用微服务网关
不同的微服务一般会有不同的网络地址,而客户端可能需要调用多个服务接口才能完成一个业务需求,若让客户端直接与各个微服务通信,会有以下问题:
(1)客户端会多次请求不同微服务,增加了客户端复杂性
(2)存在跨域请求,处理相对复杂
(3)认证复杂,每个服务都需要独立认证
(4)难以重构,多个服务可能将会合并成一个或拆分成多个
3、网关的优点
微服务网关介于服务端与客户端的中间层,所有外部服务请求都会先经过微服务网关客户只能跟微服务网关进行交互,无需调用特定微服务接口,使得开发得到简化
总的理解网关优点
服务网关 = 路由转发 + 过滤器
(1)路由转发:接收一切外界请求,转发到后端的微服务上去。
(2)过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)。
4、服务网关技术选型
引入服务网关后的微服务架构如上,总体包含三部分:服务网关、open-service和service。
(1)总体流程
服务网关、open-service和service启动时注册到注册中心上去;
用户请求时直接请求网关,网关做智能路由转发(包括服务发现,负载均衡)到open-service,这其中包含权限校验、监控、限流等操作
open-service聚合内部service响应,返回给网关,网关再返回给用户
(2)引入网关的注意点
增加了网关,多了一层转发(原本用户请求直接访问open-service即可),性能会下降一些(但是下降不大,通常,网关机器性能会很好,而且网关与open-service的访问通常
是内网访问,速度很快);
(3)服务网关基本功能
智能路由:接收外部一切请求,并转发到后端的对外服务open-service上去;
注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;
当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。
权限校验:可在微服务网关上进行认证,然后在将请求转发给微服务,无须每个微服务都进行认证,不校验服务内部的请求。服务内部的请求有必要校验吗?
API监控:只监控经过网关的请求,以及网关本身的一些性能指标(例如,gc等);
限流:与监控配合,进行限流操作;
API日志统一收集:类似于一个aspect切面,记录接口的进入和出去时的相关日志。
二、Zuul项目搭建
使用到的组件包括:Eureka、Feign、Zuul,包括以下四个项目:
(1)Eureka-server: 7001 注册中心
(2)product-server :8001 商品微服务
(3)order-server : 9001 订单微服务
(4)zuul-gateway : 6001 Zuul网关
注册中心、商品微服务、order在之前博客都已搭建,这里就不重复写。这里只写zuul-gateway微服务。
1、pom.xml
<!--客户端jar包,这个在订单微服务,商品微服务都要添加-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <!--zuuljar包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
2、application.yml
server:
port: 9999
#服务的名称
spring:
application:
name: api-gateway zuul:
#自定义路由转发
routes:
order-service: /loveliuqianqian/order/**
product-service: /loveliuqianqian/product/**
#环境隔离配置:不想让默认的服务对外暴露接口(就是下面配置的路径进行拦截不能访问)
#ignored-patterns:
# /*-service/api/v1/order/save
3、SpringBoot启动类
@SpringBootApplication
//网关注解
@EnableZuulProxy
public class ApiGatewayApplication { public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
} }
4、测试
(1)直接订单服务调商品服务
(2)通过Zuul网关实现订单接口调商品服务
5、自定义Zuul过滤器实现登录鉴权实战
(1)在网关服务项目中奖励一个filter 继承ZuulFilter
@Component
public class LoginFilter extends ZuulFilter { // 前置过滤器
@Override
public String filterType() {
return PRE_TYPE;
} //设置过滤器级别
@Override
public int filterOrder() {
return 4;
} //过滤器是否生效
@Override
public boolean shouldFilter() {
//zool 使用时,上下文对象RequestContext,是共享的。 所以通过RequestContext 获取值
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//设置需要拦截的路径
if ("/loveliuqianqian/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
//拦住了
return true;
}
//放行
return false;
} //业务逻辑
@Override
public Object run() throws ZuulException {
//zool 使用时,上下文对象RequestContext,是共享的。 所以通过RequestContext 获取值
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String token = request.getHeader("token");
String cookie = request.getHeader("Cookie");
if (StringUtils.isBlank(token)) {
token = request.getParameter("token");
cookie = request.getParameter("Cookie");
}
//如果token 等于null 返回状态码和没有权限的信息给前台
if (StringUtils.isBlank(token)) {
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
//(JWT)解析token 获取权限列表 鉴权。
return null;
}
}
7、高级篇幅之高并发情况下接口限流特技
(1)借助谷歌guava框架介绍,网关限流使用(下面这个filte 可以和上面鉴权的过滤器结合使用,具体看自己业务就行,下面代码中加黑的就是限流的主要代码)
@Component
public class OrderRateLimiterFilter extends ZuulFilter { //每秒产生500个令牌(请求进来后会拿去一个令牌,如果没拿到就不让访问。)
private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);
@Override
public String filterType() {
return PRE_TYPE;
} @Override
public int filterOrder() {
return -4;
} @Override
public boolean shouldFilter() {
//zool 使用时,上下文对象RequestContext,是共享的。 所以通过RequestContext 获取值
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//设置需要拦截的路径
if ("/loveliuqianqian/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
//拦住了
return true;
}
//放行
return false;
} @Override
public Object run() throws ZuulException {
//zool 使用时,上下文对象RequestContext,是共享的。 所以通过RequestContext 获取值
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String token = request.getHeader("token");
if (StringUtils.isBlank(token)) {
token = request.getParameter("token");
}
//限流 如果qps 访问过高(超过上面定义的,就停止访问)
if (!RATE_LIMITER.tryAcquire()||StringUtils.isBlank(token)) {
//如果token 等于null 返回状态码和没有权限的信息给前台
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
//(JWT)解析token 获取权限列表 鉴权。
return null;
}
}
5、注意些细节
(1)url不能重复,否则会覆盖
order-service: /apigateway/order/**
product-service: /apigateway/product/**
(2)通过zuul后,request中的cookie值获取不到,那是因为网关给过滤掉了。
@RequestMapping("list")
public void list(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId, HttpServletRequest request){
String token = request.getHeader("token");
String cookie = request.getHeader("cookie");
//会发现token值能够获取,cookie无法获取,原因是因为网关会过滤掉敏感词
System.out.println("token="+token);
System.out.println("cookie="+cookie);
}
想要不过滤掉cookie值那么在配置里配置
zuul:
#处理http请求头为空的问题
sensitive-headers:
6、问题
自己遇到两个问题记录下,后期再来思考解决。
1、现在通过订单服务地址可以直接访问订单微服务,如何配置成订单微服务不能直接服务,只能通过网关访问。
思考,是不是以后订单微服务配置到内网就不会有这个问题了。
2、当我的订单服务调商品服务异常时,直接访问订单微服务熔断降级能够完成,通过网关竟然直接报异常了。
我在商品微服务相关接口添加:
//睡眠两秒,微服务默认一秒就超时,所以会到降级方法
TimeUnit.SECONDS.sleep(2);
直接调订单服务,降级信息返回正常。如果通过网关访问。
返回的是异常,这不是很蛋疼吗,总是有解决办法让降级信息返回来的,以后解决来再来写。
上面的代码如果需要 可以留言给我 ,无条件发给你 。我这是微服务一套的代码,记住需要看前面几篇文章,你会理解的更好。
SpringCloud(六)之 网关概念、Zuul项目搭建-(利用Zuul 实现鉴权和限流实战)的更多相关文章
- SpringCloud(7)---网关概念、Zuul项目搭建
SpringCloud(7)---网关概念.Zuul项目搭建 一.网关概念 1.什么是路由网关 网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求.鉴权.监控. ...
- SpringCloud---网关概念、Zuul项目搭建(六)
SpringCloud---网关概念.Zuul项目搭建(六) 一.网关概念 1.什么是路由网关 网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求.鉴权.监控. ...
- Spring Cloud Gateway 整合阿里 Sentinel网关限流实战!
大家好,我是不才陈某~ 这是<Spring Cloud 进阶>第八篇文章,往期文章如下: 五十五张图告诉你微服务的灵魂摆渡者Nacos究竟有多强? openFeign夺命连环9问,这谁受得 ...
- 使用Alibaba的Nacos做为SpringCloud的注册和配置中心,并结合Sentinel+Nocos动态进行限流熔断
最近在学习阿里的Nacos组件以及Sentinel组件,折腾出了一个小demo. Git地址:https://github.com/yangzhilong/nacos-client 有兴趣的小伙伴可以 ...
- [SpringCloud教程]2. 版本选型和项目搭建
Spring Cloud Alibaba 版本选型 建议先选择Spring Cloud Alibaba的大版本,方便兼容 选择 Spring Cloud Alibaba 大版本 访问链接,找到标题&q ...
- Vuex的基本概念、项目搭建、入坑点
前言:Vuex是一个专门为Vue.js应用程序开发的状态管理模式, 它采用集中式存储管理所有组件的公共状态, 并以相应的规则保证状态以一种可预测的方式发生变化. Vuex的四大核心 1.state 驱 ...
- soul开源网关项目搭建学习
1. soul开源网关项目搭建学习 1.1. 地址 https://gitee.com/shuaiqiyu/soul 1.2. 介绍 官方介绍:这是一个异步的,高性能的,跨语言的,响应式的API网关. ...
- Day04_乐优商城项目搭建
学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"乐优商城"获取视频和教程资料! b站在线视频 0.学习 ...
- SpringCloud Gateway高阶之Sentinel限流、熔断
前言 为什么需要服务熔断和降级?微服务是当前业界的一大趋势,原理就是将单一职责的功能模块独立化为子服务,降低服务间的耦合,服务间互相调用.但是这样也会出现一些问题: 上图中大量微服务互相调用,存在大量 ...
随机推荐
- js 扁平化输出数组
1.使用数组的flat方法 [1,2,[3,[4,5]]].flat(Infinity) //[1, 2, 3, 4, 5] 2.实现方式二: var arr = [[1, 2, 23], [13, ...
- ARM体系结构与编程读书笔记——处理器的寄存器
ARM处理器共有37个寄存器,其中包括: 31个通用寄存器,包括程序计数器(PC)在内,寄存器都是32位: 6个状态寄存器,这些寄存器都是32位的,目前只使用了其中12位: 通用寄存器 可以分为下面3 ...
- C#信号量(Semaphore,SemaphoreSlim)
Object->MarshalByRefObject->WaitHandle->Semaphore 1.作用: 多线程环境下,可以控制线程的并发数量来限制对资源的访问 2.举例: S ...
- P3377 【模板】左偏树(可并堆) 左偏树浅谈
因为也是昨天刚接触左偏树,从头理解,如有不慎之处,跪请指教. 左偏树: 什 么是(fzy说)左偏树啊? 前置知识: 左偏树中dist:表示到右叶点(就是一直往右下找,最后一个)的距离,特别的,无右节点 ...
- Loadrunner:脚本编写通用模板(Http协议类型)
1. 背景 对于 Http协议,Loadrunner 脚本可以使用通用模板反复粘贴,只需要修改其中的 URL 和 传参,就可以完成一整个业务 2. Get 类型的接口 web_custom_reque ...
- Linux文件系统之目录管理mkdir命令
mkdir命令 mkdir命令mkdir命令简介mkdir命令用来创建指定的名称的空目录,要求创建用户在当前目录具有权限,并且制定的目录名不能是当前目录中已有的目录. 命令格式mkdir [选项] [ ...
- Kettle安装和简单使用
Kettle安装和使用 安装 安装之前需要准备的环境为Java环境,需要提前配置好jdk 下载之后,解压即可使用. 使用 1.因为该工具主要是对数据库进行操作,所以需要提前将mysql的jar包放到l ...
- struts2之单文件上传(7)
前台页面jsp <!-- 拦截的时候用这个 <s:form action="uploadAction" enctype="multipart/form-dat ...
- 长春理工大学第十四届程序设计竞赛D Capture The Flag——哈希&&打表
题目 链接 题意:给定一个字符串 $s$,求不同于 $s$ 的字符串 $t$,使得 $Hash(s) = Hash(t)$,其中 $\displaystyle Hash(s) = \sum_0^{le ...
- 括号序列的dp问题模型
括号序列的dp问题模型 Codeforces314E ◦给定一个长度为n的仅包含左括号和问号的字符串,将问号变成左括号或 右括号使得该括号序列合法,求方案总数. ◦例如(())与()()都是合法的括号 ...