带着问题学习是最好的,什么是网关?使用网关的好处是什么?怎么使用网关
网关:是系统对外的唯一入口,是介于客户端和服务端的中间层,处理非业务功能,提供路由的请求,鉴权,监控,缓存,限流等
网关的好处:可以将很多非业务功能集中在网关处理,例如鉴权,限流等,并且只提供了一个入口,那么也可以将业务服务很好的保护起来。
网关的使用:
1.使用idea创建zuul工程
2.zuul也是一个注册中心的客户端,并且要导入你使用的网关类型,我这里使用的是zuul,如果选不了,就是spring-boot版本过高,要调整一下spring-boot版本
3.在启动类上增加注解 @EnableZuulProxy
package com.xdclass.apigateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
4.修改配置文件application.yml(我是将.properties修改 成yml的)
server: port: 9000 #服务名称 spring: application: name: api-gateway #指定注册中心 eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
5.启动项目,访问试一试,拿到结果了
使用网关前的链接:ip:server port/controller Request mapping/method mapping
http://localhost:8781/api/v1/order/save?user_id=1&product_id=1
使用网关后的链接:ip:gateway port/server name/controller Request mapping/method mapping
http://localhost:9000/order-service/api/v1/order/save?user_id=1&product_id=1
6.yml增加配置
#自定义路径规则 zuul: routes: #自定义路由转发: order-service: /apigateway-order/** product-service: /apigateway-product/** #环境隔离配置:不想让默认的服务对外暴露接口 ignored-patterns: /*-service/**
再次使用链接:http://localhost:9000/order-service/api/v1/order/save?user_id=1&product_id=1,发现不能访问数据了,更改链接成:http://localhost:9000/apigateway-order/api/v1/order/save?user_id=1&product_id=1
在配置文件中将order-service 替换成了apigateway-order,不暴露原路径
7.自定义拦截器,创建一个类,增加注解@Component,继承ZuulFilter,然后实现里面的方法‘
package com.xdclass.apigateway.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; @Component public class LoginFilter extends ZuulFilter { @Override public String filterType() { //这个类里面记录了很多拦截器的类型,PRE表示前置,表示你这个拦截器是要在什么时候执行 return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { //这里表示拦截器执行的先后顺序,数字越小越在前面执行 return 0; } @Override public boolean shouldFilter() { HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); String uri = request.getRequestURI(); System.out.println("uri--:::"+uri); if(!StringUtils.isEmpty(uri) && uri.toLowerCase().contains("order")){
//true表示拦截 return true; } return false; } @Override
//拦截时调用的方法 public Object run() throws ZuulException {
RequestContext requestContext= RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); System.out.println("拦截了--"+request.getRequestURI()); String tokenStr = "token"; //进行逻辑处理 String token = request.getHeader(tokenStr); if(StringUtils.isEmpty(token)){ token = request.getParameter(tokenStr); } //根据token 进行登录校验逻辑的处理,根据公司的情况来自定义 JWT if(StringUtils.isEmpty(token)){ requestContext.setSendZuulResponse(false); requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); } return null; } }
7.zuul默认拦截三种请求信息,要么使用token,要么就在配置文件中增加一个配置
#增加配置,等于空就行
zuul
sensitiveHeaders=
8.使用zuul进行限流,使用令牌算法
代码如下:
package com.xdclass.apigateway.filter; import com.google.common.util.concurrent.RateLimiter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; import org.springframework.http.HttpStatus; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; /** * 订单限流 * @author chengcheng123 * @date 2021/6/9 0:35 */ //@Component public class OrderRateLimiterFilter extends ZuulFilter { //每秒创建一千个令牌 private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000); @Override public String filterType() { //这个类里面记录了很多拦截器的类型,PRE表示前置 return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { return -4; } @Override public boolean shouldFilter() { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); //如果请求的接口是订单接口的话,那么就进行拦截 String requestURI = request.getRequestURI(); if(!StringUtils.isEmpty(requestURI) && requestURI.toLowerCase().contains("order")){ return true; } return false; } @Override public Object run() throws ZuulException { //进行限流的处理 RequestContext currentContext = RequestContext.getCurrentContext(); if(!RATE_LIMITER.tryAcquire()){ //如果没有拿到令牌,则返回一个错误码 currentContext.setSendZuulResponse(false); currentContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value()); } return null; } }