linux怎么查看本机内存大小
301
2022-09-20
3. zuul网关的应用--实践操作
目录:
1. nginx网关和zuul网关的区别
2. zuul项目搭建及演示
3. 配置特殊路由规则
四. 动态的路由机制
五. zuul的全局拦截
六. 在zuul里面实现限流
七. 在zuul里面实现熔断器
一. nginx网关和zuul网关的区别
1. 相同点
都是网关. 用户访问, 都是先访问网关. 不能直接访问里面的服务. 他们都能做路由, 负债均衡, 以及限流
2. 异同点
nginx在做路由,负载均衡,限流之前, 都有修改nginx.conf的配置文件. 把需要负载均衡,限流,路由的规则定义在nginx.conf配置文件中eg: 使用nginx做tomcat负载均衡, 需要修改nginx.conf配置文件
Upsteam car.com { server ip: port, server ip: port}Location / { proxy_pass zuul是自动负载均衡和路由, zuul和eureka高度集成, 实现自动的路由, 和ribbon结合,实现了负载均衡, zuul也能轻易的实现限流和权限验证
性能相比: nginx的性能比zuul要高. nginx是c写的
二.zuul项目搭建及演示
2.1 新建网关项目--zuul-test-gateway
2.1.1 引入项目依赖
我搭建的是一个全新的项目
在项目名称zuul-test-gateway
引入的依赖: web, zuul, nacos-config, nacos-discovery
引入的配置如下:
2.1.2 新建bootstrap.yml配置文件
spring: cloud: nacos: config: server-addr: 127.0.0.1:8848 file-extension: yml namespace: 482c42bd-fba1-4147-a700-5b678d7c0747 group: ZUUL_TEST
2.1.3 修改配置文件application.yml
server: port: 8080spring: application: name: gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: 482c42bd-fba1-4147-a700-5b678d7c0747 redis: host: localhost port: 6379
2.1.4 在启动类引入相关注解
1. 开启zuul网关的注解:@EnableZuulProxy
2. nacos注册发现注解: @EnableDiscoveryClient
3. web框架注解: @RestController
4. 微服务间调用注解feign: @EnableFeignClients
5. 动态更新配置注解: @RefreshScope
package com.lxl.gateway;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestController@EnableDiscoveryClient@EnableFeignClients@SpringBootApplication@EnableZuulProxy // 开启zuul网关功能@RefreshScopepublic class ZuulTestGatewayApplication { @Value("${config}") private String config; public static void main(String[] args) { SpringApplication.run(ZuulTestGatewayApplication.class, args); } @GetMapping("config") public String getconfig(){ return this.config; }}
2.1.5 启动nacos服务端
我们这里配置中心使用的是nacos, 因此我们需要启动nacos服务.
如何配置nacos,启动nacos, 参考文章:
启动nacos, 我这里是单机模式启动, 进入到nacos的目录
cd /users/nacos/nacos/bin./startup.sh -m standalone
2.1.6 启动gateway网关项目
上面的配置文件中已经包含了nacos配置和服务发现的配置内容
2.1.7 在nacos中查看网关项目
1. 网关的配置文件, 如下图所示
2.网关项目启动后, 查看服务列表
2.2 创建另一个服务,用户服务----zuul-test-user
2.2.1 添加依赖
需要添加的依赖有: nacos配置和发现, web,以及feign
2.2.2 添加bootstrap.yml配置文件
spring: cloud: nacos: config: server-addr: 127.0.0.1:8848 file-extension: yml namespace: 482c42bd-fba1-4147-a700-5b678d7c0747 group: ZUUL_TEST
2.2.3 修改application.yml配置文件
server: port: ${port:8089}spring: application: name: user cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: 482c42bd-fba1-4147-a700-5b678d7c0747
2.2.4 启动类引入注解
package com.lxl.user;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestController@EnableDiscoveryClient@SpringBootApplication@RefreshScopepublic class ZuulTestUserApplication { @Value("${config}") private String config; public static void main(String[] args) { SpringApplication.run(ZuulTestUserApplication.class, args); } @GetMapping("/config") public String getconfig(){ return config + "2222"; }}
2.2.5 启动user服务
2.2.6 查看nacos
1. 查看user配置文件
2. 查看项目启动情况
2.3. 启动另一个user服务. 换一个端口
1. 上面我们定义user服务的端口的时候,定义的是动态端口
下面我们构建集群环境,再启动一个user服务.
4. 选中要启动的应用, 然后设置端口号
6. 查看nacos中服务的启动情况
我们看到user的实例数,现在是2台
至此项目搭建就完成了!!!
2.4. 下面来感受一下网关
现在有两个服务, 一个是网关服务,端口是8080; 一个是user服务, 端口分别是8089和8088.
我们通过网关服务区请求user, 看看可不可以
我在postman中输入的是网关的端口localhost:8080, 然后紧跟着服务名+path, 可以正确跳转到user服务上.
其实,我们在配置文件中, 没有做任何配置.
网关是网关服务, 用户是用户服务, 他们都可已单独存在, 单独工作. 但是通过网关的地址却能够跳转到user服务上. 这是zuul自动为我们在服务发现上发现相应的集群中的其他服务.
下面来详细说说网关的应用
三. 配置特殊的路由规则
zuul: routes: user-router: # 随便写, 是一个唯一的, 代表一个微服务的路由机制 service-id: user # 该路由机制针对的是哪个微服务 path: /user1/**
我们可以在网关中自定义服务的路由路径. 如上所示
这表示, 所有连接那么也会正确的请求的user服务上
四. 动态的路由机制
五. zuul的全局拦截
zuul是前端访问的唯一入口, 我们可以在zuul实现一个token的拦截验证
1. 定义一个TokenFilter过滤器,这个过滤器extends ZuulFilter
package com.lxl.gateway.filter;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import javax.servlet.class TokenFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return true; } /** * 实现token 拦截验证 * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { // 怎么判断用户的token? // RequestContext 请求的上下文, 包含所有的请求参数, 他默认和线程绑定 RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); // 从请求头中拿出token String token = request.getHeader("token"); if (!StringUtils.hasText(token)) { // token 为null currentContext.setResponseBody("token is null"); currentContext.setResponseStatusCode(401); // 是否发送路由响应 currentContext.setSendZuulResponse(false); return null; } if (!"123456".equals(token)) { currentContext.setResponseBody("token is error"); currentContext.setResponseStatusCode(401); currentContext.setSendZuulResponse(false); return null; } currentContext.setSendZuulResponse(true); return null; }}
这个过滤器extends自ZuulFilter, 后面的案例多了, 我们就发现, 其实zuul网关的本质就是拦截器, zuul的各种功能,也是通过拦截器来实现的
filterType() : 拦截器的类型是前置拦截器.
filterOrder(): 执行顺序是第一个执行.
shouldFilter(): 过滤器执行的条件, 这里是所有的连接都需要过这个拦截器, 所以直接设置为true
run(): 拦截器的核心逻辑. 这里的拦截器逻辑很简单, 就是判断header中是否有一个叫做token的属性, 且其值为123456
2. 启动服务, 查看拦截器效果
当有header, 不启用的时候, 会被拦截, 提示token is null, 并且跳过后面的拦截器, 直接返回
当有token ,但是token的值不是123456的时候, 会说token错误
只有当token符合我们的预期的时候, 才可以放行
这个拦截器是对所有微服务有效的.
六. 在zuul里面实现限流
当有个恶意用户每分钟访问超过一定的次数后, 我们可以对他实行限制, 让他1分钟内只能访问n次
6.1 添加zuul的限流组件
git地址:上面是源码, 下面是使用方法
6.2 添加限流组件--引入依赖
1. 添加组件 -->
我们引入限流组件, 同时引入redis. 用来记录当前用户登录的次数
6.3 在配置文件中增加redis配置.
在本地先启动redis, 端口6379
然后增加redis配置
6.4 增加限流配置
6.4.1 全局限流配置
根据文档, 限流配置有两种,
1. 通用限流配置: 对所有的微服务都生效
2. 特定服务限流配置: 针对某一个微服务设置的限流
文档内容如下:
zuul: routes: user-router: # 随便写, 是一个唯一的, 代表一个微服务的路由机制 service-id: user # 该路由机制针对的是哪个微服务 path: /user1/** ratelimit: enabled: true repository: REDIS behind-proxy: true add-response-headers: true default-policy-list: # 全局配置, 改配置对所有的微服务都有效 - limit: 10 #选填--限制的次数 quota: 1000 #选填--时间的显示--刷新窗口时间隔的时间限制 refresh-interval: 60 # 60s type: #选填--针对哪个服务有效 #- user # 针对用户么 - origin #针对域名么 #- url #针对url么 #- #针对方法么
如上限流的含义是: 对所有微服务都生效的限流策略是: 对某个微服务在60s内,请求次数限制是10次. 或者刷新窗口时间隔实现的限制是1秒. 也就是1秒刷新一次窗口.
配置中的具体含义如上注释
配置好以后, 启动微服务, 在postman中查看 是否起到限流作用
当次数超过10次时候, 就会给出异常提示, too many requests.
6.4.2 特定微服务的限流限制
zuul: routes: user-router: # 随便写, 是一个唯一的, 代表一个微服务的路由机制 service-id: user # 该路由机制针对的是哪个微服务 path: /user1/** ratelimit: enabled: true repository: REDIS behind-proxy: true add-response-headers: true default-policy-list: # 全局配置, 改配置对所有的微服务都有效 - limit: 10 #选填--限制的次数 quota: 1000 #选填--时间的显示 refresh-interval: 60 # 60s type: #选填--针对哪个服务有效 #- user # 针对用户么 - origin #针对域名么 #- url #针对url么 #- #针对方法么 policy-list: user: #这里设置的是具体的服务id - limit: 10 #optional 设置限流的次数 quota: 1000 #optional 设置限流的时间--刷新窗口间隔的时间限制 refresh-interval: 60 # 60s为单位限流 type: #optional 针对的限流类型 #- user #针对用户限流么? - origin #针对域名限流么? 表示的是一个客户端 #- url # 针对url链接限流么?
设置单个微服务的限流策略, 如上所示, 具体含义: 60s内, 限制次数为10次, 窗口刷新间隔时间是1秒.
效果如下, 当每分钟请求次数超过5次的时候, 爆出连接次数过多
6.5 限流的机制
限流器的本质是filter在限流器通过filter来记录用户的访问次数, 当次数达到一定值, 直接让filter拦截
6.6 限流里面redis的作用
使用redis的原因, 当zuul是一个集群的时候,要在多个redis中共享访问次数
七. 在zuul里面实现熔断器
熔断, 其含义是当路由失败的时候, 执行熔断器.
zuul是自带熔断机制的. 不需要引入任何额外的依赖
我们需要的是, 实现熔断器中的FallbackProvider接口. 定义自己的熔断机制
package com.lxl.gateway.fallback;import org.apache.org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;import org.springframework.org.springframework.org.springframework.org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.RequestHeader;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;/** * zuul熔断器 */@Componentpublic class ZuulFallbackProvider implements FallbackProvider { /** * 要对哪个微服务实现熔断 * @return */ @Override public String getRoute() { return "user"; // 这里写的是服务的id, *表示任何服务 } /** * 在熔断时, 用户执行怎样的响应数据 * @param route * @param cause * @return 当熔断被触发以后, 如何响应内容 */ @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { System.out.println("熔断器被触发:" + route); System.out.println("熔断的原因:" + cause); return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.BAD_REQUEST; } @Override public int getRawStatusCode() throws IOException { return 401; } @Override public String getStatusText() throws IOException { return "服务异常!"; } @Override public void close() { } @Override public InputStream getBody() throws IOException { byte[] body = "server is error, get in the fallback".getBytes(); return new ByteArrayInputStream(body); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.add("reason", "server is error, get in fallback!"); return headers; } }; }}
getRoute(): 定义对哪个服务启用熔断策略
fallbackResponse(String route, Throwable cause): 当熔断时, 执行怎么样的操作
这里的熔断机制比较简单, 如果熔断了, 那么就打印日志, 并输出server is error, get in fallback!
比如: 我的user微服务挂了, 通过网关请求, 就会进得到如下信息提示.
以上就是zuul在项目中通常使用的场景. demo很简单, 但框架即是如此, 具体可以根据详细的需求增减
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~