网站在线留言怎么做,html教程书,杭州响应式网站制作,图片上传 网站建设教学视频教程源码在最后
一、安装Nacos注册中心
1.1查看Nacos官网#xff0c;安装Nacos服务#xff0c;下载源码或者安装包
1.2启动服务#xff0c;默认端口为8848#xff0c;
二、创建服务注册发现
2.1使用脚手架#xff0c;创建注册服务和发现服务项目#xff0c;我用的版…源码在最后
一、安装Nacos注册中心
1.1查看Nacos官网安装Nacos服务下载源码或者安装包
1.2启动服务默认端口为8848
二、创建服务注册发现
2.1使用脚手架创建注册服务和发现服务项目我用的版本是2.6.13
2.2增加启动类配置用于支持注册服务和发现服务和Feign请求等
2.2.1注册服务增加配置类注解
2.2.2发现服务配置激活Feign
2.2.3创建包nacosdiscoveryprovider包下创建接口EchoServiceController作为注册服务接口 用于后续Feign请求测试启动服务
2.2.4创建发现服务普通RestTemplate接口测试通过RestTemplate请求是否可以转发到注册服务端
2.2.5创建Feign接口
三、创建网关服务
3.1 脚手架创建网关服务
3.2启动类增加注解
3.3创建Controller接口测试服务是否可以正常访问
4.网关服务作为统一入口需要配置断言Predicate机制拦截一个请求在抵达网关层后首先就要进行断言匹配在满足所有断言之后才会进入Filter阶段转发至发现服务nacos-discovery-provider-sample断言配置采用Nacos中心动态配置。
4.1在Nacos中心创建配置
4.2 网关服务application.properties增加配置获取Nacos中心的配置
4.3动态刷新中心配置
4.4增加配置类事件推送类动态更新配置DynamicRouteServiceImpl
4.5项目创建DynamicRouteServiceImplNacos类用于接收动态刷新。
4.5启动网关服务Postman调用网关
5.网关配置JTWtoken鉴权
5.1自定义过滤器鉴权规则 5.2修改Nacos中心nacos-gateway-sample.json断言配置增加过滤器
5.3增加模拟登录接口获取token
四、为服务增加sentinel限流熔断配置
4.1下载按照运行sentinel
4.2网关服务配置sentinel
4.3配置限流规则
4.3.1选择API管理新增API规则
4.3.2新增网关流控规则
4.3.3配置熔断规则
4.3.4配置限流和熔断统一返回值此例是返回值
五、限流熔断配置Nacos持久化
5.1Nacos控制台新建一个限流和熔断配置
5.1.1限流配置
5.1.1熔断配置
5.2项目配置文件增加nacos的数据源配置
5.3创建config类初始化加载配置参数属性
5.4创建限流熔断工厂类加载sentinel相关内容。加载限流、熔断规则自定义限流熔断错误返回处理
5.5 Postman测试
5.5.1限流生效返回
5.5.2熔断生效返回
六 结束语 一、安装Nacos注册中心
1.1查看Nacos官网安装Nacos服务下载源码或者安装包
Nacos 快速开始
1.2启动服务默认端口为8848
进入文件夹cd nacos/bin
以单机模式启动 服务
sh startup.sh -m standalone
登录注册中心查看服务是否正常
二、创建服务注册发现
2.1使用脚手架创建注册服务和发现服务项目我用的版本是2.6.13
项目名称nacos-discovery-provider-sample
脚手架创建的服务包含注册和发现
Cloud Native App Initializer (aliyun.com)
选择组件 项目pom完整内容 ?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.alibaba.cloud/groupIdartifactIdnacos-discovery-provider-sample/artifactIdversion0.0.1-SNAPSHOT/versionnamenacos-discovery-provider-sample/namedescriptionDemo project for Spring Boot/descriptionpropertiesjava.version1.8/java.versionproject.build.sourceEncodingUTF-8/project.build.sourceEncodingproject.reporting.outputEncodingUTF-8/project.reporting.outputEncodingspring-boot.version2.6.13/spring-boot.versionspring-cloud-alibaba.version2021.0.5.0/spring-cloud-alibaba.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactIdexclusionsexclusiongroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-ribbon/artifactId/exclusion/exclusions/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactIdversion3.1.5/version/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactIdversion3.1.5/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependenciesdependencyManagementdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion${spring-boot.version}/versiontypepom/typescopeimport/scope/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion${spring-cloud-alibaba.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.8.1/versionconfigurationsource1.8/sourcetarget1.8/targetencodingUTF-8/encoding/configuration/pluginplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdversion${spring-boot.version}/versionconfigurationmainClasscom.alibaba.cloud.nacosdiscoveryprovidersample.NacosDiscoveryProviderSampleApplication/mainClassskiptrue/skip/configurationexecutionsexecutionidrepackage/idgoalsgoalrepackage/goal/goals/execution/executions/plugin/plugins/build
/projectapplication.properties内容
默认服务名
spring.application.namenacos-discovery-provider-sample
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
spring.application.namenacos-discovery-provider-sample
# Nacos认证信息
spring.cloud.nacos.discovery.usernamenacos
spring.cloud.nacos.discovery.passwordnacos
# Nacos 服务发现与注册配置其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr192.168.100.115:8848
# 注册到 nacos 的指定 namespace默认为 public
spring.cloud.nacos.discovery.namespace23963657-2b3b-49db-be69-f2517dc3695c
#ribbon.nacos.enabledtrue
server.port80822.2增加启动类配置用于支持注册服务和发现服务和Feign请求等
2.2.1注册服务增加配置类注解
EnableDiscoveryClient 开启服务提供者或消费者客户端的支持用来注册服务
EnableFeignClients 开启Feign功能
配置类注解Configuration
/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the License); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an AS IS BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.nacosdiscoveryprovidersample.nacosdiscovery;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;/*** author a hrefmailto:chenxilzx1gmail.comtheonefx/a*/
EnableDiscoveryClient
Configuration
EnableFeignClients
public class NacosDiscoveryConfiguration {
}
2.2.2发现服务配置激活Feign
/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the License); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an AS IS BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.alibaba.cloud.nacosdiscoveryprovidersample.demos.nacosdiscoveryconsumer;import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
EnableFeignClients // 激活 FeignClient
Configuration
public class NacosDiscoveryConsumerConfiguration {}2.2.3创建包nacosdiscoveryprovider包下创建接口EchoServiceController作为注册服务接口 用于后续Feign请求测试启动服务
/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the License); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an AS IS BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.nacosdiscoveryprovidersample.demos.nacosdiscoveryprovider;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;RestController
public class EchoServiceController {GetMapping(/echo/{message})public String echo(PathVariable String message) throws InterruptedException {System.out.println(message);return [ECHO] : message;}GetMapping(/test)public String test() {return [ECHO] : test;}
}
2.2.4创建发现服务普通RestTemplate接口测试通过RestTemplate请求是否可以转发到注册服务端
/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the License); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an AS IS BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.alibaba.cloud.nacosdiscoveryprovidersample.demos.nacosdiscoveryconsumer;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.util.concurrent.Delayed;RestController
public class RestTemplateController {LoadBalancedLazyAutowiredpublic RestTemplate restTemplate;LoadBalancedBeanpublic RestTemplate restTemplate() {return new RestTemplate();}GetMapping(/call/echo/{message})public String callEcho(PathVariable String message) throws InterruptedException {// 访问应用 nacos-discovery-provider-sample 的 EchoServiceController 中的/echo/{message}return restTemplate.getForObject(http://nacos-discovery-provider-sample/echo/ message, String.class);}
}Postman 调用本服务接口 /call/echo/{message}正常访问到接口之后RestTemplate通过路由
http://nacos-discovery-provider-sample/echo/ 路由前缀为注册服务名称 转发的上述
nacosdiscoveryprovider包下接口EchoServiceController。
2.2.5创建Feign接口
创建发现服务Feign 接口用于接收Feign请求转发只服务端接口增加注解
FeignClient(nacos-discovery-provider-sample) 指向服务提供者应用
/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the License); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an AS IS BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.cloud.nacosdiscoveryprovidersample.demos.nacosdiscoveryconsumer;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;FeignClient(nacos-discovery-provider-sample) // 指向服务提供者应用
public interface EchoService {GetMapping(/echo/{message})String echo(PathVariable(message) String message);
}创建FeignController 测试Feign请求
/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the License); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an AS IS BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.alibaba.cloud.nacosdiscoveryprovidersample.demos.nacosdiscoveryconsumer;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;RestController
public class OpenFeignController {Autowiredprivate EchoService echoService;GetMapping(/feign/echo/{message})public String feignEcho(PathVariable String message) throws InterruptedException {return echoService.echo(message);}
}通过Postman 请求接口/feign/echo/{message}
服务根据EchoService 中的FeignClient注解请求会转发至nacos-discovery-provider-sample服务的/echo/{message}接口
至此Nacos中心搭建完成注册服务和发现服务注册成功并且服务支持Fdign请求。
三、创建网关服务
3.1 脚手架创建网关服务
Cloud Native App Initializer (aliyun.com) 项目pom完整内容
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.alibaba.cloud/groupIdartifactIdnacos-gateway-sample/artifactIdversion0.0.1-SNAPSHOT/versionnamenacos-gateway-sample/namedescriptionDemo project for Spring Boot/descriptionpropertiesjava.version1.8/java.versionproject.build.sourceEncodingUTF-8/project.build.sourceEncodingproject.reporting.outputEncodingUTF-8/project.reporting.outputEncodingspring-boot.version2.6.13/spring-boot.versionspring-cloud-alibaba.version2021.0.5.0/spring-cloud-alibaba.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactIdversion3.1.5/version/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-sentinel-gateway/artifactId/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-gateway-server/artifactIdversion3.1.5/version/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactIdversion3.1.5/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.4/versionscopeprovided/scope/dependencydependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.76/version/dependencydependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.3.10/version/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-gateway-server/artifactIdversion3.1.5/version/dependencydependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.0/version/dependencydependencygroupIdjavax.xml.bind/groupIdartifactIdjaxb-api/artifactIdversion2.3.1/version/dependencydependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-crypto/artifactId/dependency/dependenciesdependencyManagementdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion${spring-boot.version}/versiontypepom/typescopeimport/scope/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion${spring-cloud-alibaba.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.8.1/versionconfigurationsource1.8/sourcetarget1.8/targetencodingUTF-8/encoding/configuration/pluginplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdversion${spring-boot.version}/versionconfigurationmainClasscom.alibaba.cloud.nacosgatewaysample.NacosGatewaySampleApplication/mainClassskiptrue/skip/configurationexecutionsexecutionidrepackage/idgoalsgoalrepackage/goal/goals/execution/executions/plugin/plugins/build/projectapplication.properties
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
spring.application.namenacos-gateway-sample
server.port9080
# Nacos认证信息
spring.cloud.nacos.discovery.usernamenacos
spring.cloud.nacos.discovery.passwordnacos
## 整合sentinel配置sentinel控制台的地址## 指定控制台的地址默认端口8080
spring.cloud.sentinel.enabledtruespring.main.allow-bean-definition-overriding: true
# Nacos 服务发现与注册配置其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr192.168.100.115:8848
# 注册到 nacos 的指定 namespace默认为 public
spring.cloud.nacos.discovery.namespace23963657-2b3b-49db-be69-f2517dc3695c
#sentinel控制台
spring.cloud.sentinel.transport.dashboard192.168.100.115:9090
##限流或者熔断返回
## 一种是redirect重定向跳转需要同时配置redirect(跳转的uri)
spring.cloud.sentinel.scg.fallback.moderesponse
## 响应的状态
spring.cloud.sentinel.scg.fallback.response-status200
## 响应体
spring.cloud.sentinel.scg.fallback.response-body{code: 200,message: 限流/熔断稍后重试}nacos.gateway.route.config.data-idnacos-gateway-sample.json
nacos.gateway.route.config.groupDEFAULT_GROUP
murg.gateway.jwt.enabledtrue
murg.gateway.jwt.secretfjkfaf;afa
murg.gateway.jwt.headerAuthorization
murg.gateway.jwt.expiration3000000000000000
murg.gateway.jwt.userParamNameusername
murg.gateway.jwt.pwdParamNamepassword
3.2启动类增加注解EnableDiscoveryClient
启动服务登录Nacos注册中心查看网关服务是否正常注册。 3.3创建Controller接口测试服务是否可以正常访问
JwtAuthController /*** 测试*/RequestMapping(/aaa/test)public String testaaa(RequestBody MapString,String map) throws InterruptedException {Thread.sleep(3000);return aaaaaa;}
Postman测试请求/aaa/test
正常返回数据。
4.网关服务作为统一入口需要配置断言Predicate机制拦截一个请求在抵达网关层后首先就要进行断言匹配在满足所有断言之后才会进入Filter阶段转发至发现服务nacos-discovery-provider-sample断言配置采用Nacos中心动态配置。
4.1在Nacos中心创建配置 本例采用Json格式配置详情如下
[ { id:nacos-gateway-sample, order:0, predicates:[ { args:{ pattern:/nacos-discovery-provider-sample/** //路由匹配内容 }, name:Path //通过路由方式拦截 } ], uri:lb://nacos-discovery-provider-sample,//匹配成功转发到的服务地址 } ]
注中心配置内不能有注释在中心把注释删除
4.2 网关服务application.properties增加配置获取Nacos中心的配置
nacos.gateway.route.config.data-idnacos-gateway-sample.json
nacos.gateway.route.config.groupDEFAULT_GROUP
启动网关服务会自动加载Nacos中心中的网关断言配置
4.3动态刷新中心配置
Nacos中心的断言配置如有变化为了不重新服务可以创建动态监听配置类动态刷新
首先需要创建一个网报配置类GatewayConfig读取Nacos相关访问配置为配置监听做准备
package com.alibaba.cloud.nacosgatewaysample.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/*** 配置类读取Nacos相关的配置项用于配置监听器*/
SuppressWarnings(all)
Configuration
public class GatewayConfig {/*** 读取配置的超时时间*/public static final long DEFAULT_TIMEOUT 30000;/*** Nacos 服务器地址*/public static String NACOS_SERVER_ADDR;/*** Nacos 命名空间*/public static String NACOS_NAMESPACE;/*** nacos 配置列表中的dataid*/public static String NACOS_ROUTE_DATE_ID;/*** nacos分组id*/public static String NACOS_GROUP_ID;Value(${spring.cloud.nacos.discovery.server-addr})public void setNacosServerAddr(String nacosServerAddr) {NACOS_SERVER_ADDR nacosServerAddr;}Value(${spring.cloud.nacos.discovery.namespace})public void setNacosNamespace(String nacosNamespace) {NACOS_NAMESPACE nacosNamespace;}Value(${nacos.gateway.route.config.data-id})public void setNacosRouteDateId(String nacosRouteDateId) {NACOS_ROUTE_DATE_ID nacosRouteDateId;}Value(${nacos.gateway.route.config.group})public void setNacosGroupId(String nacosGroupId) {NACOS_GROUP_ID nacosGroupId;}}4.4增加配置类事件推送类动态更新配置DynamicRouteServiceImpl
package com.alibaba.cloud.nacosgatewaysample.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Mono;
import java.util.List;/*** 事件推送 Aware: 动态更新路由网关 Service* */
Slf4j
Service
SuppressWarnings(all)
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {/** 写路由定义 */private final RouteDefinitionWriter routeDefinitionWriter;/** 获取路由定义 */private final RouteDefinitionLocator routeDefinitionLocator;/** 事件发布 */private ApplicationEventPublisher publisher;public DynamicRouteServiceImpl(RouteDefinitionWriter routeDefinitionWriter,RouteDefinitionLocator routeDefinitionLocator) {this.routeDefinitionWriter routeDefinitionWriter;this.routeDefinitionLocator routeDefinitionLocator;}Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {// 完成事件推送句柄的初始化this.publisher applicationEventPublisher;}/*** 从nacos读取路由配hi写道gateway中* h2增加路由定义/h2* */public String addRouteDefinition(RouteDefinition definition) {log.info(gateway add route: [{}], definition);// 保存路由配置并发布routeDefinitionWriter.save(Mono.just(definition)).subscribe();// 发布事件通知给 Gateway, 同步新增的路由定义this.publisher.publishEvent(new RefreshRoutesEvent(this));return success;}/*** h2更新路由/h2* */public String updateList(ListRouteDefinition definitions) {log.info(更新网关路由: [{}], definitions);// 先拿到当前 Gateway 中存储的路由定义ListRouteDefinition routeDefinitionsExits routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();if (!CollectionUtils.isEmpty(routeDefinitionsExits)) {// 清除掉之前所有的 旧的 路由定义routeDefinitionsExits.forEach(rd - {deleteById(rd.getId());log.info(清除掉之前所有的 旧的 路由定义: [{}], rd);});}// 把更新的路由定义同步到 gateway 中definitions.forEach(definition - updateByRouteDefinition(definition));return success;}/*** h2根据路由 id 删除路由配置/h2* */private String deleteById(String id) {try {log.info(要删除的路由id: [{}], id);this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();// 发布事件通知给 gateway 更新路由定义this.publisher.publishEvent(new RefreshRoutesEvent(this));return 删除成功;} catch (Exception ex) {log.error(删除网关路由失败: [{}], ex.getMessage(), ex);return 删除失败;}}/*** h2更新路由/h2* 更新的实现策略比较简单: 删除 新增 更新* */private String updateByRouteDefinition(RouteDefinition definition) {try {log.info(更新网关路由: [{}], definition);this.routeDefinitionWriter.delete(Mono.just(definition.getId()));} catch (Exception ex) {return 更新失败,没有查到更新的网关路由id: definition.getId();}try {this.routeDefinitionWriter.save(Mono.just(definition)).subscribe();this.publisher.publishEvent(new RefreshRoutesEvent(this));return 成功;} catch (Exception ex) {return 更新路由失败;}}
}4.5项目创建DynamicRouteServiceImplNacos类用于接收动态刷新。
package com.alibaba.cloud.nacosgatewaysample.config;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;/*** 通过Nacos下发的动态配置监听nacos中路由配置*/
Slf4j
Component
//再另外一个Bean初始化之后再去初始化当前类
DependsOn({gatewayConfig})
SuppressWarnings(all)
public class DynamicRouteServiceImplNacos {private ConfigService configService;private final DynamicRouteServiceImpl dynamicRouteService;public DynamicRouteServiceImplNacos(DynamicRouteServiceImpl dynamicRouteService){this.dynamicRouteService dynamicRouteService;}/*** 初始化ConfigService** return*/private ConfigService initConfigService() {try {Properties properties new Properties();properties.setProperty(serverAddr, GatewayConfig.NACOS_SERVER_ADDR);properties.setProperty(namespace, GatewayConfig.NACOS_NAMESPACE);return configService NacosFactory.createConfigService(properties);} catch (Exception ex) {log.error(初始化配置服务:[{}], ex.getMessage());return null;}}/*** bean在容器中构造完成之后会立即执行当前的init方法* 加载路由信息注册监听器*/PostConstructpublic void init(){log.info(网关路由初始化...);try {//初始化nacos配置客户端configService initConfigService();if(configServicenull){log.error(初始化配置服务异常,配置服务是null!);return;}//通过 nacos config 并指定路由配置路径去获取路由配置String configInfo configService.getConfig(GatewayConfig.NACOS_ROUTE_DATE_ID,GatewayConfig.NACOS_GROUP_ID,GatewayConfig.DEFAULT_TIMEOUT);log.info(当前网关配置信息:[{}]:,configInfo);//反序列化ListRouteDefinition routeDefinitions JSON.parseArray(configInfo, RouteDefinition.class);if(CollectionUtil.isNotEmpty(routeDefinitions)){//新增for (RouteDefinition routeDefinition : routeDefinitions) {log.info(初始化 路由定义对象 信息:[{}]:,routeDefinition);dynamicRouteService.addRouteDefinition(routeDefinition);}}} catch (Exception e) {log.error(网关路由初始化失败:[{}],e.getMessage());}//设置监听器dynamicRouteServiceImplNacosByListener(GatewayConfig.NACOS_ROUTE_DATE_ID, GatewayConfig.NACOS_GROUP_ID);}/*** 监听 Nacos下发的动态路由配置** param dataId* param group*/private void dynamicRouteServiceImplNacosByListener(String dataId, String group) {try {//给Nacos config 客户端增加一个监听器configService.addListener(dataId, group, new Listener() {/*** 自己提供线程池执行操作* return*/Overridepublic Executor getExecutor() {return null;}/*** 监听器收到接收到配置变更信息* param configInfo nacos 中最新配置信息*/Overridepublic void receiveConfigInfo(String configInfo) {log.info(接收的配置信息:[{}], configInfo);ListRouteDefinition routeDefinitions JSON.parseArray(configInfo, RouteDefinition.class);dynamicRouteService.updateList(routeDefinitions);log.info(更新后的路由配置信息:[{}], routeDefinitions.toString());}});} catch (Exception e) {log.error(监听 Nacos下发的动态路由配置异常:[{}], e.getMessage());}}
}
Nacos中心配置变更发布之后监听更新调用DynamicRouteServiceImpl updateList 实现更新配置
4.5启动网关服务Postman调用网关
路由/nacos-discovery-provider-sample/call/echo/nnn
根据断言配置的 pattern:/nacos-discovery-provider-sample/** 匹配到前缀网关自动转发至
发现服务nacos-discovery-provider-sample的/call/echo/nnn接口控制台输出nnn
5.网关配置JTWtoken鉴权
为网关配置鉴权过滤器
pom引入以下配置
dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.0/version/dependencydependencygroupIdjavax.xml.bind/groupIdartifactIdjaxb-api/artifactIdversion2.3.1/version/dependencydependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-crypto/artifactId/dependency
5.1自定义过滤器鉴权规则
创建JwtProperties类
package com.alibaba.cloud.nacosgatewaysample.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;Data
ConfigurationProperties(prefix murg.gateway.jwt)
Component
public class JwtProperties {//是否开启JWT即注入相关的类对象private Boolean enabled;//JWT密钥private String secret;//JWT有效时间private Long expiration;//前端向后端传递JWT时使用HTTP的header名称前后端要统一private String header;//用户登录-用户名参数名称private String userParamName username;//用户登录-密码参数名称private String pwdParamName password;}
application.properties增加 JWT配置
murg.gateway.jwt.enabledtrue
murg.gateway.jwt.secretfjkfaf;afa
murg.gateway.jwt.headerAuthorization
murg.gateway.jwt.expiration3000000000000000
murg.gateway.jwt.userParamNameusername
murg.gateway.jwt.pwdParamNamepassword创建JTWUtile鉴权逻辑
package com.alibaba.cloud.nacosgatewaysample.config;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;Component
public class JwtTokenUtil {Resourceprivate JwtProperties jwtProperties;/*** 生成token令牌** param userId 用户Id或用户名* param payloads 令牌中携带的附加信息* return 令token牌*/public String generateToken(String userId,MapString,String payloads) {int payloadSizes payloads null? 0 : payloads.size();MapString, Object claims new HashMap(payloadSizes 2);claims.put(sub, userId);claims.put(created, new Date());if(payloadSizes 0){for(Map.EntryString,String entry:payloads.entrySet()){claims.put(entry.getKey(),entry.getValue());}}return generateToken(claims);}/*** 从令牌中获取用户名** param token 令牌* return 用户名*/public String getUsernameFromToken(String token) {String username;try {Claims claims getClaimsFromToken(token);username claims.getSubject();} catch (Exception e) {username null;}return username;}/*** 判断令牌是否过期** param token 令牌* return 是否过期*/public Boolean isTokenExpired(String token) {try {Claims claims getClaimsFromToken(token);Date expiration claims.getExpiration();return expiration.before(new Date());} catch (Exception e) {//验证JWT签名失败等同于令牌过期return true;}}/*** 刷新令牌** param token 原令牌* return 新令牌*/public String refreshToken(String token) {String refreshedToken;try {Claims claims getClaimsFromToken(token);claims.put(created, new Date());refreshedToken generateToken(claims);} catch (Exception e) {refreshedToken null;}return refreshedToken;}/*** 验证令牌** param token 令牌* param userId 用户Id用户名* return 是否有效*/public Boolean validateToken(String token, String userId) {String username getUsernameFromToken(token);return (username.equals(userId) !isTokenExpired(token));}/*** 从claims生成令牌,如果看不懂就看谁调用它** param claims 数据声明* return 令牌*/private String generateToken(MapString, Object claims) {Date expirationDate new Date(System.currentTimeMillis() jwtProperties.getExpiration());return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret()).compact();}/*** 从令牌中获取数据声明,验证JWT签名** param token 令牌* return 数据声明*/private Claims getClaimsFromToken(String token) {Claims claims;try {claims Jwts.parser().setSigningKey(jwtProperties.getSecret()).parseClaimsJws(token).getBody();} catch (Exception e) {claims null;}return claims;}
}创建JWTAuthCheckFilter自定义过滤规则实现JTW鉴权Order注解配置自动注入顺序后注入防止先加载。
/authentication模拟登录注册接口此接口放行。package com.alibaba.cloud.nacosgatewaysample.Filter;import com.alibaba.cloud.nacosgatewaysample.config.JwtProperties;
import com.alibaba.cloud.nacosgatewaysample.config.JwtTokenUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;Configuration
Order(-101)
public class JWTAuthCheckFilter implements GatewayFilter, Ordered {Resourceprivate JwtProperties jwtProperties;Resourceprivate JwtTokenUtil jwtTokenUtil;//将JWT鉴权失败的消息响应给客户端private MonoVoid writeUnAuthorizedMessageAsJson(ServerHttpResponse serverHttpResponse, String message) {serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);Map reusltnew HashMap();reuslt. put(code,401);reuslt. put(msg,鉴权失败);serverHttpResponse.getHeaders().add(Content-Type, application/json;charsetUTF-8);DataBuffer dataBuffer serverHttpResponse.bufferFactory().wrap(JSON.toJSONStringWithDateFormat(reuslt,JSON.DEFFAULT_DATE_FORMAT).getBytes(StandardCharsets.UTF_8));return serverHttpResponse.writeWith(Flux.just(dataBuffer));}Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest serverHttpRequest exchange.getRequest();ServerHttpResponse serverHttpResponse exchange.getResponse();String requestUrl serverHttpRequest.getURI().getPath();if(!requestUrl.equals(/authentication)){//从HTTP请求头中获取JWT令牌String jwtToken serverHttpRequest.getHeaders().getFirst(jwtProperties.getHeader());//对Token解签名并验证Token是否过期boolean isJwtNotValid jwtTokenUtil.isTokenExpired(jwtToken);if(isJwtNotValid){ //如果JWT令牌不合法return writeUnAuthorizedMessageAsJson(serverHttpResponse,请先去登录再访问服务);}//从JWT中解析出当前用户的身份userId并继续执行过滤器链转发请求ServerHttpRequest mutableReq serverHttpRequest.mutate().header(userId, jwtTokenUtil.getUsernameFromToken(jwtToken)).build();ServerWebExchange mutableExchange exchange.mutate().request(mutableReq).build();return chain.filter(mutableExchange);}else{ //如果是登录认证请求直接执行不需要进行JWT权限验证return chain.filter(exchange);}}Overridepublic int getOrder() {return 101;}
}自定义过滤器工厂为网关加载过滤器使用
package com.alibaba.cloud.nacosgatewaysample.Filter;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;Component
public class JWTAuthCheckFilterFactory extends AbstractGatewayFilterFactoryObject {AutowiredJWTAuthCheckFilter jWTAuthCheckFilte;Overridepublic GatewayFilter apply(Object config) {return jWTAuthCheckFilte;}
}5.2修改Nacos中心nacos-gateway-sample.json断言配置增加过滤器
[{id:nacos-gateway-sample, order:0, predicates:[ {args:{pattern:/nacos-discovery-provider-sample/** },name:Path }],uri:lb://nacos-discovery-provider-sample,filters:[{name:JWTAuthCheckFilterFactory},{name:StripPrefix, args:{parts:1} }]}
]
filters的name指定为自定义工厂JWTAuthCheckFilterFactory。
至此鉴权流程完成。
5.3增加模拟登录接口获取token
/*** 使用用户名密码换JWT令牌*/RequestMapping(/authentication)public MonoMap authentication(RequestBody MapString,String map){//从请求体中获取用户名密码String username map.get(jwtProperties.getUserParamName());String password map.get(jwtProperties.getPwdParamName());if(StringUtils.isEmpty(username)|| StringUtils.isEmpty(password)){return buildErrorResponse(用户名或者密码不能为空);}//根据用户名用户Id去数据库查找该用户SysUser sysUser new SysUser();sysUser.setPassword(123456);if(sysUser ! null){//将数据库的加密密码与用户明文密码match// boolean isAuthenticated passwordEncoder.matches(123456,sysUser.getPassword());boolean isAuthenticated123456.equals(sysUser.getPassword());if(isAuthenticated){ //如果匹配成功//通过jwtTokenUtil生成JWT令牌并returnreturn buildSuccessResponse(jwtTokenUtil.generateToken(username,null));} else{ //如果密码匹配失败return buildErrorResponse(请确定您输入的用户名或密码是否正确);}}else{return buildErrorResponse(请确定您输入的用户名或密码是否正确);}}
返回TOKEN之后测试请求网关/nacos-discovery-provider-sample/call/echo/nnn
请求Header中带入参数
AuthorizationeyJhbGciOiJIUzUxMiJ9.eyJleHAiOjMwMDE3MDk3Nzc5NjIsInN1YiI6ImFkbWluIiwiY3JlYXRlZCI6MTcwOTc3Nzk2MjQ1Nn0.3pw5NVIhiMggFvPEDvUHGX_Iy8EyLT0EQGQS7Xf3bAiu5GhAFHvtSd2_3nsOMzjtAbYT2sk2ffx122cLBXQzPQ
接口正常。去掉Authorization接口返回
{ msg: 鉴权失败, code: 401 }
四、为服务增加sentinel限流熔断配置
4.1下载按照运行sentinel
下载Sentinel: 官网阿里 Sentinelsentinel
Sentinel: 官网阿里 Sentinel
启动sentinel指定管理界面端口为9092
nohup java -Dserver.port9090 -Dcsp.sentinel.dashboard.serverlocalhost:9092 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.7.jar
登录管理端 用户名密码默认 sentinel/sentinel 4.2网关服务配置sentinel
application.properties增加## 整合sentinel配置sentinel控制台的地址## 指定控制台的地址默认端口8080
spring.cloud.sentinel.enabledtrue
#sentinel控制台
spring.cloud.sentinel.transport.dashboard192.168.100.115:9090
重启服务,登录sentinel管理端 右侧不显示网关服务
idea增加启动参数
Dcsp.sentinel.dashboard.server192.168.100.115:9090 -Dproject.namenacos-natewayn-ample -Dcsp.sentinel.api.port9090 -Dcsp.sentinel.app.type1
或者启动类增加
重新启动显示正常
正常压测 4.3配置限流规则
本例以路由前缀限流
4.3.1选择API管理新增API规则 新增API分组 匹配串 /nacos-discovery-provider-sample/**
4.3.2新增网关流控规则
限流配置完成
压测截图 4.3.3配置熔断规则 修改限流规则qps1000停掉发现服务nacos-discovery-provider-sample测试 返回429 熔断生效
4.3.4配置限流和熔断统一返回值此例是返回值 一种是redirect重定向跳转需要同时配置redirect(跳转的uri)
application.properties
spring.cloud.sentinel.scg.fallback.moderesponse
## 响应的状态
spring.cloud.sentinel.scg.fallback.response-status200
## 响应体
spring.cloud.sentinel.scg.fallback.response-body{\code\:\429\,\msg\:\请求太多了\}
重新启动服务nacos-discovery-provider-sample测试限流返回 返回正常200数据。
五、限流熔断配置Nacos持久化
限流和熔断配置在网关服务重启之后会失效在sentinel中会消失改为Nacos持久化配置
引入依赖
dependency groupIdcom.alibaba.csp/groupId artifactIdsentinel-datasource-nacos/artifactId /dependency
5.1Nacos控制台新建一个限流和熔断配置
5.1.1限流配置
nacos-discovery-provider-sample-flow的json配置内容如下
[{resource: nacos-gateway-sample,controlBehavior: 0,count: 100,grade: 1,limitApp: default,strategy: 0}
]resource资源名称和网关的配置nacos-gateway-sample.json id保持一致指明来源
nacos-gateway-sample limitApp来源应用 grade阈值类型0表示线程数1表示QPS count单机阈值 strategy流控模式0表示直接1表示关联2表示链路 controlBehavior流控效果0表示快速失败1表示Warm Up2表示排队等待 clusterMode是否集群。 5.1.1熔断配置
nacos-discovery-provider-sample-degrade 5.2项目配置文件增加nacos的数据源配置
## 整合sentinel配置sentinel控制台的地址## 指定控制台的地址默认端口8080
spring.cloud.sentinel.enabledtrue
#sentinel控制台
spring.cloud.sentinel.transport.dashboard192.168.100.115:9090
#指定限流的配置名字
sentinel.config.nacos.data-id-flownacos-discovery-provider-sample-flow
#指定熔断的配置名字
sentinel.config.nacos.data-id-degradenacos-discovery-provider-sample-degrade
#指定默认分组
sentinel.config.nacos.groupDEFAULT_GROUP
5.3创建config类初始化加载配置参数属性
package com.alibaba.cloud.nacosgatewaysample.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
SuppressWarnings(all)
Configuration
public class SentinelConfig {/*** Nacos 服务器地址*/public static String NACOS_SERVER_ADDR;/*** Nacos 命名空间*/public static String NACOS_SENTINEL_NAMESPACE;/*** Nacos 分组id*/public static String NACOS_SENTINEL_GROUP;/*** nacos 限流配置列表中的dataid*/public static String NACOS_SENTINEL_DATAID_FLOW;/*** nacos 熔断配置列表中的dataid*/public static String NACOS_SENTINEL_DATAID_DEGRADE;Value(${spring.cloud.nacos.discovery.server-addr})public void setNacosServerAddr(String nacosServerAddr) {NACOS_SERVER_ADDR nacosServerAddr;}Value(${spring.cloud.nacos.discovery.namespace})public void setNacosSentinelNamespace(String nacosSentinelNamespace) {NACOS_SENTINEL_NAMESPACE nacosSentinelNamespace;}Value(${sentinel.config.nacos.group})public void setNacosSentinelGroup(String nacosSentinelGroup) {NACOS_SENTINEL_GROUP nacosSentinelGroup;}Value(${sentinel.config.nacos.data-id-flow})public void setNacosSentinelDataidFlow(String nacosSentinelDataidFlow) {NACOS_SENTINEL_DATAID_FLOW nacosSentinelDataidFlow;}Value(${sentinel.config.nacos.data-id-degrade})public void setNacosSentinelDataidDegrade(String nacosSentinelDataidDegrade) {NACOS_SENTINEL_DATAID_DEGRADE nacosSentinelDataidDegrade;}
}5.4创建限流熔断工厂类加载sentinel相关内容。加载限流、熔断规则自定义限流熔断错误返回处理
限流自定义返回状态码429
熔断自定义返回状态码504
package com.alibaba.cloud.nacosgatewaysample.Filter;import com.alibaba.cloud.nacosgatewaysample.config.SentinelConfig;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.api.PropertyKeyConst;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.PostConstruct;
import java.util.*;Component
//再另外一个Bean初始化之后再去初始化当前类
DependsOn({sentinelConfig})//再另外一个Bean初始化之后再去初始化当前类
public class SentinelFactory implements BlockRequestHandler {private ListViewResolver viewResolvers;private ServerCodecConfigurer serverCodecConfigurer;public SentinelFactory(ObjectProviderListViewResolver viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer) {//视图解析this.viewResolvers viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer serverCodecConfigurer;Properties properties new Properties();properties.put(PropertyKeyConst.SERVER_ADDR, SentinelConfig.NACOS_SERVER_ADDR);properties.put(PropertyKeyConst.NAMESPACE, SentinelConfig.NACOS_SENTINEL_NAMESPACE);//加载nacos配置中心的限流规则ReadableDataSourceString, ListFlowRule flowRuleDataSource new NacosDataSource(properties, SentinelConfig.NACOS_SENTINEL_GROUP, SentinelConfig.NACOS_SENTINEL_DATAID_FLOW,source - JSON.parseObject(source, new TypeReferenceListFlowRule() {}));FlowRuleManager.register2Property(flowRuleDataSource.getProperty());//加载nacos配置中心的熔断规则ReadableDataSourceString, ListDegradeRule degradeRuleDataSource new NacosDataSource(properties, SentinelConfig.NACOS_SENTINEL_GROUP, SentinelConfig.NACOS_SENTINEL_DATAID_DEGRADE,source - JSON.parseObject(source, new TypeReferenceListDegradeRule() {}));DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());}//异常处理接收HandlerBeanOrder(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}//这是执行sentinel规则的拦截器Gateway路由之前会先执行这个拦截器BeanOrder(Ordered.HIGHEST_PRECEDENCE)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}Overridepublic MonoServerResponse handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {String path serverWebExchange.getRequest().getPath().pathWithinApplication().value();Map map new HashMap();map.put(error,Unauthorized);map.put(path,path);map.put(status,HttpStatus.TOO_MANY_REQUESTS.value());map.put(imestamp,new Date());if (throwable instanceof FlowException){map.put(message,服务被限流);return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS.value()).contentType(MediaType.APPLICATION_JSON).body(Mono.just(map), Map.class);} else if (throwable instanceof DegradeException) {map.put(message,服务被熔断降级);return ServerResponse.status(HttpStatus.GATEWAY_TIMEOUT.value()).contentType(MediaType.APPLICATION_JSON).body(Mono.just(map), Map.class);}return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value()).contentType(MediaType.APPLICATION_JSON).body(Mono.just(map), Map.class);}}5.5 Postman测试
重启服务调用接口/nacos-discovery-provider-sample/call/echo/nnn测试
5.5.1限流生效返回 5.5.2熔断生效返回 PS按照4.3动态刷新配置 创建监听实现动态加载由于太懒没弄感兴趣的同学可以自行加一下。
六 结束语
以上就是基于Nacos中心部署spring cloud的基础内容包含JTW鉴权网关、feign、sentinel限流熔断等基本内容自学一周大概了解一下内容。
Nacos 文档地址
Nacos官方文档地址Nacos 快速开始
github下载地址:Releases · alibaba/nacos · GitHub gitee下载地址: Nacos 发行版 - Gitee.com
sentinel 文档地址
Read Me - 《Sentinel v1.8 文档手册》 - 书栈网 · BookStackRead Me - 《Sentinel v1.8 文档手册》 - 书栈网 · BookStackRead Me - 《Sentinel v1.8 文档手册》 - 书栈网 · BookStack
脚手架地址
Cloud Native App Initializer (aliyun.com) 源码下载连接 https://download.csdn.net/download/weixin_41647530/88969539
祝福语
同窗共学亦为知己。让我们携手共进相互勉励成为更好的自己。