网站自适应案例,为什么网站显示建设中,外贸网站建设推广,案例中优衣库所采用的网络营销方式从本文开始#xff0c;笔者将总结 spring cloud 相关内容的教程
版本选择
为了适应 java8#xff0c;笔者选择了下面的版本#xff0c;后续会出 java17的以SpringBoot3.0.X为主的教程 SpringBoot 版本 2.6.5 SpringCloud 版本 2021.0.1 SpringCloudAlibaba 版本 2021.0.1.…从本文开始笔者将总结 spring cloud 相关内容的教程
版本选择
为了适应 java8笔者选择了下面的版本后续会出 java17的以SpringBoot3.0.X为主的教程 SpringBoot 版本 2.6.5 SpringCloud 版本 2021.0.1 SpringCloudAlibaba 版本 2021.0.1.0 SpringCloudAlibaba github 版本说明截图 SpringCloud 官网https://spring.io/projects/spring-cloud
Spring Cloud Alibaba 官网https://sca.aliyun.com/zh-cn/ 目录
1、环境准备
2、项目创建
3、测试限流
4、改进限流返回
5、项目代码 1、环境准备
本文讲解Spring Cloud Gateway 使用 Redis 限流注册中心使用 Nacos
Macos 官网https://nacos.io/zh-cn/index.html
Nacos 安装这里不做过多介绍不了解的朋友可以参考
Nacos 单机安装https://blog.csdn.net/wsjzzcbq/article/details/123916233
Nacos 集群安装https://blog.csdn.net/wsjzzcbq/article/details/123956116
笔者使用 docker 开启 nacos 和 redis
Spring Cloud Alibaba 2021.0.1.0 版本对应的nacos版本是 1.4.2
笔者使用的 Naocs 版本是 2.0.0-bugfixredis 版本是 7.0.6 2、项目创建
新建 maven 聚合项目 cloud-learn
最外层父工程 cloud-learn 的 pom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.wsjzzcbq/groupIdartifactIdcloud-learn/artifactIdversion1.0-SNAPSHOT/versionmodulesmodulegateway-learn/modulemoduleconsumer-learn/module/modulespackagingpom/packagingrepositoriesrepositoryidnaxus-aliyun/idnamenaxus-aliyun/nameurlhttps://maven.aliyun.com/repository/public/urlreleasesenabledtrue/enabled/releasessnapshotsenabledfalse/enabled/snapshots/repository/repositoriesparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.6.5/versionrelativePath//parentpropertiesspring-cloud.version2021.0.1/spring-cloud.versionspring-cloud-alibaba.version2021.0.1.0/spring-cloud-alibaba.versionalibaba-nacos-discovery.veriosn2021.1/alibaba-nacos-discovery.veriosnalibaba-nacos-config.version2021.1/alibaba-nacos-config.versionspring-cloud-starter-bootstrap.version3.1.1/spring-cloud-starter-bootstrap.version/propertiesdependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion${spring-cloud-alibaba.version}/versiontypepom/typescopeimport/scope/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactIdversion${alibaba-nacos-discovery.veriosn}/version/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-config/artifactIdversion${alibaba-nacos-config.version}/version/dependency!--spring-cloud-dependencies 2020.0.0 版本不在默认加载bootstrap文件如果需要加载bootstrap文件需要手动添加依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-bootstrap/artifactIdversion${spring-cloud-starter-bootstrap.version}/version/dependencydependencygroupIdcom.alibaba.fastjson2/groupIdartifactIdfastjson2/artifactIdversion2.0.40/version/dependency/dependencies/dependencyManagementdependenciesdependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency/dependencies/project
然后创建2个子工程 consumer-learn 和 gateway-learn
gateway-learn 中配置路由转发到 consumer-learn consumer-learn 工程 pom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdcloud-learn/artifactIdgroupIdcom.wsjzzcbq/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdconsumer-learn/artifactIddependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency!--feign负载均衡--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build
/project
consumer-learn 工程 启动类
package com.wsjzzcbq;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** ConsumerApplication** author wsjz* date 2023/09/17*/
EnableFeignClients
SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}
}consumer-learn 工程 配置文件
spring.application.nameconsumer-learn
server.port8081
spring.cloud.nacos.discovery.usernamenacos
spring.cloud.nacos.discovery.passwordnacos
spring.cloud.nacos.discovery.server-addr192.168.31.152:8848
spring.cloud.nacos.discovery.namespacepublic
logging.level.com.alibaba.cloudlearnconsumer.feign.ProducerServiceDEBUGconsumer-learn 工程 controller
package com.wsjzzcbq.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** ConsumerController** author wsjz* date 2023/09/17*/
RestController
public class ConsumerController {RequestMapping(/name)public String user() {return 宝剑锋从磨砺出梅花香自苦寒来;}
}gateway-learn
gateway-learn 工程 pom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdcloud-learn/artifactIdgroupIdcom.wsjzzcbq/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdgateway-learn/artifactIddependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!-- gateway负载均衡需要下面依赖不添加会报错503--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId/dependency!--redis使用较高版本5以上版本不要使用windows版redis低版本redis不支持lua中的命令--!--https://blog.csdn.net/wxxiangge/article/details/95024214/--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis-reactive/artifactId/dependencydependencygroupIdcom.alibaba.fastjson2/groupIdartifactIdfastjson2/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project
gateway-learn 工程 启动类
package com.wsjzzcbq;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** GatewayApplication** author wsjz* date 2023/09/17*/
SpringBootApplication
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}
}限流需要实现 KeyResolver 接口的 resolve 方法
在 resolve 方法中返回限流的维度如请求路径、ip地址、请求参数等
笔者这里限流维度是请求路径
package com.wsjzzcbq.limit;import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** ApiKeyResolver** author wsjz* date 2023/09/17*/
Component
public class ApiKeyResolver implements KeyResolver {Overridepublic MonoString resolve(ServerWebExchange exchange) {System.out.println(API限流: exchange.getRequest().getPath().value());return Mono.just(exchange.getRequest().getPath().value());}
}gateway-learn 工程 配置文件
server:port: 9000
spring:application:name: gateway-learnredis:host: 192.168.31.152password: 123456timeout: 5000database: 0cloud:nacos:discovery:server-addr: http://192.168.31.152:8848gateway:routes:- id: consumer-learnuri: lb://consumer-learnpredicates:- Path/cloudlearn/consumer/**filters:- name: RequestRateLimiterargs:key-resolver: #{apiKeyResolver}redis-rate-limiter.replenishRate: 1 #生成令牌速率个/秒redis-rate-limiter.burstCapacity: 2 #令牌桶容量redis-rate-limiter.requestedTokens: 1 #每次消费的Token数量默认是 1- StripPrefix2
配置说明
RequestRateLimiter 是 gateway 提供的限流过滤器
#{apiKeyResolver} 是笔者实现的 ApiKeyResolver
redis-rate-limiter.replenishRate 生成令牌的速率每秒几个
redis-rate-limiter.burstCapacity 令牌桶容量
redis-rate-limiter.requestedTokens 每次消费的令牌数量
当请求到网关以 /cloudlearn/consumer/ 为开头前缀时会路由到 consumer-learn 服务上 创建完成的项目结构 3、测试限流
分别启动 consumer-learn 和 gateway-learn
登录 Nacos 控制台查看 启动成功后可在Naocs 控制台查看注册服务信息
浏览器访问测试限流http://localhost:9000/cloudlearn/consumer/name
运行效果 可以看到当1秒钟内请求超过2次时会被限流 4、改进限流返回
上面代码实现了限流但限流触发后返回的是429不利于前端处理这里我们可以在默认的限流过滤器基础上进行改进自定义限流时的返回
新建 NewRequestRateLimiterGatewayFilterFactory 类
继承默认的 RequestRateLimiterGatewayFilterFactory
package com.wsjzzcbq.filter;import com.alibaba.fastjson2.JSONObject;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.HttpStatusHolder;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;/*** NewRequestRateLimiterGatewayFilterFactory** author wsjz* date 2023/09/17*/
Component
public class NewRequestRateLimiterGatewayFilterFactory extends RequestRateLimiterGatewayFilterFactory {private final RateLimiter defaultRateLimiter;private final KeyResolver defaultKeyResolver;private boolean denyEmptyKey true;private String emptyKeyStatusCode HttpStatus.FORBIDDEN.name();public NewRequestRateLimiterGatewayFilterFactory(RateLimiter defaultRateLimiter, KeyResolver defaultKeyResolver) {super(defaultRateLimiter, defaultKeyResolver);this.defaultRateLimiter defaultRateLimiter;this.defaultKeyResolver defaultKeyResolver;}Overridepublic GatewayFilter apply(Config config) {System.out.println(过滤限流);KeyResolver resolver (KeyResolver)this.getOrDefault(config.getKeyResolver(), this.defaultKeyResolver);RateLimiterObject limiter (RateLimiter)this.getOrDefault(config.getRateLimiter(), this.defaultRateLimiter);boolean denyEmpty (Boolean)this.getOrDefault(config.getDenyEmptyKey(), this.denyEmptyKey);HttpStatusHolder emptyKeyStatus HttpStatusHolder.parse((String)this.getOrDefault(config.getEmptyKeyStatus(), this.emptyKeyStatusCode));return (exchange, chain) - {return resolver.resolve(exchange).defaultIfEmpty(____EMPTY_KEY__).flatMap((key) - {if (____EMPTY_KEY__.equals(key)) {if (denyEmpty) {ServerWebExchangeUtils.setResponseStatus(exchange, emptyKeyStatus);return exchange.getResponse().setComplete();} else {return chain.filter(exchange);}} else {String routeId config.getRouteId();if (routeId null) {Route route (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);routeId route.getId();}return limiter.isAllowed(routeId, key).flatMap((response) - {Iterator var4 response.getHeaders().entrySet().iterator();while(var4.hasNext()) {Map.EntryString, String header (Map.Entry)var4.next();exchange.getResponse().getHeaders().add((String)header.getKey(), (String)header.getValue());}if (response.isAllowed()) {return chain.filter(exchange);} else {ServerHttpResponse httpResponse exchange.getResponse();httpResponse.getHeaders().set(Content-Type, application/json);JSONObject json new JSONObject();json.put(code, 0);json.put(msg, 当前请求人数较多请稍后再访问);DataBuffer dataBuffer httpResponse.bufferFactory().wrap(json.toJSONString().getBytes(StandardCharsets.UTF_8));return httpResponse.writeWith(Mono.just(dataBuffer));}});}});};}private T T getOrDefault(T configValue, T defaultValue) {return configValue ! null ? configValue : defaultValue;}
}修改配置文件
配置我们自定义的限流过滤器
server:port: 9000
spring:application:name: gateway-learnredis:host: 192.168.31.152password: 123456timeout: 5000database: 0cloud:nacos:discovery:server-addr: http://192.168.31.152:8848gateway:routes:- id: consumer-learnuri: lb://consumer-learnpredicates:- Path/cloudlearn/consumer/**filters:- name: NewRequestRateLimiterargs:key-resolver: #{apiKeyResolver}redis-rate-limiter.replenishRate: 1 #生成令牌速率个/秒redis-rate-limiter.burstCapacity: 2 #令牌桶容量redis-rate-limiter.requestedTokens: 1 #每次消费的Token数量- StripPrefix2
重新启动 gateway-learn
请求测试 5、项目代码
码云地址https://gitee.com/wsjzzcbq/csdn-blog/tree/master/cloud-learn 至此完