技术支持 如皋网站建设,老域名对做网站的,建设网站需要用到哪些技术人员,软件技术开发合同范本文章目录 1. 网关介绍2. 网关搭建2.1 引入依赖2.2 创建启动类2.3 编写配置2.4 测试 3. 路由断言工厂4. 路由过滤器4.1 过滤器配置4.2 全局过滤器4.3 过滤器执行顺序 5. 跨域问题处理 1. 网关介绍
到现在#xff0c;我们可以使用Nacos对不同的微服务进行注册并管理配置文件我们可以使用Nacos对不同的微服务进行注册并管理配置文件也可以使用 Feign 对不同的微服务进行访问但是这种访问是任何人都可以访问的这是不行的访问之间应该有某种权限的控制而且如果所有允许的访问都可以进入那么如果有一个时间访问量太过巨大则会引起服务器出现问题这就需要使得请求限流了所以我们需要使用一些工具来达到这些目的这就是网关Gateway。 网关具体需要实现的功能包括
对用户请求做身份认证、权限校验将用户请求路由到微服务并实现负载均衡对用户请求做限流
SpringCloud中网关的实现有两种
gatewayzuul
zuul是基于Servlet的实现属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux属于响应式编程的实现具备更好的性能所以我们接下来使用Gateway来对网关进行实现。
2. 网关搭建
接下来我们就试着为userservice 和 orderservice 搭建网关。
2.1 引入依赖
首先初始化一个新的Module将其初始化为空的Maven统一网关实际上也是一个微服务所以也需要在Nacos上进行注册发现故添加如下依赖
dependencies!-- nacos服务发现注册依赖 --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!-- 网关gateway依赖 --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency
/dependencies2.2 创建启动类
创建一个 GatewayApplication 的文件将其当做启动类该文件的内容如下
SpringBootApplication
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}
}2.3 编写配置
在网关这里需要在 application.yml 配置中编写路由配置以及nacos的地址等配置信息配置文件中的配置信息如下所示
server:port: 10010
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由标示必须唯一uri: lb://userservice # 路由的目标地址lb是负载均衡后面跟服务名称predicates: # 路由断言判断请求是否符合规则- Path/user/** # 路径断言判断路径是否是以/user开头如果是则符合- id: order-serviceuri: lb://orderservicepredicates:- Path/order/**从配置信息可以看到网关实现了负载均衡以及路径的断言让访问变得更加的轻松方便。
2.4 测试
接下来我们将 userservice, orderservice, gateway 三个服务都启动然后输入网址 http://localhost:10010/user/1 可以看到用户信息能够顺利显示出来。 再输入网址 http://localhost:10010/order/101 能够正确的显示相关的信息 这说明我们的网关构建时成功的。
3. 路由断言工厂
我们在配置文件中写的断言规则只是字符串这些字符串会被Predicate Factory读取并处理 转变为路由判断的条件。
例如 Path/user/** 是按照路径匹配这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory 类来处理的像这样的断言工厂在SpringCloudGateway中还有十几个。
Spring提供了11中基本的路由断言工厂11中工厂如下
名称说明After只处理某个时间点后的请求Before只处理某个时间点之前的请求Between只处理某两个时间点之前的请求Cookie请求必须包含某些cookie才处理Header请求必须包含某些header才处理Host请求必须是访问某个host域名才处理Method请求方式必须是指定方式才处理Path请求路径必须符合指定规则才处理Query请求参数必须包含指定参数才处理RemoteAddr请求者的ip必须是指定范围才处理Weight权重处理
所有这些断言工厂的实例都可以在Spring官网中找到。
比如我们需要只处理上海市2024年3月28日的orderservice请求那么修改配置文件如下
server:port: 10010
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由标示必须唯一uri: lb://userservice # 路由的目标地址lb是负载均衡后面跟服务名称predicates: # 路由断言判断请求是否符合规则- Path/user/** # 路径断言判断路径是否是以/user开头如果是则符合- id: order-serviceuri: lb://orderservicepredicates:- Path/order/**- After2024-03-28T17:42:47.789-07:00[Asia/Shanghai]上面仅新增了最后一行这样因为现在是2023年所以访问 http://localhost:10010/order/101 必定会失效。
4. 路由过滤器
Gateway不可能所有请求都进行响应其会根据一些条件将不符合的路径进行过滤这也就是路由过滤器GatewayFilter的作用对进行网关的请求和微服务返回的响应做出处理。
4.1 过滤器配置
Spring中提供了30种不同的路由过滤器工厂这里就不一一列举出来了所有的路由过滤器工厂都能在Spring官网进行查看。
比如这里可以使用过滤器给userservice 添加一个请求头添加如下
server:port: 10010
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由标示必须唯一uri: lb://userservice # 路由的目标地址lb是负载均衡后面跟服务名称predicates: # 路由断言判断请求是否符合规则- Path/user/** # 路径断言判断路径是否是以/user开头如果是则符合filters:- AddRequestHeaderTruth,I am a really ikun!则上面的代码会对所有的 userservice 服务添加一个请求头。
如果想要对所有的请求都添加一个请求头应该怎么做呢 只需要定义 default-filters 即可定义的过滤器如下
server:port: 10010
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由标示必须唯一uri: lb://userservice # 路由的目标地址lb是负载均衡后面跟服务名称predicates: # 路由断言判断请求是否符合规则- Path/user/** # 路径断言判断路径是否是以/user开头如果是则符合default-filters:- AddRequestHeaderTruth,I am a really ikun!4.2 全局过滤器
全局过滤器的作用也是处理一切进入网关的请求和微服务响应与 default-filters 的作用一样区别在于 default-filters 通过配置定义处理逻辑是固定的。而 GlobalFilter 的逻辑需要自己 写代码实现。
全局过滤器的实现步骤如下
实现 GlobalFilter 接口添加 Order 注解或实现 Ordered 接口目的是设置过滤的优先级编写处理逻辑
比如我们定义一个全局过滤器拦截请求判断请求的参数是或符合下面的条件
参数中是否有 authorizationauthorization 参数值是否为 admin
如果同时满足则对请求进行放行。
我们在 gateway 的Module中创新一个 AuthorizeFilter 的全局过滤文件其文件内容如下;
// Order 注解定义过滤器优先级值越小优先级越高也可以通过Ordered接口实现
Order(-1)
Component
public class AuthorizeFilter implements GlobalFilter {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取请求参数ServerHttpRequest request exchange.getRequest();MultiValueMapString, String params request.getQueryParams();// 2.获取参数中的 authorization 参数String auth params.getFirst(authorization);// 3.判断参数值是否等于 adminif (admin.equals(auth)) {// 4.是放行return chain.filter(exchange);}// 5.否拦截// 5.1.设置状态码exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);// 5.2.拦截请求return exchange.getResponse().setComplete();}
}之后再使用 http://localhost:10010/order/101 则网页会报告我们所设置的状态码的错误错误如下 而如果使用 http://localhost:10010/order/101?authorizationadmin 则网页能够正常访问。
4.3 过滤器执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter 请求路由后会将当前路由过滤器和DefaultFilter、GlobalFilter合并到一个过滤器链(集合中排序后依次执行每个过滤器那么过滤器链的执行顺序是怎样的呢
过滤器执行顺序如下
每一个过滤器都必须指定一个int类型的order值order值越小优先级越高执行顺序越靠前。GlobalFilter 通过实现 Ordered 接口或者添加 Order 注解来指定 order 值由我们自己指定路由过滤器和 defaultFilter 的 order 由Spring指定默认是按照声明顺序从1递增。即如果定义了多个过滤器配置则其第一行优先级是1第二行优先级是2以此类推当过滤器的 order 值一样时会按照 defaultFilter 路由过滤器 GlobalFilter 的顺序执行。
5. 跨域问题处理
跨域问题指的是不同站点之间使用 ajax 无法相互调用的问题。跨域问题本质是浏览器的一种保护机制它的初衷是为了保证用户的安全防止恶意网站窃取数据但这个保护机制也带来了新的问题它的问题是给不同站点之间的正常调用也带来的阻碍。简单来说就是浏览器禁止请求的发起者与服务端发生跨域ajax请求请求被浏览器拦截的问题。
在请求时如果出现了以下情况中的任意一种那么它就是跨域请求
协议不同如 http 和 https域名不同端口不同。
也就是说即使域名相同如果一个使用的是 http另一个使用的是 https那么它们也属于跨域访问。常见的跨域问题如下图所示
当前页面被请求页面是否跨域http://www.test.com/http://www.test.com/index.html否http://www.test.com/https://www.test.com/index.html是协议名不同(http,https)http://www.test.com/http://www.baidu.com/是主域名不同(test,baidu)http://www.test.com/http://blog.test.com/是子域名不同(www,blog)http://www.test.com:8080/http://www.test.com:8081/是端口不同(8080,8081)
而解决跨域问题的方案就是 CORSCORS 是一个W3C标准全称是”跨域资源共享”Cross-origin resource sharing允许浏览器向跨源服务器发出XMLHttpRequest请求从而克服了AJAX只能同源使用的限制。它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制如果浏览器支持CORS、并且判断Origin通过的话就会允许XMLHttpRequest发起跨域请求。
网关处理跨域问题采用的方案同样是CORS方案且只需要经行简单的配置即可配置如下
spring:cloud:gateway:globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题cors-configurations:[/**]: # 对哪些网址进行配置[/**] 指的是所有网址allowedOrigins: # 允许哪些网站的跨域请求- http://localhost:8090- http://www.leyou.comallowedMethods: # 允许的跨域AJAX请求方式- GET- POST- DELETE- PUT- OPTIONSallowedHeaders: * # 允许在请求头中携带的头信息allowedCredentials: true # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期有效期内无需再次检查请求按照这种格式进行配置即可解决跨域问题。