【springcloud】快速搭建一套分布式服务springcloudalibaba(二) ...

打印 上一主题 下一主题

主题 1872|帖子 1872|积分 5616

第二篇 基于nacos搭建分布式项目 网关
项目所需 maven + nacos + java8 + idea + git + mysql(用户信息) + redis(用于限流)
本文通过网关实现用户登录拦截,网关体系/用户体系/商品体系 用户未带token请求除登录以外的任何操纵都被拦截返回登录页面。
请先准备好情况,可以直接clone下来项目去部署。

  
分布式体系为什么需要网关

在分布式体系中,网关(Gateway) 是一个非常重要的组件,它充当了体系的同一入口,负责处理外部请求并将其路由到内部服务。

  • 同一入口(客户端只需与网关交互,而不需要直接访问内部服务)
  • 路由与负载均衡(请求 /user/** 路由到用户服务,请求 /order/** 路由到订单服务)
  • 安全与认证(网关可以会合处理身份验证(如 JWT、OAuth2)和授权(如权限校验)
  • 限流与熔断(支持熔断和限流机制,当某个服务不可用或者超出瞬时流量限制时,快速失败并返回降级响应。)
  • 日记与监控 (网关可以会合记录请求日记,便于问题排查和性能分析)
  • 跨域支持(网关可以同一处理跨域请求(CORS),制止每个服务单独设置)
  • 灰度发布与流量控制(网关可以根据请求的 Header、参数或其他条件,将流量分发到不同版本的服务。)
    接下里我们一个一个实现看看
图内各个服务节点可以集群部署。

项目布局

快速部署分布式项目
  1. git clone git@gitee.com:goodluckv/ali-cloud-common.git
  2. git clone git@gitee.com:goodluckv/ali-cloud-gateway.git
  3. git clone git@gitee.com:goodluckv/ali-cloud-user.git
  4. git clone git@gitee.com:goodluckv/ali-cloud-goods.git
复制代码

创建项目

快速创建,可参考第一篇快速搭建,参加spring-cloud-starter-gateway。gateway网关项目不需要spring-boot-starter-web包。Spring MVC 是基于阻塞式 I/O 的传统 Web 框架,通常用于构建同步的 Web 应用程序。
Spring Cloud Gateway 是基于 Spring WebFlux 的响应式编程框架,使用非阻塞式 I/O,实用于构建异步、高性能的网关服务。


nacos 中的config
定名gateway-service-dev.yaml
  1. user:
  2.   name: 自动刷新
  3.   age: 30
  4. spring:
  5.   cloud:
  6.     gateway:
  7.       routes:
  8.         - id: user-service
  9.           uri: lb://user-service
  10.           predicates:
  11.             - Path=/user/**
  12.           filters:
  13.             - StripPrefix=1
  14.             # 熔断
  15.             - name: CircuitBreaker
  16.               args:
  17.                 name: systemBreaker
  18.                 fallbackUri: forward:/system/fallback/tip
  19.             # 限流
  20.             - name: RequestRateLimiter
  21.               args:
  22.                 redis-rate-limiter.replenishRate: 1 # 每秒允许的请求数
  23.                 redis-rate-limiter.burstCapacity: 5 # 每秒最大请求数
  24.                 key-resolver: "#{@pathKeyResolver}"  # 限流的键解析器
  25.         - id: login-service
  26.           uri: lb://user-service
  27.           predicates:
  28.             - Path=/account/**
复制代码
路由参数剖析

路由可以直接设置在nacos的动态设置中
*[HTML]:
设置分类‌‌设置项‌‌用途阐明‌‌示例值/设置‌‌路由设置‌‌spring.cloud.gateway.routes.id路由唯一标识符,用于区分不同路由规则user-servicespring.cloud.gateway.routes.uri目的服务URI(支持http、lb负载均衡模式)lb://user-service 或 http://localhost:8080 spring.cloud.gateway.routes.predicates断言条件集合,用于匹配HTTP请求特性(如路径、请求头等)- Path=/api/**
- Method=GETspring.cloud.gateway.routes.filters过滤器集合,用于修改请求/响应(如添加头、路径重写等)- AddRequestHeader=X-Request-Id,123
- StripPrefix=2 (去除前缀)‌全局设置‌‌spring.cloud.gateway.discovery.locator.enabled是否与服务发现组件集成(如Eureka),启用动态路由truespring.cloud.gateway.default-filters全局过滤器列表,作用于全部路由- DedupeResponseHeader=Access-Control-Allow-Origin‌跨域设置‌‌spring.cloud.gateway.globalcors.cors-configurations设置跨域资源共享(CORS)规则'/**':
allowedOrigins: "*"
allowedMethods: ["GET", "OST"]‌HTTP客户端设置‌‌spring.cloud.gateway.httpclient.pool.max-connections设置HTTP连接池最大连接数(优化高并发场景)500spring.cloud.gateway.httpclient.connect-timeout连接超时时间(毫秒)30000‌限流设置‌‌spring.cloud.gateway.ratelimiter.enabled是否启用请求速率限制(需共同Redis等存储)truespring.cloud.gateway.ratelimiter.redis-rate-limiter.replenishRate每秒允许的请求数10‌指标监控‌‌spring.cloud.gateway.metrics.enabled启用Prometheus等监控指标收罗true‌超时设置‌‌spring.cloud.gateway.httpclient.response-timeout响应超时时间(毫秒)60000 实在重要用到的就那几个就可以实现。(示例)

  1. spring:
  2.   cloud:
  3.     gateway:
  4.       routes:
  5.         - id: user-service
  6.           uri: lb://user-service
  7.           predicates:
  8.             - Path=/user/**
  9.           filters:
  10.             - StripPrefix=1
复制代码
spring.cloud.gateway.routes.filters

关于过滤器 又有许多 参数 ,好比熔断与限流都可以在这内里设置
*[HTML]:
过滤器名称‌‌用途阐明‌‌示例设置‌‌泉源‌AddRequestHeader添加请求头,常用于传递认证信息或自界说标识- AddRequestHeader=X-User-Id, 1001‌AddRequestParameter添加请求参数,常用于增补请求参数- AddRequestParameter=key1, value1‌PrefixPath在请求路径前添加前缀,用于同一接口前缀- PrefixPath=/api/v1‌StripPrefix去除路径前缀,将请求转发到后端时忽略指定层级的路径- StripPrefix=2(移除路径前两个层级)‌RewritePath重写请求路径,支持正则表达式匹配和更换- RewritePath=/old/(?<segment>.*), /new/$\{segment}‌Retry设置请求重试计谋(如超时重试次数、状态码触发条件)- Retry=3(默认重试3次)
- Retry=retries=3,statuses=500,methods=GET‌RequestRateLimiter基于令牌桶算法限流,需共同 Redis 或其他存储实现- RequestRateLimiter=10, 20, #{@userKeyResolver}(每秒10令牌,容量20)‌SetStatus强制修改响应状态码,常用于同一异常处理- SetStatus=401‌RemoveRequestHeader移除指定请求头,用于敏感信息过滤- RemoveRequestHeader=Authorization‌RemoveResponseHeader移除指定响应头,用于隐蔽后端服务细节- RemoveResponseHeader=Server‌SaveSession强制保存 WebSession,用于需要会话管理的场景- SaveSession‌RedirectTo重定向请求,支持 HTTP 状态码和 URL 设置- RedirectTo=302, http://example.com‌ 过滤器示例(熔断器与限流)

  1. spring:
  2.   cloud:
  3.     gateway:
  4.       routes:
  5.         - id: user-service
  6.           uri: lb://user-service
  7.           predicates:
  8.           # 请求头为/user开头的uri都路由到userservice服务
  9.             - Path=/user/**
  10.           filters:
  11.           # StripPrefix 转发的路径第一个/user会被去掉 比如 请求/user/info 实际请求 http://user-service/info 这么配置是为了更好区分各个服务,
  12.             - StripPrefix=1
  13.             # 熔断
  14.             - name: CircuitBreaker
  15.               args:
  16.                 name: systemBreaker
  17.                 fallbackUri: forward:/system/fallback/tip
  18.             # 限流
  19.             - name: RequestRateLimiter
  20.               args:
  21.                 redis-rate-limiter.replenishRate: 1 # 每秒允许的请求数
  22.                 redis-rate-limiter.burstCapacity: 5 # 每秒最大请求数
  23.                 key-resolver: "#{@pathKeyResolver}"  # 限流的键解析器
复制代码
用户认证与日记监控

示例代码中 参加了jwt,我们只需要实现GlobalFilter, Ordered 这俩接口 ,然后重写filter 方法即可实现过滤。可以设置多个过滤器。
示例代码

order 数字越小执行优先级越高(可以写负数)。
  1. @Configuration
  2. @Slf4j
  3. public class GatewayJwtTokenFilter implements GlobalFilter, Ordered {
  4.     @Override
  5.     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  6.         ServerHttpRequest request = exchange.getRequest();
  7.         String rawPath = request.getURI().getRawPath();
  8.         HttpHeaders headers = request.getHeaders();
  9.         log.info("rawPath: {}", rawPath);
  10.         if (!rawPath.startsWith("/account")) {
  11.             // 检查用户是否登录,这里假设通过检查请求头中的某个字段来判断
  12.             String token = exchange.getRequest().getHeaders().getFirst("Authorization");
  13.             Res<UserAccount> res = JwtUtil.getUser(token, UserAccountSecretInit.ACCOUNT_SECRETKEY);
  14.             if (!res.getCode().equals(Res.SUCCESS_CODE)) {
  15.                 // 未登录,重定向到 /login 页面
  16.                 exchange.getResponse().setStatusCode(HttpStatus.FOUND);
  17.                 exchange.getResponse().getHeaders().set("Location", "/account/login.html");
  18.                 return exchange.getResponse().setComplete();
  19.             }
  20.         }
  21.         return chain.filter(exchange);
  22.     }
  23.     @Override
  24.     public int getOrder() {
  25.         return 0;
  26.     }
  27. }
复制代码
熔断与限流

熔断

当某个服务或组件出现故障时,快速失败并停止对其的调用,制止故障扩散到整个体系。有好几种组件,本文用的reactor-resilience4j,阿里的spring-cloud-starter-alibaba-sentinel也不错。
默认情况下服务不可用的话页面返回503
需要使用到spring-cloud-starter-circuitbreaker-reactor-resilience4j
  1.         <dependency>
  2.             <groupId>org.springframework.cloud</groupId>
  3.             <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
  4.         </dependency>
复制代码

模仿用户登录服务瓦解的情况(user-service没有启动)
访问 http://127.0.0.1:8010/account/login.html 网关体系自动重定向到熔断页面,如果不设置熔断页面会提示503

限流

分布式体系限流 是一种用于控制体系中请求流量的技术,目的是在体系资源有限的情况下,确保体系可以或许稳定运行,制止因流量过大而导致体系瓦解或性能下降。
可以限制ip,url,不同用户,每秒请求次数,最大请求次数。
需要使用到redis用于存储key
  1.     <!-- Redis Reactive (用于限流) -->
  2.     <dependency>
  3.         <groupId>org.springframework.boot</groupId>
  4.         <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
  5.     </dependency>
复制代码
自界说限流key

  1.     @Bean
  2.     public KeyResolver pathKeyResolver() {
  3.         KeyResolver keyResolver = pathKeyGet();
  4.         log.info(keyResolver.toString());
  5.         log.info("创建限流key存入redis: {} ", JSON.toJSONString(keyResolver));
  6.         return keyResolver;
  7.     }
  8.     public KeyResolver pathKeyGet() {
  9.         return exchange -> {
  10.             // 获取请求路径
  11.             String path = exchange.getRequest().getPath().toString();
  12.             String hostAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
  13.             String key = hostAddress + "_" + path;
  14.             log.info("compositeKey 限流key:{}", key);
  15.             return Mono.just(key);
  16.         };
  17.     }
复制代码
测试

我设置的同一ip每秒请求同一url不能超过3次,在我本地测试第四次会出现该页面。计算方式根据控制台效果是按第一次请求时间开始算的,如果第一次请求过了一秒,按顺序从第二次请求时间开始算。

灰度发布与流量控制

基于路径的流量分发

可以直接将user服务前置一个版本的uri,好比/v1/user/xxx /v2/user/xxx
  1. spring:
  2.   cloud:
  3.     gateway:
  4.       routes:
  5.         - id: v1_route
  6.           uri: lb://user-service-v1
  7.           predicates:
  8.             - Path=/v1/user/**
  9.           filters:
  10.             - StripPrefix=2
  11.         - id: v2_route
  12.           uri: lb://user-service-v2
  13.           predicates:
  14.             - Path=/v2/user/**
  15.          filters:
  16.             - StripPrefix=2
复制代码
基于 Header 的流量分发

通过请求头中(如 version)将流量分发到不同版本的服务
  1. spring:
  2.   cloud:
  3.     gateway:
  4.       routes:
  5.         - id: v1_route
  6.           uri: lb://user-service-v1
  7.           predicates:
  8.             - Header=version, v1  # 匹配请求头 version=v1
  9.         - id: v2_route
  10.           uri: lb://user-service-v2
  11.           predicates:
  12.             - Header=version, v2  # 匹配请求头 version=v2
复制代码
基于权重的流量分发

Weight 过滤器用于按权重分发流量。
group1 是分组的名称,相同分组的权重总和应为 100。
  1. spring:
  2.   cloud:
  3.     gateway:
  4.       routes:
  5.         - id: weight_route
  6.           uri: lb://user-service-v1
  7.           predicates:
  8.             - Path=/service/**
  9.           filters:
  10.             - Weight=group1, 80  # 80% 的流量
  11.         - id: weight_route_v2
  12.           uri: lb://user-service-v2
  13.           predicates:
  14.             - Path=/service/**
  15.           filters:
  16.             - Weight=group1, 20  # 20% 的流量
复制代码
结尾

第一篇快速部署一套分布式服务
希望本文可以帮到你。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

尚未崩坏

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表