分布式配置中心Apollo


1,什么是分布式配置中心

項目中配置文件比較繁雜,而且不同環境的不同配置修改相對頻繁,每次發布都需要對應修改配置,如果配置出現錯誤,需要重新打包發布,時間成本較高,因此需要做統一的分布式注冊中心,能做到自動更新配置文件信息,解決以上問題

常用分布式配置中心框架

Disconf(依賴於zookpeer)、Zookpeer()、diamond、攜程(阿波羅)、Redis、xxl-conf

Zookpeer保證配置文件信息實時更新 (事件通知)

大型互聯網公司自己內部都有自己獨立分布式配置中心
獨立RPC、獨立分布式各種解決方案
注冊中心解決 rpc服務治理
分布式配置中心 解決分布式配置文件管理

Apollo阿波羅簡介

 Apollo(阿波羅)是攜程框架部門研發的分布式配置中心,能夠集中化管理應用不同環境、不同集群的配置,配置修改后能夠實時推送到應用端,並且具備規范的權限、流程治理等特性,適用於微服務配置管理場景。

Apollo阿波羅特點

用戶在Apollo修改完配置並發布后,客戶端能實時(1秒)接收到最新的配置,並通知到應用程序。

統一管理不同環境、不同集群的配置

 所有的配置發布都有版本概念,從而可以方便的支持配置的回滾。

配置修改實時生效(熱發布)

用戶在Apollo修改完配置並發布后,客戶端能實時(1秒)接收到最新的配置,並通知到應用程序

版本發布管理

所有的配置發布都有版本概念,從而可以方便的支持配置的回滾

灰度發布

支持配置的灰度發布,比如點了發布后,只對部分應用實例生效,等觀察一段時間沒問題后再推給所有應用實例。

權限管理、發布審核、操作審計

應用和配置的管理都有完善的權限管理機制,對配置的管理還分為了編輯和發布兩個環節,從而減少人為的錯誤。

所有的操作都有審計日志,可以方便的追蹤問題。

客戶端配置信息監控

可以方便的看到配置在被哪些實例使用

提供Java.Net原生客戶端

提供了Java.Net的原生客戶端,方便應用集成

支持Spring Placeholder, AnnotationSpring BootConfigurationProperties,方便應用使用(需要Spring 3.1.1+

同時提供了Http接口,非Java.Net應用也可以方便的使用

提供開放平台API

Apollo自身提供了比較完善的統一配置管理界面,支持多環境、多數據中心配置管理、權限、流程治理等特性。

不過Apollo出於通用性考慮,對配置的修改不會做過多限制,只要符合基本的格式就能夠保存。

在我們的調研中發現,對於有些使用方,它們的配置可能會有比較復雜的格式,如xml, json,需要對格式做校驗。

還有一些使用方如DAL,不僅有特定的格式,而且對輸入的值也需要進行校驗后方可保存,如檢查數據庫、用戶名和密碼是否匹配。

對於這類應用,Apollo支持應用方通過開放接口在Apollo進行配置的修改和發布,並且具備完善的授權和權限控制

部署簡單

配置中心作為基礎服務,可用性要求非常高,這就要求Apollo對外部依賴盡可能地少

目前唯一的外部依賴是MySQL,所以部署非常簡單,只要安裝好Java和MySQL就可以讓Apollo跑起來

Apollo還提供了打包腳本,一鍵就可以生成所有需要的安裝包,並且支持自定義運行時參數

Apollo整體架構原理

 

上圖簡要描述了Apollo客戶端的實現原理:

  1. 客戶端和服務端保持了一個長連接,從而能第一時間獲得配置更新的推送。(通過Http Long Polling實現)
  2. 客戶端還會定時從Apollo配置中心服務端拉取應用的最新配置。
    • 這是一個fallback機制,為了防止推送機制失效導致配置不更新
    • 客戶端定時拉取會上報本地版本,所以一般情況下,對於定時拉取的操作,服務端都會返回304 - Not Modified
    • 定時頻率默認為每5分鍾拉取一次,客戶端也可以通過在運行時指定System Property: apollo.refreshInterval來覆蓋,單位為分鍾。
  3. 客戶端從Apollo配置中心服務端獲取到應用的最新配置后,會保存在內存中
  4. 客戶端會把從服務端獲取到的配置在本地文件系統緩存一份
    • 在遇到服務不可用,或網絡不通的時候,依然能從本地恢復配置
  5. 應用程序可以從Apollo客戶端獲取最新的配置、訂閱配置更新通知

 

2, Apollo 框架下載路徑github

https://github.com/ctripcorp/apollo

里面有開發,設計思想問文檔

3,下載完成,解壓

appollo-master 相當於是源碼,apollo-build-scripts-master相當於將好幾個服務集成到一塊,用shell 腳本demo.sh 一鍵啟動

4,將apollo-build-scripts-master 文件夾發送到虛擬機192.168.178.110 /usr/local 的路徑下、

5,打開apollo-build-scripts-master/sql 下兩個sql 文件,並且將他們刷入到數據庫,注意mysql 數據庫版本是要5.7 以上

6,配置demo.sh

#!/bin/bash

# apollo config db info
apollo_config_db_url=jdbc:mysql://192.168.178.110:3306/ApolloConfigDB?characterEncoding=utf8 apollo_config_db_username=root apollo_config_db_password=12345678

# apollo portal db info
apollo_portal_db_url=jdbc:mysql://192.168.178.110:3306/ApolloPortalDB?characterEncoding=utf8 apollo_portal_db_username=root apollo_portal_db_password=12345678

# =============== Please do not modify the following content =============== #

if [ "$(uname)" == "Darwin" ]; then
    windows="0"
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
    windows="0"
elif [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then
    windows="1"
else
    windows="0"
fi

# meta server url
config_server_url=http://192.168.178.110:8080 admin_server_url=http://192.168.178.110:8090 eureka_service_url=$config_server_url/eureka/ portal_url=http://192.168.178.110:8070

需要修改的點,已經標注出來了,

數據庫,本來是安裝在了windows 系統上,也設置了可以遠程登陸,但是啟動的適合都連不上,所以直接在本機,安裝了linux版本的數據庫

配置完成,開始啟動

進入到//usr/local/apollo-build-scripts-master 輸入命令:

./demo.sh start

出現以下界面,則配置成功:

4,url 路徑所代表的意思:

從上圖中,可以看出幾個服務:

Config service:http://192.168.178.110:8080    給應用端調用

Portal service:http://192.168.178.110:8070

Admin Service:為了給Portal service 調用

 

Config service: 就是Eureka 注冊中心,將服務注冊到Eureka 上進行管理

Portal service:用戶名apollo 密碼admin  進入到了分布式配置中心web 界面

進入之后:

5,springboot 項目集成apollo

 創建Java workding set,名稱分布式配置中心,在里面創建springboot 項目,導入maven 

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RC1</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId> 
                <artifactId>jackson-databind</artifactId> </exclusion> </exclusions> -->
        </dependency>

        <!-- apollo 攜程apollo配置中心框架 -->
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-core</artifactId>
            <version>1.0.0</version>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.1</version>
                <executions>
                    <execution>
                        <id>copy-conf</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <encoding>UTF-8</encoding>
                            <outputDirectory>${project.build.directory}/ext/conf</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>ext/conf</directory>
                                    <includes>
                                        <include>logback.xml</include>
                                    </includes>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.5.201505241946</version>
                <executions>
                    <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-prepare-agent-integration</id>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.3</version>
                <configuration>
                    <imageName>hy_uav_gateway</imageName>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                            <include>ext/conf/logback.xml</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

6,將阿波羅build 到本地倉庫

因為以下這兩個包是需要引用Apollo 的包的,也就是之前Apollo-master 的源碼的包

 <!-- apollo 攜程apollo配置中心框架 -->
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-core</artifactId>
            <version>1.0.0</version>
        </dependency>

2中方式可以將源碼打入本地maven 倉庫,第一種,是將源碼導入到eclipse中,利用mvn -install 下

第二種方式就是在Apollo-master/scripts 下的build.bat 文件雙擊,就會自動將包build 

build 完成之后,maven 倉庫就生成了Apollo的包

7,現在在將springboot 項目update ,就可以引用了。

8,創建 apollo-env.properties 去連接apollo 分布式配置中心

local.meta=http://192.168.178.110:8080
dev.meta=http://192.168.178.110:8080
fat.meta=${fat_meta}
uat.meta=${uat_meta}
lpt.meta=${lpt_meta}
pro.meta=${pro_meta}

9,在resources 文件夾下,建立appid ,一個appid,代表一個應用

10,因為項目有好幾種環境,有開發,測試,預生產,生產等,怎么區分apollo 分布式配置中心連的是那種環境呢

修改/opt/settings/server.properties(Mac/Linux)或C:\opt\settings\server.properties(Windows)文件,設置env為DEV:

env=DEV

11,springboot 測試,能否獲得配置中心的值

@RestController
public class IndexController {

    @Value("${projectName:default}")
    private String projectName;

    @Value("${projectLeader:default}")
    private String projectLeader;

    @RequestMapping("/read")
    public String read() {
        return projectName + "===" + projectLeader;
    }

}

啟動類:

@Configuration
@EnableApolloConfig
@SpringBootApplication
@EnableAutoConfiguration
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

 

12,項目啟動之后,還需要在Apollo 配置中心上把projectName,projectLeader 這兩個key的value 添加,apllo 如何知道是哪個項目,就是根據appid

創建項目:

在項目上添加配置的值,支持回滾

13,測試成功

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM