亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot Admin升級boot等組件版本后無法監(jiān)控微服務(wù)問題

 更新時間:2024年08月14日 10:11:54   作者:y&m  
這篇文章主要介紹了SpringBoot Admin升級boot等組件版本后無法監(jiān)控微服務(wù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

最近,安全中心報告了spring-boot-admin服務(wù)由于集成security版本過低導(dǎo)致了安全問題,Spring Security RegexRequestMatcher 認(rèn)證繞過漏洞(CVE-2022-22978),建議升級security版本,

  • 5.5.x 版本使用者建議升級至5.5.7及其以上
  • 5.6.x 版本使用者建議升級至5.6.4及其以上。

排查服務(wù)發(fā)現(xiàn)當(dāng)前服務(wù)集成security版本為5.3.9,于是決定動手升級。

一、升級版本

由于項目通過集成

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>

接入security,因此security版本由springboot統(tǒng)一管理。

工程中各依賴版本如下:

<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>

于是為了滿足上述升級需求,我們對該服務(wù)進(jìn)行版本調(diào)整。

<spring-boot.version>2.6.8</spring-boot.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>

springboot升級到2.4+之后,不再支持bootstrap版本,因此服務(wù)此時需要調(diào)整配置由bootstrap.yml轉(zhuǎn)變?yōu)閍pplication.yml。

spring:
  application:
    name: xxx
  cloud:
    nacos:
      config:
        username: xxx
        password: xxx
        server-addr: xxx:8848
        namespace: xxx
        group: DEFAULT_GROUP
        refresh-enabled: false
  config:
    import:
      - optional:nacos:xxx.properties?group=${spring.cloud.nacos.config.group}&refreshEnabled=false
      - optional:nacos:xxx.properties?group=${spring.cloud.nacos.config.group}&refreshEnabled=false

工程可以正常啟動,但訪問監(jiān)控頁面,監(jiān)控服務(wù)健康檢查處于DOWN狀態(tài),且無元數(shù)據(jù)。

二、排查原因

排查源碼發(fā)現(xiàn)spring-boot-admin-server-cloud源碼包中

InstanceDiscoveryListener通過監(jiān)聽event事件動態(tài)更新監(jiān)控服務(wù)狀態(tài)。

服務(wù)啟動后通過監(jiān)聽事件調(diào)用

InstanceDiscoveryListener.discover()方法。

protected void discover() {
		log.debug("Discovering new instances from DiscoveryClient");
		Flux.fromIterable(discoveryClient.getServices()).filter(this::shouldRegisterService)
				.flatMapIterable(discoveryClient::getInstances).filter(this::shouldRegisterInstanceBasedOnMetadata)
				.flatMap(this::registerInstance).collect(Collectors.toSet()).flatMap(this::removeStaleInstances)
				.subscribe((v) -> {
				}, (ex) -> log.error("Unexpected error.", ex));
	}

方法首先會從注冊中心獲取注冊服務(wù),之后屏蔽不需要監(jiān)控的服務(wù),再進(jìn)行bean轉(zhuǎn)換。

此處需要注意discoveryClient::getInstances方法,即bean轉(zhuǎn)換方法。

由于服務(wù)注冊中心為consul,因此getInstance會調(diào)用

ConsulDiscoveryClient.getInstances()。

 public List<ServiceInstance> getInstances(final String serviceId, final QueryParams queryParams) {
        List<ServiceInstance> instances = new ArrayList();
        this.addInstancesToList(instances, serviceId, queryParams);
        return instances;
    }

    private void addInstancesToList(List<ServiceInstance> instances, String serviceId, QueryParams queryParams) {
        Builder requestBuilder = HealthServicesRequest.newBuilder().setPassing(this.properties.isQueryPassing()).setQueryParams(queryParams).setToken(this.properties.getAclToken());
        String[] queryTags = this.properties.getQueryTagsForService(serviceId);
        if (queryTags != null) {
            requestBuilder.setTags(queryTags);
        }

        HealthServicesRequest request = requestBuilder.build();
        Response<List<HealthService>> services = this.client.getHealthServices(serviceId, request);
        Iterator var8 = ((List)services.getValue()).iterator();

        while(var8.hasNext()) {
            HealthService service = (HealthService)var8.next();
            instances.add(new ConsulServiceInstance(service, serviceId));
        }

    }

方法中真正的bean轉(zhuǎn)換在于new ConsulServiceInstance(service, serviceId)。

該構(gòu)造器方法如下:

   public ConsulServiceInstance(HealthService healthService, String serviceId) {
        this(healthService.getService().getId(), serviceId, ConsulServerUtils.findHost(healthService), healthService.getService().getPort(), getSecure(healthService), getMetadata(healthService), healthService.getService().getTags());
        this.healthService = healthService;
    }

可見metadata數(shù)據(jù)通過getMetadata()方法獲取。

    private static Map<String, String> getMetadata(HealthService healthService) {
        Map<String, String> metadata = healthService.getService().getMeta();
        if (metadata == null) {
            metadata = new LinkedHashMap();
        }

        return (Map)metadata;
    }

從代碼看出,metadata數(shù)據(jù)從service實例的meta屬性中獲取。而由于監(jiān)控服務(wù)統(tǒng)一注冊tag標(biāo)簽而非meta到注冊中心,因此此處數(shù)據(jù)獲取為空,從而導(dǎo)致spring-boot-admin 元數(shù)據(jù)及監(jiān)控路徑拼接異常,進(jìn)而服務(wù)監(jiān)控失敗,狀態(tài)DOWN。

那么為什么之前可以正常監(jiān)控,升級版本之后便監(jiān)控異常呢?

通過回退之前版本我們發(fā)現(xiàn),老版本中meta數(shù)據(jù)獲取方法并非當(dāng)前這樣。

private void addInstancesToList(List<ServiceInstance> instances, String serviceId, QueryParams queryParams) {
        Builder requestBuilder = HealthServicesRequest.newBuilder().setPassing(this.properties.isQueryPassing()).setQueryParams(queryParams).setToken(this.properties.getAclToken());
        String queryTag = this.properties.getQueryTagForService(serviceId);
        if (queryTag != null) {
            requestBuilder.setTag(queryTag);
        }

        HealthServicesRequest request = requestBuilder.build();
        Response<List<HealthService>> services = this.client.getHealthServices(serviceId, request);

        HealthService service;
        String host;
        Map metadata;
        boolean secure;
        for(Iterator var8 = ((List)services.getValue()).iterator(); var8.hasNext(); instances.add(new DefaultServiceInstance(service.getService().getId(), serviceId, host, service.getService().getPort(), secure, metadata))) {
            service = (HealthService)var8.next();
            host = ConsulServerUtils.findHost(service);
            metadata = ConsulServerUtils.getMetadata(service, this.properties.isTagsAsMetadata());
            secure = false;
            if (metadata != null && metadata.containsKey("secure")) {
                secure = Boolean.parseBoolean((String)metadata.get("secure"));
            }
        }

    }

老版本通過調(diào)用ConsulServerUtils.getMetadata(service, this.properties.isTagsAsMetadata());獲取meta數(shù)據(jù)。

    @Deprecated
    public static Map<String, String> getMetadata(HealthService healthService, boolean tagsAsMetadata) {
        return tagsAsMetadata ? getMetadata(healthService.getService().getTags()) : healthService.getService().getMeta();
    }

此版本中metadata通過tagsAsMetadata 屬性標(biāo)識判斷是否可從tags中獲取metadata,由于該屬性默認(rèn)為true,因此我們之前注冊到tags的屬性可以被admin標(biāo)記為metadata,從而參與到

DefaultServiceInstanceConverter.convert()實現(xiàn)對Registration對象的組裝。

 protected Mono<InstanceId> registerInstance(ServiceInstance instance) {
        try {
            Registration registration = this.converter.convert(instance).toBuilder().source("discovery").build();
            log.debug("Registering discovered instance {}", registration);
            return this.registry.register(registration);
        } catch (Exception var3) {
            log.error("Couldn't register instance for discovered instance ({})", this.toString(instance), var3);
            return Mono.empty();
        }
    }

此時,我們只需要讓監(jiān)控服務(wù)注冊meta到consul注冊中心即可。

根據(jù)spring-cloud-consul官方文檔Spring Cloud Consul, metadata使用實例如下(也可使用properties文件,自行轉(zhuǎn)換即可)

此處有特別說明:

參考DefaultServiceInstanceConverter所定義的key屬性,于是我們修改配置文件,再次重新啟動微服務(wù)。

此時,服務(wù)再次報錯。

OperationException{statusCode=400, statusMessage='Bad Request', statusContent='Invalid Service Meta: Couldn't load metadata pair ('management.context-path', '/xxx/actuator'): Key contains invalid characters'}

根據(jù)異常棧,我們服務(wù)該異常由調(diào)用consul服務(wù)端rpc之后response響應(yīng)體返回。

由于是遠(yuǎn)端服務(wù)返回,考慮版本兼容性問題,直接升級最高版本consul,升級之后發(fā)現(xiàn)異常仍然存在。

為了驗證該問題,我們切換注冊中心到nacos,發(fā)現(xiàn)meta注冊正常,監(jiān)控正常。

到此,該問題排查基本結(jié)束,定義為spring-boot-admin與spring-cloud-consul版本兼容性問題。

spring-cloud-consul在v3.0.0(不包含M1等版本)及之上,meta數(shù)據(jù)獲取不再兼容tags,因此使用該版本的cloud在于admin集成時,若監(jiān)控服務(wù)存在context-path或者自定義的健康檢查路徑等,由于admin定義meata屬性key均包含"."字符,因此大概率均會出現(xiàn)監(jiān)控異常問題(推測結(jié)論,未完整驗證所有版本)。

目前,已提issue到github上spring-boot-admin中,參見https://github.com/codecentric/spring-boot-admin/issues/2076,等待官方解答中。

***************************************

該問題目前已解決,根據(jù)版本匹配關(guān)系,spring-boot需升級到2.7.0版本才可,而非2.6.8。

spring-boot-admin在2.7.4版本對metadatda做了兼容處理。

且官方文檔也指出

同時,據(jù)回復(fù),consul端也在推進(jìn)處理此問題

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java如何獲取request中json數(shù)據(jù)

    java如何獲取request中json數(shù)據(jù)

    這篇文章主要給大家介紹了關(guān)于java如何獲取request中json數(shù)據(jù)的相關(guān)資料,文中通過代碼示例以及圖文將獲取的方法介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • Mybatis官方生成器的使用方式

    Mybatis官方生成器的使用方式

    本文詳細(xì)介紹了MyBatisGenerator(MBG)的使用方法,通過實際代碼示例展示了如何配置Maven插件來自動化生成MyBatis項目所需的實體類、Mapper接口和MapperXML文件,MBG通過配置文件和Maven插件,可以大大減少開發(fā)人員在進(jìn)行CRUD操作時的重復(fù)工作,提升開發(fā)效率和代碼一致性
    2025-01-01
  • Spring Boot 啟動注解過程分析

    Spring Boot 啟動注解過程分析

    這篇文章主要為大家介紹了Spring Boot 啟動注解過程示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Spring boot整合Mybatis實現(xiàn)級聯(lián)一對多CRUD操作的完整步驟

    Spring boot整合Mybatis實現(xiàn)級聯(lián)一對多CRUD操作的完整步驟

    這篇文章主要給大家介紹了關(guān)于Spring boot整合Mybatis實現(xiàn)級聯(lián)一對多CRUD操作的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • 解決resultMap映射數(shù)據(jù)錯誤的問題

    解決resultMap映射數(shù)據(jù)錯誤的問題

    這篇文章主要介紹了解決resultMap映射數(shù)據(jù)錯誤的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot在RequestBody中使用枚舉參數(shù)案例詳解

    SpringBoot在RequestBody中使用枚舉參數(shù)案例詳解

    這篇文章主要介紹了SpringBoot在RequestBody中使用枚舉參數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • 基于Java8實現(xiàn)提高Excel讀寫效率

    基于Java8實現(xiàn)提高Excel讀寫效率

    這篇文章主要介紹了基于Java8實現(xiàn)提高Excel讀寫效率,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • Spring整合Quartz分布式調(diào)度的示例代碼

    Spring整合Quartz分布式調(diào)度的示例代碼

    本篇文章主要介紹了Spring整合Quartz分布式調(diào)度的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • ShardingSphere解析SQL示例詳解

    ShardingSphere解析SQL示例詳解

    這篇文章主要為大家介紹了ShardingSphere解析SQL的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Java?超詳細(xì)講解類的定義方式和對象的實例化

    Java?超詳細(xì)講解類的定義方式和對象的實例化

    Java是一門純面向?qū)ο蟮恼Z言(Object?Oriented?Program,繼承OOP),在面對對象的世界里面,一切皆為對象。面向?qū)ο笫墙鉀Q問題的一種思想,主要依靠對象之間的交互完成一件事情
    2022-03-03

最新評論