当前位置: 首页 > news >正文

做网站的计划概要怎么制作网页设计

做网站的计划概要,怎么制作网页设计,手表网站背景素材,网站推广方式都有哪些问题 Spring Cloud Gateway版本是2.2.9.RELEASE,原本项目中依赖服务自动发现来自动配置路由到微服务的,但是发现将spring.cloud.gateway.discovery.locator.enabledfalse 启动之后Gateway依然会将所有微服务自动注册到路由中,百思不得其解&a…

问题

Spring Cloud Gateway版本是2.2.9.RELEASE,原本项目中依赖服务自动发现来自动配置路由到微服务的,但是发现将spring.cloud.gateway.discovery.locator.enabled=false 启动之后Gateway依然会将所有微服务自动注册到路由中,百思不得其解,遂调试代码观察期启动过曾,记录此文以供参考,官方文档
在这里插入图片描述
可以看到此处明确表示,可以通过设置该值来讲微服务中服务自动添加到配置中。按照这个线索,找到了
org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator#getRouteDefinitions
这个类在之前的文章includeExpression中有提及过,在构造函数中对成员变量

public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLocator {private final DiscoveryLocatorProperties properties;...private Flux<List<ServiceInstance>> serviceInstances;/*** Kept for backwards compatibility. You should use the reactive discovery client.* @param discoveryClient the blocking discovery client* @param properties the configuration properties* @deprecated kept for backwards compatibility*/@Deprecatedpublic DiscoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient,DiscoveryLocatorProperties properties) {this(discoveryClient.getClass().getSimpleName(), properties);serviceInstances = Flux.defer(() -> Flux.fromIterable(discoveryClient.getServices())).map(discoveryClient::getInstances).subscribeOn(Schedulers.boundedElastic());}public DiscoveryClientRouteDefinitionLocator(ReactiveDiscoveryClient discoveryClient,DiscoveryLocatorProperties properties) {this(discoveryClient.getClass().getSimpleName(), properties);serviceInstances = discoveryClient.getServices().flatMap(service -> discoveryClient.getInstances(service).collectList());}...

这里会对serviceInstances进行初始化,从注册中心获取所有已注册的微服务实例进行填充,serviceInstance的获取结束了,在DiscoveryClientRouteDefinitionLocator还有一个重要的方法

#DiscoveryClientRouteDefinitionLocator@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {SpelExpressionParser parser = new SpelExpressionParser();Expression includeExpr = parser.parseExpression(properties.getIncludeExpression());Expression urlExpr = parser.parseExpression(properties.getUrlExpression());Predicate<ServiceInstance> includePredicate;if (properties.getIncludeExpression() == null|| "true".equalsIgnoreCase(properties.getIncludeExpression())) {includePredicate = instance -> true;}else {includePredicate = instance -> {Boolean include = includeExpr.getValue(evalCtxt, instance, Boolean.class);if (include == null) {return false;}return include;};}return serviceInstances.filter(instances -> !instances.isEmpty()).map(instances -> instances.get(0)).filter(includePredicate).map(instance -> {RouteDefinition routeDefinition = buildRouteDefinition(urlExpr,instance);final ServiceInstance instanceForEval = new DelegatingServiceInstance(instance, properties);for (PredicateDefinition original : this.properties.getPredicates()) {PredicateDefinition predicate = new PredicateDefinition();predicate.setName(original.getName());for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {String value = getValueFromExpr(evalCtxt, parser,instanceForEval, entry);predicate.addArg(entry.getKey(), value);}routeDefinition.getPredicates().add(predicate);}for (FilterDefinition original : this.properties.getFilters()) {FilterDefinition filter = new FilterDefinition();filter.setName(original.getName());for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {String value = getValueFromExpr(evalCtxt, parser,instanceForEval, entry);filter.addArg(entry.getKey(), value);}routeDefinition.getFilters().add(filter);}return routeDefinition;});}

根据includeExpr 配置的sl表达式判断当前的serviceInstance是否服务转发要求。填充好predicate,filter之后返回routeDefinition,urlExpr的默认值是"lb://"+serverId,predicate匹配的path就等于serverId,有配置可以转换为小写spring.cloud.gateway.discovery.locator.lower-case-service-id=true因为eureka默认会uppercase serverId,filter中会StripPrefix=1,将路径中的serverId移除再转发给下游。路由定义的部分就这里了,他的刷新逻辑,依靠SpringRefreshContext 事件,具体的定义逻辑在org.springframework.cloud.gateway.config.GatewayAutoConfiguration

	@Bean@ConditionalOnClass(name = "org.springframework.cloud.client.discovery.event.HeartbeatMonitor")public RouteRefreshListener routeRefreshListener(ApplicationEventPublisher publisher) {return new RouteRefreshListener(publisher);}

RouteRefreshListener 实现了ApplicationListener<ApplicationEvent>,监控以下几个事件,并按照条件进行逻辑执行

  • ContextRefreshEvent 启动容器,或者beans重新加载
  • RefreshScopeRefreshdEvent 是 Spring Cloud 中的一个事件,当 @RefreshScope 注解的 beans 被重新加载时发布。这个事件主要用于 Spring Cloud 的配置刷新机制,当配置中心的配置信息发生变化时,会触发该事件以刷新 beans。
  • ParentHeartbeatEvent 是 Spring Cloud Bus 中的一个事件,用于在父上下文(通常是 Spring Cloud Config Server)发生心跳时发布。这个事件用于通知子上下文(如微服务)关于父上下文的健康状态。
  • HeartbeatEvent 是 Spring Cloud Bus 中的另一个事件,用于在服务实例之间广播心跳消息,以检测和维持各个服务的健康状态。
	public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ContextRefreshedEvent) {ContextRefreshedEvent refreshedEvent = (ContextRefreshedEvent) event;if (!WebServerApplicationContext.hasServerNamespace(refreshedEvent.getApplicationContext(), "management")) {reset();}}else if (event instanceof RefreshScopeRefreshedEvent|| event instanceof InstanceRegisteredEvent) {reset();}else if (event instanceof ParentHeartbeatEvent) {ParentHeartbeatEvent e = (ParentHeartbeatEvent) event;resetIfNeeded(e.getValue());}else if (event instanceof HeartbeatEvent) {HeartbeatEvent e = (HeartbeatEvent) event;resetIfNeeded(e.getValue());}}

容器启动完成之后,该监听器接收到ContextRefreshedEvent ,会执行reset方法,reset方法主要功能是发送一个RefreshRoutesEvent 事件,定义如下

public class RefreshRoutesEvent extends ApplicationEvent {public RefreshRoutesEvent(Object source) {super(source);}
}

同样在AutoConfig中声明的CachingRouteLocator接收该参数,

tip:另外还有个CachingRouteDefinitionLocator也生命监听 RefreshRoutesEvent事件,但是默认配置下并不会产生任何逻辑

	@Bean@Primary@ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")// TODO: property to disable composite?public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));}

event invoke方法如下

	public void onApplicationEvent(RefreshRoutesEvent event) {try {fetch().collect(Collectors.toList()).subscribe(list -> Flux.fromIterable(list).materialize().collect(Collectors.toList()).subscribe(signals -> {applicationEventPublisher.publishEvent(new RefreshRoutesResultEvent(this));cache.put(CACHE_KEY, signals);}, throwable -> handleRefreshError(throwable)));}catch (Throwable e) {handleRefreshError(e);}}

CompositeRouteLocator的目的是混合 多个来源的Routers定义比如配置文件,接口,注册中心,通过@Bean形式定义的路由。可以理解成mixed route locator。
fetch方法就是获取所有RouteLocator的路由定义
private Flux<Route> fetch() { return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE); }
这里其实就是指定,之前org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator#getRouteDefinitions的方法也就是获取具体的路由定义,获取成功之后放入缓存,Fire RefreshRoutesResultEvent事件就解决了,开发人员可以通过 监听RefreshRoutesResultEvent 主动感知当前的路由变化。路由加载流程到此结束,

后语

我的问题是通过设置spring.cloud.gateway.discovery.locator.enabled依然没有办法让微服务注册失效,在整个流程中并没有看到使用该数值的地方,难道这是一个bug?转念一想DiscoveryClientRouteDefinitionLocator只需要阻止该Bean的注册即可取消掉从eureka获取服务实例的能力,通过引用关系可知

  • org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration.ReactiveDiscoveryClientRouteDefinitionLocatorConfiguration
  • org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration.BlockingDiscoveryClientRouteDefinitionLocatorConfiguration

这里两处找到了其定义,一个是为reactive非阻塞io准备的,一个是为阻塞io准备的,根据源代码可知,具体执行提供那个Locator取决于spring.cloud.discovery.reactive.enabled,我的项目中是通过VM Options参数的形式传入的-Dspring.cloud.config.discovery.enabled=true,所以我在这两个方法处都打了断点。

		@Configuration(proxyBeanMethods = false)@ConditionalOnProperty(value = "spring.cloud.discovery.reactive.enabled",matchIfMissing = true)public static class ReactiveDiscoveryClientRouteDefinitionLocatorConfiguration {@Bean@ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(ReactiveDiscoveryClient discoveryClient,DiscoveryLocatorProperties properties) {return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);}}@Configuration(proxyBeanMethods = false)@Deprecated@ConditionalOnProperty(value = "spring.cloud.discovery.reactive.enabled",havingValue = "false")public static class BlockingDiscoveryClientRouteDefinitionLocatorConfiguration {@Bean@ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);}}

当我准备要执行调试模式想看看具体是哪个Bean被初始化的时候,恍然大悟看到了DiscoveryClientRouteDefinitionLocator的依赖,我自己在GatewayApplication 中手动注册了Bean

    @Beanpublic DiscoveryClientRouteDefinitionLocator discoveryClientRouteLocator(ReactiveDiscoveryClient discoveryClient,DiscoveryLocatorProperties discoveryLocatorProperties) {return new DiscoveryClientRouteDefinitionLocator(discoveryClient, discoveryLocatorProperties);}

真的是笑死,出这个问题的原因是因为最开始的代码使用的出c4o老师生成的,一开始并不明确该代码的作用,后面查看文档才知道用于微服务发现。已经不在关注这里了。

http://www.laogonggong.com/news/17941.html

相关文章:

  • 建筑网站招聘新媒体运营需要哪些技能
  • 广东门户网站建设上海抖音seo
  • 上海网站建设品牌推广模式包括哪些模式
  • wordpress 电子商务seo流量是什么意思
  • 怎么把做的网站优化到百度百度seo刷排名网址
  • 网站建设和seo免费国外ddos网站
  • 网站速度优化免费网站怎么注册
  • 外贸b2b网站开发惠州seo计费
  • 惠州营销网站建设营销网络推广哪家好
  • 别墅设计 网站模板企业营销网站制作
  • 网站界面设计缺点如何做网站关键词优化
  • 莱阳网站建设网络营销策划的目的
  • 做网站需要哪些审核培训心得体会2000字
  • 怎么免费建设金融网站深圳精准网络营销推广
  • 制作网页添加图片济南seo关键词排名工具
  • 做网站注册的商标类别运营和营销是一回事吗
  • 做视频网站收费侵权吗营销方案网站
  • 合肥有哪些公司是做网站的镇江网络
  • 做网站封面要怎么做上海网站制作公司
  • 文案转行做网站编辑台州seo排名公司
  • 深圳定制网站制作靠谱电商网络推广
  • 网站建设定制公众号软文是什么意思
  • 电商网购网站怎么做百度点击工具
  • 专业建站商哈尔滨推广优化公司
  • 100个有趣的网站最常见企业网站有哪些
  • 哔哩哔哩网站怎么做视频网上软文发稿平台
  • 免费给网站做seo免费的网站域名查询
  • 手机制作网站开发培训心得体会感悟
  • 回龙观做网站好的网站或网页
  • 怎么看网站哪个公司做的百度搜索引擎入口登录