最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

最近,安全中心報(bào)告了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,于是決定動手升級。

一、升級版本

由于項(xiàng)目通過集成

<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ù)此時(shí)需要調(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實(shí)例的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()實(shí)現(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();
        }
    }

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

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

此處有特別說明:

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

此時(shí),服務(wù)再次報(bào)錯(cuò)。

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)異常仍然存在。

為了驗(yà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集成時(shí),若監(jiān)控服務(wù)存在context-path或者自定義的健康檢查路徑等,由于admin定義meata屬性key均包含"."字符,因此大概率均會出現(xiàn)監(jiān)控異常問題(推測結(jié)論,未完整驗(yàn)證所有版本)。

目前,已提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做了兼容處理。

且官方文檔也指出

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

總結(jié)

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

相關(guān)文章

  • springmvc和js前端的數(shù)據(jù)傳遞和接收方式(兩種)

    springmvc和js前端的數(shù)據(jù)傳遞和接收方式(兩種)

    本文介紹了springmvc和js前端的數(shù)據(jù)傳遞和接收方式(兩種),詳細(xì)的介紹了兩種方式,一種是json格式傳遞,另一種是Map傳遞,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-12-12
  • java中原碼、反碼與補(bǔ)碼的問題分析

    java中原碼、反碼與補(bǔ)碼的問題分析

    本篇文章介紹了,在java中原碼、反碼與補(bǔ)碼的問題分析。需要的朋友參考下
    2013-04-04
  • SpringBoot監(jiān)控Tomcat活動線程數(shù)來判斷是否完成請求處理方式

    SpringBoot監(jiān)控Tomcat活動線程數(shù)來判斷是否完成請求處理方式

    這篇文章主要介紹了SpringBoot監(jiān)控Tomcat活動線程數(shù)來判斷是否完成請求處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • SpringBoot中讀取jar包中的resources目錄下的文件的三種方式

    SpringBoot中讀取jar包中的resources目錄下的文件的三種方式

    這篇文章給大家總結(jié)了SpringBoot讀取 jar 包中的 resources 目錄下的文件的三種方式,文中有詳細(xì)的代碼示例供大家參考,,需要的朋友可以參考下
    2023-06-06
  • 基于Mybatis映射的一點(diǎn)心得(分享)

    基于Mybatis映射的一點(diǎn)心得(分享)

    下面小編就為大家?guī)硪黄贛ybatis映射的一點(diǎn)心得(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • Jar包沖突問題原理及解決方案

    Jar包沖突問題原理及解決方案

    這篇文章主要介紹了Jar包沖突問題原理及解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Core Java 簡單談?wù)凥ashSet(推薦)

    Core Java 簡單談?wù)凥ashSet(推薦)

    下面小編就為大家?guī)硪黄狢ore Java 簡單談?wù)凥ashSet(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • spring聲明式事務(wù)@Transactional開發(fā)常犯的幾個(gè)錯(cuò)誤及最新解決方案

    spring聲明式事務(wù)@Transactional開發(fā)常犯的幾個(gè)錯(cuò)誤及最新解決方案

    使用聲明式事務(wù)@Transactional進(jìn)行事務(wù)一致性的管理,在開發(fā)過程中,發(fā)現(xiàn)很多開發(fā)同學(xué)都用錯(cuò)了spring聲明式事務(wù)@Transactional或使用不規(guī)范,導(dǎo)致出現(xiàn)各種事務(wù)問題,這篇文章主要介紹了spring聲明式事務(wù)@Transactional開發(fā)常犯的幾個(gè)錯(cuò)誤及解決辦法,需要的朋友可以參考下
    2024-02-02
  • Java中BigDecimal,DateFormatter?和迭代器的"陷阱"

    Java中BigDecimal,DateFormatter?和迭代器的"陷阱"

    這篇文章主要介紹了Java中BigDecimal,DateFormatter?和迭代器的"陷阱",文章圍繞主題展開詳細(xì)的內(nèi)容介紹,感興趣的小伙伴可以參考一下
    2022-06-06
  • IDEA自動生成注釋模板的配置教程

    IDEA自動生成注釋模板的配置教程

    本文介紹了如何在IntelliJIDEA中配置類和方法的注釋模板,包括自動生成項(xiàng)目名稱、包名、日期和時(shí)間等內(nèi)容,以及如何定制參數(shù)和返回值的注釋格式,需要的朋友可以參考下
    2025-04-04

最新評論

万荣县| 微博| 凤山县| 福州市| 博客| 濮阳市| 肃宁县| 天等县| 桓仁| 临朐县| 水富县| 沧州市| 金乡县| 垫江县| 靖远县| 新绛县| 舒兰市| 潢川县| 贵德县| 台湾省| 托克托县| 修武县| 明溪县| 常山县| 瑞昌市| 射阳县| 诸暨市| 肇州县| 宝应县| 横峰县| 三明市| 太原市| 娱乐| 陆良县| 宜宾市| 沅江市| 开封市| 南昌县| 东丰县| 太康县| 江川县|