【springcloud】快速搭建一套分布式服务springcloudalibaba(二)
第二篇 基于nacos搭建分布式项目 网关项目所需 maven + nacos + java8 + idea + git + mysql(用户信息) + redis(用于限流)
本文通过网关实现用户登录拦截,网关体系/用户体系/商品体系 用户未带token请求除登录以外的任何操纵都被拦截返回登录页面。
请先准备好情况,可以直接clone下来项目去部署。
分布式体系为什么需要网关
在分布式体系中,网关(Gateway) 是一个非常重要的组件,它充当了体系的同一入口,负责处理外部请求并将其路由到内部服务。
[*]同一入口(客户端只需与网关交互,而不需要直接访问内部服务)
[*]路由与负载均衡(请求 /user/** 路由到用户服务,请求 /order/** 路由到订单服务)
[*]安全与认证(网关可以会合处理身份验证(如 JWT、OAuth2)和授权(如权限校验)
[*]限流与熔断(支持熔断和限流机制,当某个服务不可用或者超出瞬时流量限制时,快速失败并返回降级响应。)
[*]日记与监控 (网关可以会合记录请求日记,便于问题排查和性能分析)
[*]跨域支持(网关可以同一处理跨域请求(CORS),制止每个服务单独设置)
[*]灰度发布与流量控制(网关可以根据请求的 Header、参数或其他条件,将流量分发到不同版本的服务。)
接下里我们一个一个实现看看
图内各个服务节点可以集群部署。
https://i-blog.csdnimg.cn/direct/d4d8e51551964ebb960d8a051146e1aa.png
项目布局
快速部署分布式项目
git clone git@gitee.com:goodluckv/ali-cloud-common.git
git clone git@gitee.com:goodluckv/ali-cloud-gateway.git
git clone git@gitee.com:goodluckv/ali-cloud-user.git
git clone git@gitee.com:goodluckv/ali-cloud-goods.git
https://i-blog.csdnimg.cn/direct/4b1f5839a848485fa0fc430b0409e4fb.png
创建项目
快速创建,可参考第一篇快速搭建,参加spring-cloud-starter-gateway。gateway网关项目不需要spring-boot-starter-web包。Spring MVC 是基于阻塞式 I/O 的传统 Web 框架,通常用于构建同步的 Web 应用程序。
Spring Cloud Gateway 是基于 Spring WebFlux 的响应式编程框架,使用非阻塞式 I/O,实用于构建异步、高性能的网关服务。
https://i-blog.csdnimg.cn/direct/ec1cf08749464fe893e607486e66a18e.png
nacos 中的config
定名gateway-service-dev.yaml
user:
name: 自动刷新
age: 30
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- StripPrefix=1
# 熔断
- name: CircuitBreaker
args:
name: systemBreaker
fallbackUri: forward:/system/fallback/tip
# 限流
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1 # 每秒允许的请求数
redis-rate-limiter.burstCapacity: 5 # 每秒最大请求数
key-resolver: "#{@pathKeyResolver}"# 限流的键解析器
- id: login-service
uri: lb://user-service
predicates:
- Path=/account/**
路由参数剖析
路由可以直接设置在nacos的动态设置中
*:
设置分类设置项用途阐明示例值/设置路由设置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", "POST"]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 实在重要用到的就那几个就可以实现。(示例)
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- StripPrefix=1
spring.cloud.gateway.routes.filters
关于过滤器 又有许多 参数 ,好比熔断与限流都可以在这内里设置
*:
过滤器名称用途阐明示例设置泉源AddRequestHeader添加请求头,常用于传递认证信息或自界说标识- AddRequestHeader=X-User-Id, 1001AddRequestParameter添加请求参数,常用于增补请求参数- AddRequestParameter=key1, value1PrefixPath在请求路径前添加前缀,用于同一接口前缀- PrefixPath=/api/v1StripPrefix去除路径前缀,将请求转发到后端时忽略指定层级的路径- StripPrefix=2(移除路径前两个层级)RewritePath重写请求路径,支持正则表达式匹配和更换- RewritePath=/old/(?<segment>.*), /new/$\{segment}Retry设置请求重试计谋(如超时重试次数、状态码触发条件)- Retry=3(默认重试3次)
- Retry=retries=3,statuses=500,methods=GETRequestRateLimiter基于令牌桶算法限流,需共同 Redis 或其他存储实现- RequestRateLimiter=10, 20, #{@userKeyResolver}(每秒10令牌,容量20)SetStatus强制修改响应状态码,常用于同一异常处理- SetStatus=401RemoveRequestHeader移除指定请求头,用于敏感信息过滤- RemoveRequestHeader=AuthorizationRemoveResponseHeader移除指定响应头,用于隐蔽后端服务细节- RemoveResponseHeader=ServerSaveSession强制保存 WebSession,用于需要会话管理的场景- SaveSessionRedirectTo重定向请求,支持 HTTP 状态码和 URL 设置- RedirectTo=302, http://example.com 过滤器示例(熔断器与限流)
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
# 请求头为/user开头的uri都路由到userservice服务
- Path=/user/**
filters:
# StripPrefix 转发的路径第一个/user会被去掉 比如 请求/user/info 实际请求 http://user-service/info 这么配置是为了更好区分各个服务,
- StripPrefix=1
# 熔断
- name: CircuitBreaker
args:
name: systemBreaker
fallbackUri: forward:/system/fallback/tip
# 限流
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1 # 每秒允许的请求数
redis-rate-limiter.burstCapacity: 5 # 每秒最大请求数
key-resolver: "#{@pathKeyResolver}"# 限流的键解析器
用户认证与日记监控
示例代码中 参加了jwt,我们只需要实现GlobalFilter, Ordered 这俩接口 ,然后重写filter 方法即可实现过滤。可以设置多个过滤器。
示例代码
order 数字越小执行优先级越高(可以写负数)。
@Configuration
@Slf4j
public class GatewayJwtTokenFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String rawPath = request.getURI().getRawPath();
HttpHeaders headers = request.getHeaders();
log.info("rawPath: {}", rawPath);
if (!rawPath.startsWith("/account")) {
// 检查用户是否登录,这里假设通过检查请求头中的某个字段来判断
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
Res<UserAccount> res = JwtUtil.getUser(token, UserAccountSecretInit.ACCOUNT_SECRETKEY);
if (!res.getCode().equals(Res.SUCCESS_CODE)) {
// 未登录,重定向到 /login 页面
exchange.getResponse().setStatusCode(HttpStatus.FOUND);
exchange.getResponse().getHeaders().set("Location", "/account/login.html");
return exchange.getResponse().setComplete();
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
熔断与限流
熔断
当某个服务或组件出现故障时,快速失败并停止对其的调用,制止故障扩散到整个体系。有好几种组件,本文用的reactor-resilience4j,阿里的spring-cloud-starter-alibaba-sentinel也不错。
默认情况下服务不可用的话页面返回503
需要使用到spring-cloud-starter-circuitbreaker-reactor-resilience4j
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
https://i-blog.csdnimg.cn/direct/921cf9c597a748868ee998dd62928587.png
模仿用户登录服务瓦解的情况(user-service没有启动)
访问 http://127.0.0.1:8010/account/login.html 网关体系自动重定向到熔断页面,如果不设置熔断页面会提示503
https://i-blog.csdnimg.cn/direct/6e16dda0989147e9b7ffb909e4049d52.png
限流
分布式体系限流 是一种用于控制体系中请求流量的技术,目的是在体系资源有限的情况下,确保体系可以或许稳定运行,制止因流量过大而导致体系瓦解或性能下降。
可以限制ip,url,不同用户,每秒请求次数,最大请求次数。
需要使用到redis用于存储key
<!-- Redis Reactive (用于限流) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
自界说限流key
@Bean
public KeyResolver pathKeyResolver() {
KeyResolver keyResolver = pathKeyGet();
log.info(keyResolver.toString());
log.info("创建限流key存入redis: {} ", JSON.toJSONString(keyResolver));
return keyResolver;
}
public KeyResolver pathKeyGet() {
return exchange -> {
// 获取请求路径
String path = exchange.getRequest().getPath().toString();
String hostAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
String key = hostAddress + "_" + path;
log.info("compositeKey 限流key:{}", key);
return Mono.just(key);
};
}
测试
我设置的同一ip每秒请求同一url不能超过3次,在我本地测试第四次会出现该页面。计算方式根据控制台效果是按第一次请求时间开始算的,如果第一次请求过了一秒,按顺序从第二次请求时间开始算。
https://i-blog.csdnimg.cn/direct/b5c50d39c4a84300ad439595c6d43c94.png
灰度发布与流量控制
基于路径的流量分发
可以直接将user服务前置一个版本的uri,好比/v1/user/xxx /v2/user/xxx
spring:
cloud:
gateway:
routes:
- id: v1_route
uri: lb://user-service-v1
predicates:
- Path=/v1/user/**
filters:
- StripPrefix=2
- id: v2_route
uri: lb://user-service-v2
predicates:
- Path=/v2/user/**
filters:
- StripPrefix=2
基于 Header 的流量分发
通过请求头中(如 version)将流量分发到不同版本的服务
spring:
cloud:
gateway:
routes:
- id: v1_route
uri: lb://user-service-v1
predicates:
- Header=version, v1# 匹配请求头 version=v1
- id: v2_route
uri: lb://user-service-v2
predicates:
- Header=version, v2# 匹配请求头 version=v2
基于权重的流量分发
Weight 过滤器用于按权重分发流量。
group1 是分组的名称,相同分组的权重总和应为 100。
spring:
cloud:
gateway:
routes:
- id: weight_route
uri: lb://user-service-v1
predicates:
- Path=/service/**
filters:
- Weight=group1, 80# 80% 的流量
- id: weight_route_v2
uri: lb://user-service-v2
predicates:
- Path=/service/**
filters:
- Weight=group1, 20# 20% 的流量
结尾
第一篇快速部署一套分布式服务
希望本文可以帮到你。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]