微服务 分布式配置中心Apollo详解

news2024/12/30 3:08:32

微服务 分布式配置中心Apollo详解

  • 1. 配置中心概述
    • 1.1 配置中心简介
    • 1.2 配置中心特点
    • 1.3 配置中心对比
  • 2. Apollo概述
    • 2.1 Apollo简介
    • 2.2 Apollo特点
  • 3. Apollo设计实现
    • 3.1 基础模型
    • 3.2 架构设计
    • 3.3 Why Eureka
    • 3.4 模块说明
  • 4. Apollo安装部署
    • 4.1 部署说明
    • 4.2 环境准备
    • 3.3 下载安装包
    • 4.4 创建数据库
    • 4.5 修改配置文件
    • 4.6 启动应用程序
    • 4.7 使用配置中心
  • 5. Apollo集成SpringBoot
    • 5.1 使用说明
    • 5.2 开发验证
    • 5.2 集成问题
    • 5.3 灰度测试
    • 5.4 热更新问题
  • 6. Apollo问题总结
    • 6.1 Apollo FAQ
    • 6.2 Apollo性能测试报告

1. 配置中心概述

1.1 配置中心简介

配置就是应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数据库连接参数、启动参数等。常见的配置properties,yml,xml等。

先说为什么需要配置中心,传统的配置有什么问题?
没有配置也可以在代码写死,为什么需要配置文件,其实这个问题就是配置文件的优点了,比如,统一管理配置信息,灵活调整,方便扩展。
分布式微服务的出现,导致不同模块领域划分为独立应用,每个独立应用为了保持高可用搭建为集群部署,所以一个产品线对应几十个应用,每个应用对应上百台机器,按照传统方式配置文件,那每次修改配置都要修改上百台应用的配置,可维护性,扩展性极低。分布式配置中心是独立于每一个应用服务的单独组件,统一对外提供配置服务,便于维护扩展管理。

总结一句话:配置中心就是一种统一管理各种应用配置的基础服务组件。

1.2 配置中心特点

1.配置是独立于程序的只读变量
配置首先是独立于程序的,同一份程序在不同的配置下会有不同的行为。其次,配置对于程序是只读的,程序通过读取配置来改变自己的行为,但是程序不应该去改变配置。

2.配置伴随应用的整个生命周期
配置贯穿于应用的整个生命周期,应用在启动时通过读取配置来初始化,在运行时根据配置调整行为。比如:启动时需要读取服务的端口号、系统在运行过程中需要读取定时策略执行定时任务等。

3.配置可以有多种加载方式
常见的有程序内部硬编码,配置文件,环境变量,启动参数,基于数据库等。

4 配置需要治理
权限控制:由于配置能改变程序的行为,不正确的配置甚至能引起灾难,所以对配置的修改必须有比较完善的权限控制。不同环境、集群配置管理:同一份程序在不同的环境(开发,测试,生产)、不同的集群(如不同的数据中心)经常需要有不同的配置,所以需要有完善的环境、集群配置管理。

1.3 配置中心对比

在这里插入图片描述总的来看,Apollo和Nacos相对于Spring Cloud Config的生态支持更广,在配置管理流程上做的更好。Apollo相对于Nacos在配置管理做的更加全面,Nacos则使用起来相对比较简洁,在对性能要求比较高的大规模场景更适合。但对于一个开源项目的选型,项目上的人力投入(迭代进度、文档的完整性)、社区的活跃度(issue的数量和解决速度、Contributor数量、社群的交流频次等),这些因素也比较关键,考虑到Nacos开源时间不长和社区活跃度,所以从目前来看Apollo应该是最合适的配置中心选型。

2. Apollo概述

2.1 Apollo简介

Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。

Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。
.Net客户端不依赖任何框架,能够运行于所有.Net运行时环境。

更多产品介绍参见Apollo配置中心介绍。
本地快速部署请参见Quick Start

演示环境(Demo):
http://81.68.181.139
账号/密码:apollo/admin

apollo gitee :https://gitee.com/apolloconfig
apollo github:https://github.com/apolloconfig
apollo 官方地址:https://www.apolloconfig.com/#/zh/README

2.2 Apollo特点

1.统一管理不同环境、不同集群的配置

  • Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。
  • 同一份代码部署在不同的集群,可以有不同的配置,比如zk的地址等
  • 通过命名空间(namespace)可以很方便的支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
  • 配置界面支持多语言(中文,English)

2.配置修改实时生效(热发布)
用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序。

3.版本发布管理
所有的配置发布都有版本概念,从而可以方便的支持配置的回滚。

4.灰度发布
支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例。

5.权限管理、发布审核、操作审计

  • 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。
  • 所有的操作都有审计日志,可以方便的追踪问题。

6.客户端配置信息监控
可以方便的看到配置在被哪些实例使用

7.提供Java和.Net原生客户端

  • 提供了Java和.Net的原生客户端,方便应用集成
  • 支持Spring Placeholder,Annotation和Spring Boot的ConfigurationProperties,方便应用使用(需要Spring 3.1.1+)
  • 同时提供了Http接口,非Java和.Net应用也可以方便的使用

8.提供开放平台API

  • Apollo自身提供了比较完善的统一配置管理界面,支持多环境、多数据中心配置管理、权限、流程治理等特性。
  • 不过Apollo出于通用性考虑,对配置的修改不会做过多限制,只要符合基本的格式就能够保存。
  • 在我们的调研中发现,对于有些使用方,它们的配置可能会有比较复杂的格式,如xml, json,需要对格式做校验。
  • 还有一些使用方如DAL,不仅有特定的格式,而且对输入的值也需要进行校验后方可保存,如检查数据库、用户名和密码是否匹配。
  • 对于这类应用,Apollo支持应用方通过开放接口在Apollo进行配置的修改和发布,并且具备完善的授权和权限控制

8.部署简单

  • 配置中心作为基础服务,可用性要求非常高,这就要求Apollo对外部依赖尽可能地少
  • 目前唯一的外部依赖是MySQL,所以部署非常简单,只要安装好Java和MySQL就可以让Apollo跑起来
  • Apollo还提供了打包脚本,一键就可以生成所有需要的安装包,并且支持自定义运行时参数

3. Apollo设计实现

3.1 基础模型

如下即是Apollo的基础模型:
1.用户在配置中心对配置进行修改并发布
2.配置中心通知Apollo客户端有配置更新
3.Apollo客户端从配置中心拉取最新的配置、更新本地配置并通知到应用

3.2 架构设计

下图是Apollo的作者宋顺给出的架构图概览,详细说明可以参考Apollo配置中心架构剖析。
在这里插入图片描述可能从架构图并不能很清晰的明白整个架构设计,业务流转,下边给出一些说明结合上图理解相对容易些。
1.Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端。
2.Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)。
3.Config Service和Admin Service都是多实例、无状态部署,所以需要将自己注册到Eureka中并保持心跳。
4.在Eureka之上我们架了一层Meta Server用于封装Eureka的服务发现接口。
5.Client通过域名访问Meta Server获取Config Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Client侧会做load balance、错误重试。
6.Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Portal侧会做load balance、错误重试。
7.为了简化部署,我们实际上会把Config Service、Eureka和Meta Server三个逻辑角色部署在同一个JVM进程中。

3.3 Why Eureka

关于为什么采用eureka作者给了三点原因
1.它提供了完整的Service Registry和Service Discovery实现。
2.和SpringCloud无缝集成。
3.Open Source,对也就是开源。

3.4 模块说明

各个模块说明详见官网说明。

4. Apollo安装部署

4.1 部署说明

为了让大家更快的上手了解Apollo配置中心,我们这里准备了一个Quick Start,能够在几分钟内在本地环境部署、启动Apollo配置中心。

考虑到Docker的便捷性,我们还提供了Quick Start的Docker版本,如果你对Docker比较熟悉的话,可以参考Apollo Quick Start Docker部署通过Docker快速部署Apollo。

不过这里需要注意的是,Quick Start只针对本地测试使用,如果要部署到生产环境,还请另行参考分布式部署指南。

4.2 环境准备

1.Java环境
Apollo服务端:1.8+
Apollo客户端:1.8+
在配置好后,可以通过如下命令检查:

java -version

正常输出:

java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)

注意事项:
如需运行在 Java 1.7 运行时环境,请使用 1.x 版本的 apollo 客户端,如 1.9.1
Windows用户请确保JAVA_HOME环境变量已经设置。

2.MySQL
版本要求:5.6.5+
Apollo的表结构对timestamp使用了多个default声明,所以需要5.6.5以上版本。
连接上MySQL后,可以通过如下命令检查:

SHOW VARIABLES WHERE Variable_name = 'version';

正常输出

Variable_nameValue
version5.7.11

3.3 下载安装包

我们准备好了一个Quick Start安装包,大家只需要下载到本地,就可以直接使用,免去了编译、打包过程。
安装包共50M,如果访问github网速不给力的话,可以从百度网盘下载。

从GitHub下载
checkout或下载apollo-build-scripts项目
由于Quick Start项目比较大,所以放在了另外的repository,请注意项目地址
https://github.com/nobodyiam/apollo-build-scripts

从百度网盘下载
通过网盘链接下载,提取码: 9wwe
下载到本地后,在本地解压apollo-quick-start.zip

为啥安装包要58M这么大?
因为这是一个可以自启动的jar包,里面包含了所有依赖jar包以及一个内置的tomcat容器
注意如果是源码需要手动打包。

4.4 创建数据库

找到解压apollo-quick-start.zip后的文件下的sql文件夹,包含两个sql脚本apolloconfigdb.sql 与 apolloportaldb.sql。
Apollo服务端共需要两个数据库:ApolloPortalDB和ApolloConfigDB,我们把数据库、表的创建和样例数据都分别准备了sql文件,只需要导入数据库即可。
注意:如果你本地已经创建过Apollo数据库,请注意备份数据。我们准备的sql文件会清空Apollo相关的表。

通过Navicat客户端直接导入这两个sql文件即可,选择数据库右键,运行sql文件,选择sql文件执行,然后刷新,可以看到两个新的数据库apolloconfigdb与apolloportaldb。
或者通过命令执行也可,创建ApolloPortalDB与ApolloConfigDB,并且验证。

source /your_local_path/sql/apolloportaldb.sql
select `Id`, `AppId`, `Name` from ApolloPortalDB.App;

source /your_local_path/sql/apolloconfigdb.sql
select `NamespaceId`, `Key`, `Value`, `Comment` from ApolloConfigDB.Item;

4.5 修改配置文件

Apollo服务端需要知道如何连接到你前面创建的数据库,所以需要编辑demo.sh,修改ApolloPortalDB和ApolloConfigDB相关的数据库连接串信息。
注意:填入的用户需要具备对ApolloPortalDB和ApolloConfigDB数据的读写权限。

# apollo config db info
apollo_config_db_url="jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai"
apollo_config_db_username=${APOLLO_CONFIG_DB_USERNAME:-root}
apollo_config_db_password=${APOLLO_CONFIG_DB_PASSWORD:-123456}

# apollo portal db info
apollo_portal_db_url="jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai"
apollo_portal_db_username=${APOLLO_PORTAL_DB_USERNAME:-root}
apollo_portal_db_password=${APOLLO_PORTAL_DB_PASSWORD:-123456}

4.6 启动应用程序

启动应用程序的时候需要注意,如果是Windows环境是不能使用cmd窗口执行demo.sh脚本的,一般开发安装的都有gitbash,可以通过Git Bash Here打开命令窗口执行启动命令,如果没有安装gitbash则通过Java -jar的方式单独启动。
Quick Start脚本会在本地启动3个服务,分别使用8070, 8080, 8090端口,请确保这3个端口当前没有被使用。

1.首先检查端口是否占用
在Linux/Mac下,可以通过如下命令检查:

lsof -i:8080

windows端口查看端口占用情况
输入【netstat -ano】命令,回车,就可看到Windows系统当前所有端口的占用情况
输入【netstat -aon|findstr “端口号”】命令,回车,就可以看到指定端口的占用情况
输入【tasklist|findstr “被占用端口对应的 PID”】命令,就可以查看是哪个进程或者程序占用了相应的端口。
输入【taskkill /t /f /pid pid号】 命令,结束端口占用的进程。

netstat -ano
netstat -aon|findstr "8080"
tasklist|findstr "151520"
taskkill /t /f /pid 151520

2.执行启动脚本
Windows打开gitbash,Linux打开命令窗口。执行demo.sh脚本。

./demo.sh start

当看到如下输出,则说明启动成功

Think@LAPTOP-DIDC0OGA MINGW64 /c/software/apollo-quick-start-2.0.1
$ ./demo.sh start
Windows new JAVA_HOME is: /c/software/Java/JDK18~1.0_1
==== starting service ====
Service logging file is ./service/apollo-service.log
Started [1589]
Waiting for config service startup...
Config service started. You may visit http://localhost:8080 for service status now!
Waiting for admin service startup.
Admin service started
==== starting portal ====
Portal logging file is ./portal/apollo-portal.log
Started [1634]
Waiting for portal startup...
Portal started. You can visit http://localhost:8070 now!

4.7 使用配置中心

1.查看样例配置
打开配置中心页面:http://localhost:8070
Quick Start集成了Spring Security简单认证,更多信息可以参考Portal 实现用户登录功能

2.登录客户端
输入用户名apollo,密码admin后登录

3.首页案例
点击SampleApp进入配置界面,可以看到当前有一个配置timeout=100 配置界面
如果提示系统出错,请重试或联系系统负责人,请稍后几秒钟重试一下,因为通过Eureka注册的服务有一个刷新的延时。

4.可以通过配置中心页面进行简单的操作
创建新的应用,简单配置,开启密匙管理。
在这里插入图片描述5.运行客户端程序进行验证
我们准备了一个简单的Demo客户端来演示从Apollo配置中心获取配置。程序很简单,就是用户输入一个key的名字,程序会输出这个key对应的值。如果没找到这个key,则输出undefined。同时,客户端还会监听配置变化事件,一旦有变化就会输出变化的配置信息。
运行./demo.sh client启动Demo客户端,忽略前面的调试信息,可以看到如下提示:

Apollo Config Demo. Please input key to get the value. Input quit to exit.
>timeout
> [SimpleApolloConfigDemo] Loading key : timeout with value: 100

5. Apollo集成SpringBoot

5.1 使用说明

详情参考 Java客户端使用指南:https://www.apolloconfig.com/#/zh/usage/java-sdk-user-guide

5.2 开发验证

1.项目结构

│  apollo-platform
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─zrj
│  │  │          └─apollo
│  │  │              └─platform
│  │  │                  │  ApolloPlatformApplication.java
│  │  │                  │  
│  │  │                  ├─config
│  │  │                  │      ApolloConfig.java
│  │  │                  │      ApolloConfigBean.java
│  │  │                  │      ApolloConfigListener.java
│  │  │                  │      
│  │  │                  └─controller
│  │  │                          ApolloController.java
│  │  │                          
│  │  └─resources
│  │          application.properties
│  │          
└─pom.xml   

2.maven依赖

<!--apollo-client-config-data已经依赖apollo-client, 所以只需要添加这一个依赖即可, 无需再添加apollo-client的依赖-->
<dependency>
	<groupId>com.ctrip.framework.apollo</groupId>
	<artifactId>apollo-client-config-data</artifactId>
	<version>2.0.1</version>
</dependency>

2.配置文件
application.properties

# 端口
server.port=8088

# apollo config
app.id=apollo-platform
apollo.meta=127.0.0.1:8080
apollo.access-key.secret=0ba77e739c4c4becbb9a4b44f8820d73

# will inject 'application' namespace in bootstrap phase
apollo.bootstrap.enabled = true
# will inject 'application', 'FX.apollo' and 'application.yml' namespaces in bootstrap phase
#apollo.bootstrap.namespaces = application,FX.apollo,application.yml
apollo.bootstrap.namespaces = application

3.代码实现
ApolloConfigBean

package com.zrj.apollo.platform.config;

import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * ApolloConfigBean
 * <p>
 * Apollo自动加载热更新问题
 * 1、Apollo默认会对Value和ApolloJsonValue注解的数据进行热更新。
 * 2、其他数据需要通过ApplicationContext.publishEven刷新到应用中。
 * 3、当多个namespace时,优先使用先加载的数据,如namespaces: zone-dev,application,使用zone-dev中数据。
 * 方案一:通过ApolloConfigChangeListener监听指定namespace,无法满足根据分区配置namespace。
 * 方案二:通过Config.addChangeListener监听指定namespace,动态监听不同的namespace配置。
 *
 * @author zrj
 * @since 2023/1/6
 **/
@Data
@Component
public class ApolloConfigBean {
    @Value("${timeout:100}")
    private int timeout;

    @Value("${batch:100}")
    private int batch;

    @Value("${run:stop}")
    private String run;

    @Value("${say:hi}")
    private String say;

    /**
     * ApolloJsonValue annotated on fields example, the default value is specified as empty list - []
     * <br /> jsonBeanProperty=[{"someString":"hello","someInt":100},{"someString":"world!","someInt":200}]
     */
    @ApolloJsonValue("${jsonBeanProperty:[]}")
    private List<JsonBean> jsonBeans;

    private static class JsonBean {

        private String someString;
        private int someInt;

        @Override
        public String toString() {
            return "JsonBean{" +
                    "someString='" + someString + '\'' +
                    ", someInt=" + someInt +
                    '}';
        }
    }
}

ApolloConfigListener

package com.zrj.apollo.platform.config;

import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.spring.events.ApolloConfigChangeEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;

import java.util.Set;

/**
 * apollo监听器
 *
 * @author zrj
 * @since 2023/1/6
 **/
public class ApolloConfigListener implements ApplicationListener<ApolloConfigChangeEvent> {
    private static final Logger logger = LoggerFactory.getLogger(ApolloConfigListener.class);

    @Override
    public void onApplicationEvent(ApolloConfigChangeEvent apolloConfigChangeEvent) {
        String namespace = apolloConfigChangeEvent.getConfigChangeEvent().getNamespace();
        logger.info("On ApplicationEvent ApolloConfigChangeEvent received, namespace: {}", namespace);

        Set<String> changedKeys = apolloConfigChangeEvent.getConfigChangeEvent().changedKeys();
        for (String key : changedKeys) {
            ConfigChange configChange = apolloConfigChangeEvent.getConfigChangeEvent().getChange(key);
            logger.info("configChange received {}", configChange);
        }
    }
}

ApolloConfig

package com.zrj.apollo.platform.config;

import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * apollo配置
 *
 * @author zrj
 * @since 2023/1/6
 **/
@Configuration
@EnableApolloConfig
public class ApolloConfig {

    @Bean
    public ApplicationListener testApplicationListener() {
        return new ApolloConfigListener();
    }
}

ApolloController

package com.zrj.apollo.platform.controller;

import com.zrj.apollo.platform.config.ApolloConfigBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * apollo
 *
 * @author zrj
 * @since 2023/1/6
 **/
@RestController
@RequestMapping("/apollo")
public class ApolloController {
    private static final Logger logger = LoggerFactory.getLogger(ApolloController.class);

    private final ApolloConfigBean apolloConfigBean;

    public ApolloController(ApolloConfigBean apolloConfigBean) {
        this.apolloConfigBean = apolloConfigBean;
    }

    @GetMapping("/get")
    public String getApolloConfig() {
        String helloTime = "【ApolloController】ApolloConfigBean:" + apolloConfigBean.toString();
        logger.info(helloTime);
        return helloTime;
    }


}

ApolloPlatformApplication

package com.zrj.apollo.platform;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * apollo
 * 配置系统启动参数,idea,VM options:-Dapollo.meta=http://127.0.0.1:8080 -Denv=dev
 * 
 * @author zrj
 * @since 20230106
 */
@SpringBootApplication
public class ApolloPlatformApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApolloPlatformApplication.class, args);
    }

}

4.配置启动参数
配置系统启动参数,idea,VM options:-Dapollo.meta=http://127.0.0.1:8080 -Denv=dev

5.测试验证
访问地址:http://localhost:8088/apollo/get
访问结果:
【ApolloController】ApolloConfigBean:ApolloConfigBean(timeout=600, batch=900, run=start, jsonBeans=[JsonBean{someString=‘hello’, someInt=100}, JsonBean{someString=‘world!’, someInt=200}])

5.2 集成问题

启动的时候遇到了两个问题,官方文档上也没具体说明,当然也可能是我忽略了,主要是启动参数必须配置,官方案例中也没用配置启动参数拉去配置是没有问题,自己集成的必须配置启动参数才能拉去配置,目前解决方案如下。

启动问题
日志循环打印拉取失败信息,RemoteConfigLongPollService: Long polling failed, will retry in 1 seconds. appId: apollo-platform, cluster: default, namespaces: application, long polling url: null, reason: Get config services failed from 127.0.0.1:8080/services/config?appId=apollo-platform&ip=192.168.3.24
解决方案
这个是未对apollo.meta 属性进行正确赋值,必须是eureka的地址和端口,就是你输入这个url+端口的时候跳转到的是eureka这个界面,而非apollo管理页面,否则必定报错。
配置系统启动参数,idea,VM options:-Dapollo.meta=http://127.0.0.1:8080 -Denv=dev

权限问题
Cause: Server returned HTTP response code: 401 for URL
解决方案
apollo开启了密匙,需要配置正确的密匙。
apollo管理页面:管理密钥。配置文件:apollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719

5.3 灰度测试

apollo支持灰度发布,可以通过配置灰度版本,灰度规则,根据不同的ip或者标签拉取不同的配置。只有符合灰度规则的机器才能拉取灰度配置。

1.配置灰度
灰度-添加灰度配置-添加灰度规则
在这里插入图片描述在这里插入图片描述
2.灰度验证
访问地址:http://localhost:8088/apollo/get
访问结果:
【ApolloController】ApolloConfigBean:ApolloConfigBean(timeout=600, batch=900, run=start, say=hello, jsonBeans=[JsonBean{someString=‘hello’, someInt=100}, JsonBean{someString=‘world!’, someInt=200}])

5.4 热更新问题

Apollo自动加载热更新问题
1、Apollo默认会对Value和ApolloJsonValue注解的数据进行热更新。
2、其他数据需要通过ApplicationContext.publishEven刷新到应用中。
3、当多个namespace时,优先使用先加载的数据,如namespaces: zone-dev,application,使用zone-dev中数据。
方案一:通过ApolloConfigChangeListener监听指定namespace,无法满足根据分区配置namespace。
方案二:通过Config.addChangeListener监听指定namespace,动态监听不同的namespace配置。

6. Apollo问题总结

6.1 Apollo FAQ

Apollo常见问题:https://www.apolloconfig.com/#/zh/faq/faq

Apollo部署&开发问题:https://www.apolloconfig.com/#/zh/faq/common-issues-in-deployment-and-development-phase

6.2 Apollo性能测试报告

Apollo性能测试报告:https://www.apolloconfig.com/#/zh/misc/apollo-benchmark

1.环境配置
机器配置:4C12G
JVM参数:1.8.0_60
Apollo版本:0.9。0
单台机器客户端连接数:5600
集群客户端连接数:10W+

2.性能指标

获取配置Http接口响应时间
QPS: 160
平均响应时间: 0.1ms
95线响应时间: 0.3ms
999线响应时间: 2.5ms

Config Server GC情况
YGC: 平均2Min一次,一次耗时300ms
OGC: 平均1H一次,一次耗时380ms

CPU指标
LoadAverage:0.5
System CPU利用率:6%
Process CPU利用率:8%

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/146727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript奇技淫巧:隐形字符

JavaScript奇技淫巧&#xff1a;隐形字符 本文&#xff0c;分享一种奇特的JS编程技巧&#xff0c;功能是&#xff1a;可以使字符串“隐形”、不可见&#xff01; 效果展示 如下图所示&#xff0c;一个字符串经物别的操作之后&#xff0c;其长度有621字节&#xff0c;但内容却…

[ 数据结构 ] 查找算法--------递归实现

0 前言 查找算法有4种: 线性查找 二分查找/折半查找 插值查找 斐波那契查找 1 线性查找 思路:线性遍历数组元素,与目标值比较,相同则返回下标 /**** param arr 给定数组* param value 目标元素值* return 返回目标元素的下标,没找到返回-1*/public static int search(…

ora-39083/01917报错

报错信息&#xff1a; Import: Release 11.2.0.4.0 - Production on Wed Dec 7 17:59:59 2022 Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production …

1、Javaweb_HTMLtable布局

web概念概述 * JavaWeb&#xff1a; * 使用Java语言开发基于互联网的项目 * 软件架构&#xff1a; 1. C/S: Client/Server 客户端/服务器端 * 在用户本地有一个客户端程序&#xff0c;在远程有一个服务器端程序 * 如&#xff1a;QQ&#xff0c;迅雷.…

Linux环境下安装 java / javac

目录 1、检查虚拟机或者服务器的位数 2、下载 jdk 3、解压jdk 4、添加全局环境变量 1、检查虚拟机或者服务器的位数 安装 java / javac 其实就是下载合适版本的 jdk&#xff0c;我们需要先确认虚拟机或者服务器的主机信息&#xff0c;来下载合适版本的 jdk。 输入 uname …

maven环境变量配置(超详细!)

下载地址&#xff1a; 官网地址 建议不要下载在C盘&#xff01;&#xff01; 配置过程 1.解压下载好的压缩包 2.此电脑–右键–属性–高级系统设置–环境变量 3.新建一个系统变量&#xff08;点击系统变量的新建&#xff09; 变量名&#xff1a;MAVEN_HOME 变量值&#x…

Python深度学习基础(八)——线性回归

线性回归引言损失函数解析解公式代码实例梯度下降理论随机梯度下降的手动实现代码torch中的随机梯度下降引言 我们生活中可能会遇到形如 yw1x1w2x2w3x3byw_1x_1w_2x_2w_3x_3byw1​x1​w2​x2​w3​x3​b 的问题&#xff0c;其中有y为输出&#xff0c;x为输入&#xff0c;w为权…

Java设计模式中工厂模式是啥?静态工厂、简单工厂与抽象工厂,工厂方法模式又是啥,怎么用,

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 4.3 工厂模式 4.3.1 背景 若创建对象时直接new对象&#xff0c;则会使对象耦合严重&#xff0c;更换对象则很复杂 4.3.2 简单工厂 4.3.3 特点 不是一种设计模…

c语言 文件处理2 程序环境和预处理

对比函数 sprintf&#xff08;把一个格式化数据转化为字符串&#xff09; sscanf &#xff08;从一个字符串中读一个格式化数据&#xff09; struct S {char arr[10];int age;float f; };int main() {struct S s { "hello", 20, 5.5f };//把这个转化为一个字符串s…

idea调试unity里面的lua代码

前言 本人一名java后端开发&#xff0c;看到前端同事调试lua代码无脑print&#xff0c;甚为鄙视&#xff0c;百度加实操写一份调试unity的lua脚本文档 操作 1.安装lua lua官网下载页面 最终下载页面 2.idea安装插件 emmylua 3.idea打开unity的lua脚本 idea->file->op…

【面试题】面试如何正确的介绍项目经验

大厂面试题分享 面试题库前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库1、在面试前准备项目描述&#xff0c;别害怕&#xff0c;因为面试官什么都不知道面试官是人&#xff0c;不是神&#xff0c;拿到你的简历的时候…

ospf双向重发布,LSA优化综合

目录实验分析ip地址划分写公网缺省路由区域0公网MGRE搭建各个区域ospf的宣告改变ospf接口工作方式和更改接口优先级ospf多进程及双向重发布减少LSA的更新量1&#xff0c;减少特殊区域的LSA更新量2&#xff0c;骨干区域的优化域间汇总域外汇总防环nat的设置实验分析 如图实际的…

VS Code 为 Clang for MSVC 配置 cmake cmake tools

介绍 在windows平台上&#xff0c;由于平台API差异过大&#xff0c;一般为linux设计的项目&#xff08;POSIX兼容&#xff09;无法通过MSVC的编译&#xff0c;而是会报非常多的头文件错误。如果要修改&#xff0c;工程量将巨大。Windows平台上&#xff0c;主要有两个类POSIX兼容…

【JavaScript】事件--总结

千锋 1.Event 对象 代表事件的状态&#xff0c;比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。 div{width: 200px;height: 200px;background-color: yellow;} </style> <body><input type"text" id"username"&…

JavaScript 事件

文章目录JavaScript 事件HTML 事件常见的HTML事件JavaScript 可以做什么?JavaScript 事件 HTML 事件是发生在 HTML 元素上的事情。 当在 HTML 页面中使用 JavaScript 时&#xff0c; JavaScript 可以触发这些事件。 HTML 事件 HTML 事件可以是浏览器行为&#xff0c;也可以是…

babel做兼容处理 到底怎么使用?

1.背景 日常项目开发中总是避免不了对低版本浏览器做一些兼容处理&#xff0c;最常见的手段就是结合编译工具使用babel来处理一些语法的兼容&#xff0c;但是每次使用的时候其实Babel的配置和使用到的相关库总是云里雾里&#xff0c;网上的各种推荐方案眼花缭乱不知道到底应该…

自定义DotNetCore 项目模板

在进行代码开发时候&#xff0c;各自的团队或者公司都会有服务自己要求的项目代码模板&#xff0c;再创建新的项目时&#xff0c;都需要按照模板规范进行定义&#xff0c;NET支持自定义项目模板&#xff0c;这样在进行项目创建时就会高效很多。 官方参考文档&#xff1a;dotne…

软测复习01:软件测试概述

文章目录软件测试的目的软件测试的定义软件测试与软件开发软件测试发展软件测试的目的 基于不同的立场&#xff0c;存在着两种完全不同的测试目的 从用户的角度出发&#xff0c;希望通过软件测试暴露软件中隐藏的错误和缺陷&#xff0c;以考虑是否可接受该产品。从软件开发者的…

Java当中的定时器

目录 一、什么是定时器 二、Java当中的定时器 ①schedule()方法&#xff1a; ②TimerTask ​编辑 ③delay 三、实现一个定时器 前提条件: 代码实现: ①确定一个“任务”&#xff08;MyTask)的描述&#xff1a; ②schedule方法&#xff1a; ③需要一个计时器 属性…

MAT-内存泄漏工具使用

目录 一、MAT简介 1.1 MAT介绍 1.2 MAT工具的下载安装 二、使用MAT基本流程 2.1 获取HPROF文件 2.2 MAT主界面介绍 2.3 MAT中的概念介绍 2.3.1 Shallow heap 2.3.2 Retained Heap 2.3.3 GC Root 2.4 MAT中的一些常用的视图 2.4.1 Thread OvewView 2.4.2 Group 2.…