Nacos、Sentinel、Gateway、Feign学习相关记录
上一篇笔记在2019年06月23日,,,
Nacos+Gateway实现灰度控制
在Gateway增加配置类,如果Header中存在Version(或者自己定义的其他玩意),从符合的服务进行调用,否则走默认的轮询
/*** 灰度控制** 需要在Header中增加version* 如果没有默认走轮询** @author Krasus1966* @date 2021/5/4 22:52**/// 这个注解放在 init 类上了,理论上可以加在能扫描的包上面public class VersionControlSupplier extends DiscoveryClientServiceInstanceListSupplier {public VersionControlSupplier(DiscoveryClient delegate, Environment environment) {super(delegate, environment);}public VersionControlSupplier(ReactiveDiscoveryClient delegate, Environment environment) {super(delegate, environment);}public Flux<List<ServiceInstance>> get(Request request) {final String requestVersion = ((RequestDataContext) request.getContext()).getClientRequest().getHeaders().getFirst("version");if (requestVersion != null) {return super.get(request).map(list -> {List<ServiceInstance> tmpList = list.stream().filter(instance -> requestVersion.equals(instance.getMetadata().get("version"))).collect(Collectors.toList());return tmpList.isEmpty() ? list : tmpList;});}return super.get(request);}// VersionControlSupplierConfiguration 注册的 beanVersionControlSupplier serviceInstanceListSupplier(ConfigurableApplicationContext context) {ReactiveDiscoveryClient reactiveDiscoveryClient = context.getBean(ReactiveDiscoveryClient.class);return new VersionControlSupplier(reactiveDiscoveryClient, context.getEnvironment());}}
在需要版本控制的服务中增加版本的元数据
spring:cloud:nacos:discovery:# 元数据中增加版本号metadata:version: v1.0
Sentinel推送限流规则到Nacos进行持久化
需要下载Sentinel源码,首次运行前,需要将除DashBoard以外的模块打包进本地Maven仓库,完成后能成功运行DashBoard,就可以将DashBoard模块迁移到需要的项目中。
增加Nacos依赖和配置,能在Nacos控制台看到DashBoard服务。在 test->rule->nacos 目录中有写好的Nacos推送规则相关代码,移动到主目录的rule中。其中的NacosConfig需要增加bean,如果需要拓展其他规则的推送,也可以仿照源代码中内容进行补充。
// 源代码中的限流规则配置,需要拓展其他规则就仿写这里的,对应规则实体在com.alibaba.csp.sentinel.dashboard.datasource.entity.rule 下public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {return JSON::toJSONString;}public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {return s -> JSON.parseArray(s, FlowRuleEntity.class);}// 需要补充Nacos连接配置,不配置的话默认Nacos控制台地址为localhost:8848,命名空间为public,不受bootstrap.yml配置文件管理public ConfigService nacosConfigService() throws Exception {Properties properties = new Properties();// Nacos 控制台地址properties.put(PropertyKeyConst.SERVER_ADDR,serverAddr);// 命名空间properties.put(PropertyKeyConst.NAMESPACE,namespace);return ConfigFactory.createConfigService(properties);}
在对应的Controller中,将SentinelApiClient用源码中的ruleProvider和rulePublisher替换
public class FlowControllerV2 {private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;public Result<List<FlowRuleEntity>> apiQueryMachineRules( String app) {if (StringUtil.isEmpty(app)) {return Result.ofFail(-1, "app can't be null or empty");}try {// 此处的获得规则列表用ruleProvider.getRules(appName)获得,其他方法基本相同List<FlowRuleEntity> rules = ruleProvider.getRules(app);if (rules != null && !rules.isEmpty()) {for (FlowRuleEntity entity : rules) {entity.setApp(app);if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) {entity.setId(entity.getClusterConfig().getFlowId());}}}rules = repository.saveAll(rules);return Result.ofSuccess(rules);} catch (Throwable throwable) {logger.error("Error when querying flow rules", throwable);return Result.ofThrowable(-1, throwable);}}// 需要将方法修改成以下内容private void publishRules(/*@NonNull*/ String app) throws Exception {List<FlowRuleEntity> rules = repository.findAllByApp(app);rulePublisher.publish(app, rules);}}
<li ui-sref-active="active" ng-if="!entry.isGateway"><!-- 这个a标签中的内容就是js中调用的Controller,其他规则仿写就行 --><a ui-sref="dashboard.flow({app: entry.app})"><i class="glyphicon glyphicon-filter"></i> 流控规则</a></li>
需要注意此处的angular项目需要使用node.js版本10.x(使用n对node.js进行版本管理),修改后使用gulp build进行打包。运行DashBoard后页面报错优先清理缓存。
Nacos内显示如下
Sentinel DashBoard + Gateway
Sentinel可以整合Gateway,Gateway服务中增加以下依赖,并像其他服务一样写Sentinel配置文件。
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId></dependency>
在Gateway的启动类中增加以下代码
// 不增加此代码,或者启动时不在启动参数中写此内容,// Sentinel会把Gateway服务当成普通服务,显示url地址,// 加了会显示链路、API分组等内容System.setProperty("csp.sentinel.app.type", "1");
Feign相关说明
Feign传递Header
public class FeignInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();// jwttemplate.header(AuthInfoConstant.USER_TOKEN, request.getHeader(AuthInfoConstant.USER_TOKEN));// 网关template.header(AuthInfoConstant.GATEWAY_AUTH, request.getHeader(AuthInfoConstant.GATEWAY_AUTH));}}
Feign的继承
Feign的接口可以被Controller继承,Controller中不用再写@RequestMapping和@RequestParam等注解,官网不推荐使用继承特性。
需要注意Feign默认使用Post方式请求,使用@SpringQueryMap替换@RequestParam注解可以实现GET接收数据。
GET下@SpringQueryMap可以接收param和form-data,POST下可以接收x-www-form-urlencoded,JSON格式接不到
