Apollo介紹以及應(yīng)用

傳統(tǒng)應(yīng)用配置問題

  • 靜態(tài)配置
    • 傳統(tǒng)應(yīng)用的配置,都是靜態(tài)配置,寫在配置文件中,運(yùn)行時(shí)無(wú)法動(dòng)態(tài)修改,如果修改之后,就需要重啟應(yīng)用
  • 配置格式不統(tǒng)一
    • 開發(fā)人員習(xí)慣不同,使用XML、properties、DB存儲(chǔ)配置
  • 易引起事故
    • 在上線時(shí),有時(shí)會(huì)忘記修改配置文件,將測(cè)試環(huán)境的變量變成線上
  • 配置修改麻煩,周期長(zhǎng)
    • 在部署多個(gè)服務(wù)器時(shí),修改配置費(fèi)時(shí)費(fèi)力
  • 缺少安全審計(jì)和版本控制
    • 沒有版本控制,在出現(xiàn)問題時(shí),無(wú)法及時(shí)進(jìn)行回滾。

配置中心解決方法

  • 靜態(tài)配置
    • 集中式配置,所有的配置信息都保存到配置中心
  • 配置格式不統(tǒng)一
    • 配置中心統(tǒng)一管理格式,開發(fā)人員不用關(guān)心格式,通過界面管理
  • 易引發(fā)事故
    • 環(huán)境隔離,不同的環(huán)境使用不同的配置,互不干擾
    • 配置修改之后,可以生效
  • 配置麻煩,周期長(zhǎng)
  • 配置集中一次修改,實(shí)時(shí)通知到所有客戶端
  • 缺少安全審計(jì)和版本控制
  • 所有修改都有歷史記錄,方便查找修改人和時(shí)間
  • 可以按需退回到歷史版本

配置基本概念

配置定義

  • 可獨(dú)立于程序的可配變量
  • 同一份程序在不同配置下會(huì)有不同行為
  • 應(yīng)用場(chǎng)景:連接字符串、應(yīng)用配置、業(yè)務(wù)配置

配置形態(tài)

  • 程序內(nèi)部硬編碼(堅(jiān)決反對(duì))
  • 配置文件:將配置寫入xml、properties文件中
  • 環(huán)境變量:根據(jù)環(huán)境不同,傳遞到程序中
  • 啟動(dòng)參數(shù):將參數(shù)傳遞到程序中
  • 基于數(shù)據(jù)庫(kù):將配置寫入到數(shù)據(jù)庫(kù)

配置治理

  • 權(quán)限控制和審計(jì):要保留用戶的操作記錄和權(quán)限
  • 不同環(huán)境、集群配置管理:根據(jù)不同環(huán)境,獲取不同的配置
  • 框架類組件配置管理:獲取配置,是否開啟功能
  • 灰度發(fā)布:進(jìn)行公測(cè),環(huán)境隔離

配置分類和場(chǎng)景

動(dòng)態(tài)配置

  • 應(yīng)用配置
    • 請(qǐng)求超時(shí)、線程池、隊(duì)列、緩存、數(shù)據(jù)庫(kù)連接池的容量、日志級(jí)別、限流熔斷閾值、黑白名單
  • 功能開關(guān)
    • 藍(lán)綠發(fā)布、灰度開關(guān)、降級(jí)開關(guān)、HA高可用開關(guān)、DB遷移
  • 業(yè)務(wù)配置
    • 促銷規(guī)律、貸款額度、利率等業(yè)務(wù)參數(shù)、A/B測(cè)試

靜態(tài)配置

  • 安全配置
    用戶名、密碼、令牌、許可證戶等
  • 環(huán)境相關(guān)
    • 數(shù)據(jù)庫(kù)/中間件/其他服務(wù)的連接字符串

開關(guān)驅(qū)動(dòng)開發(fā)原理

優(yōu)點(diǎn)

  • 新功能和代碼發(fā)布分離,減輕發(fā)布風(fēng)險(xiǎn)
  • 迭代速度快,快速創(chuàng)新實(shí)現(xiàn)
  • 可定時(shí)高級(jí)A/B測(cè)試
  • 相對(duì)復(fù)雜發(fā)布系統(tǒng),投入成本相對(duì)低
  • 沒有分支開發(fā)的合并沖突問題

缺點(diǎn)

  • 代碼侵入、需要定期清理
  • 需要開關(guān)配置中心配合
  • 需要DevOps文化和流程配合

Apollo 功能亮點(diǎn)

  • 統(tǒng)一管理不同環(huán)境、不同集群的配置
    • Apollo提供了一個(gè)統(tǒng)一界面集中式管理不同環(huán)境(environment)、不同集群(cluster)、不同命名空間(namespace)的配置。
    • 同一份代碼部署在不同的集群,可以有不同的配置,比如zk的地址等
    • 通過命名空間(namespace)可以很方便的支持多個(gè)不同應(yīng)用共享同一份配置,同時(shí)還允許應(yīng)用對(duì)共享的配置進(jìn)行覆蓋
  • 配置修改實(shí)時(shí)生效(熱發(fā)布)
    • 用戶在Apollo修改完配置并發(fā)布后,客戶端能實(shí)時(shí)(1秒)接收到最新的配置,并通知到應(yīng)用程序。
  • 版本發(fā)布管理
    • 所有的配置發(fā)布都有版本概念,從而可以方便的支持配置的回滾。
  • 灰度發(fā)布
    • 支持配置的灰度發(fā)布,比如點(diǎn)了發(fā)布后,只對(duì)部分應(yīng)用實(shí)例生效,等觀察一段時(shí)間沒問題后再推給所有應(yīng)用實(shí)例。
  • 權(quán)限管理、發(fā)布審核、操作審計(jì)
    • 應(yīng)用和配置的管理都有完善的權(quán)限管理機(jī)制,對(duì)配置的管理還分為了編輯和發(fā)布兩個(gè)環(huán)節(jié),從而減少人為的錯(cuò)誤。
    • 所有的操作都有審計(jì)日志,可以方便的追蹤問題。
  • 客戶端配置信息監(jiān)控
    • 可以方便的看到配置在被哪些實(shí)例使用
  • 提供Java和.Net原生客戶端
    • 提供了Java和.Net的原生客戶端,方便應(yīng)用集成
    • 支持Spring Placeholder,Annotation和Spring Boot的ConfigurationProperties,方便應(yīng)用使用
    • 同時(shí)提供了Http接口,非Java和.Net應(yīng)用也可以方便的使用
  • 提供開放平臺(tái)API
    • Apollo自身提供了比較完善的統(tǒng)一配置管理界面,支持多環(huán)境、多數(shù)據(jù)中心配置管理、權(quán)限、流程治理等特性。
    • 不過Apollo出于通用性考慮,對(duì)配置的修改不會(huì)做過多限制,只要符合基本的格式就能夠保存。
    • 配置可能會(huì)有比較復(fù)雜的格式,如xml, json,需要對(duì)格式做校驗(yàn)。
    • 還有一些使用方如DAL,不僅有特定的格式,而且對(duì)輸入的值也需要進(jìn)行校驗(yàn)后方可保存,如檢查數(shù)據(jù)庫(kù)、用戶名和密碼是否匹配。
    • 對(duì)于這類應(yīng)用,Apollo支持應(yīng)用方通過開放接口在Apollo進(jìn)行配置的修改和發(fā)布,并且具備完善的授權(quán)和權(quán)限控制
  • 部署簡(jiǎn)單
    • 配置中心作為基礎(chǔ)服務(wù),可用性要求非常高,這就要求Apollo對(duì)外部依賴盡可能地少
    • 目前唯一的外部依賴是MySQL,所以部署非常簡(jiǎn)單,只要安裝好Java和MySQL就可以讓Apollo跑起來(lái)
    • Apollo還提供了打包腳本,一鍵就可以生成所有需要的安裝包,并且支持自定義運(yùn)行時(shí)參數(shù)

Apollo 架構(gòu)

核心概念

概念 應(yīng)用 環(huán)境 集群 配置項(xiàng)
解釋 應(yīng)用程序的唯一標(biāo)識(shí),存儲(chǔ)位置為
/META-INF/app.properties
功能不同,不同環(huán)境,存儲(chǔ)位置為
/opt/settings/server.properties
一個(gè)應(yīng)用不同實(shí)例的分組,不同集群,
擁有不同的配置
支持xml、properties、json格式

注意:配置項(xiàng)存放位置:(1)私有配置env+app+cluster+namespace+item_key;(2)共有配置:env+cluster+namespace+item_key。

命名空間

一個(gè)應(yīng)用不同配置的分組,默認(rèn)的命名空間為application。

命名空間類型

  • 私有類型:只能被所屬應(yīng)用獲取
  • 共有類型:環(huán)境變量必須全局唯一
  • 關(guān)聯(lián)類型:私有繼承公開并覆蓋、定制公共組建配置場(chǎng)景

基礎(chǔ)模型

基礎(chǔ)模型的流程:

1.用戶登陸Apollo系統(tǒng)之后,在配置中心修改配置并發(fā)布

2.在用戶發(fā)布配置之后,會(huì)同知道Apollo客戶端更新配置

3.Apollo客戶端會(huì)定時(shí)從配置中心拉取最新的配置、更新本地配置并通知到應(yīng)用

架構(gòu)模塊介紹

Config Server

  • 提供配置獲取接口
  • 提供配置更新推送接口(基于Http long polling)
    • 服務(wù)端使用 Spring DeferredResult實(shí)現(xiàn)異步化,從而大大增加長(zhǎng)連接數(shù)量
    • 目前使用的tomcat embed默認(rèn)配置是最多10000個(gè)連接
  • 接口服務(wù)對(duì)象為Apollo客戶端

Admin Service

  • 提供配置管理接口
  • 提供配置修改、發(fā)布等接口
  • 接口服務(wù)對(duì)象為Portal

Meta Server

  • Portal通過域名訪問Meta Server獲取Admin Service服務(wù)列表(IP+Port)
  • Client通過域名訪問Meta Server獲取Config Service服務(wù)列表(IP+Port)
  • Meta Server從Eureka獲取Config Service和Admin Service的服務(wù)信息,相當(dāng)于是一個(gè)Eureka Client
  • 增設(shè)一個(gè)Meta Server的角色主要是為了封裝服務(wù)發(fā)現(xiàn)的細(xì)節(jié),對(duì)Portal和Client而言,永遠(yuǎn)通過一個(gè)Http接口獲取Admin Service和Config Service的服務(wù)信息,而不需要關(guān)心背后實(shí)際的服務(wù)注冊(cè)和發(fā)現(xiàn)組件
  • Meta Server只是一個(gè)邏輯角色,在部署時(shí)和Config Service是在一個(gè)JVM進(jìn)程中的,所以IP、端口和Config Service一致

Eureka

  • 基于Eureka和Spring Cloud Netflix提供服務(wù)注冊(cè)和發(fā)現(xiàn)
  • Config Service和Admin Service會(huì)向Eureka注冊(cè)服務(wù),并保持心跳
  • 為了簡(jiǎn)單起見,目前Eureka在部署時(shí)和Config Service是在一個(gè)JVM進(jìn)程中的(通過Spring Cloud Netflix)

Portal

  • 提供Web界面供用戶管理配置
  • 通過Meta Server獲取Admin Service服務(wù)列表(IP+Port),通過IP+Port訪問服務(wù)
  • 在Portal側(cè)做load balance、錯(cuò)誤重試

Client

  • Apollo提供的客戶端程序,為應(yīng)用提供配置獲取、實(shí)時(shí)更新等功能
  • 通過Meta Server獲取Config Service服務(wù)列表(IP+Port),通過IP+Port訪問服務(wù)
  • 在Client側(cè)做load balance、錯(cuò)誤重試

框架如何保證實(shí)時(shí)更新

用戶在Portal發(fā)布配置之后,AdminService會(huì)將配置寫入到ReleaseMessage表中,ConfigServer會(huì)定期掃描ReleaeMessage表,會(huì)實(shí)時(shí)通知客戶端。(長(zhǎng)連接,通過Http Long Polling實(shí)現(xiàn))

客戶端還會(huì)定時(shí)從Apollo配置中心拉取配置(推拉結(jié)合,Spring DeferredResult、定期拉配置)

高可用

1.Config/Admin/Portal 都是用負(fù)載均衡技術(shù),來(lái)保證高可用。
2.服務(wù)端的實(shí)時(shí)推送技術(shù)、客戶端定時(shí)拉取配置,保證及時(shí)性,如果拉取不到,客戶端使用本地緩存的配置,保證高可用。

為什么使用Eureka

  • 它提供了完整的Service Registry和Service Discovery實(shí)現(xiàn)
    +首先是提供了完整的實(shí)現(xiàn),并且也經(jīng)受住了Netflix自己的生產(chǎn)環(huán)境考驗(yàn),相對(duì)使用起來(lái)會(huì)比較省心。
  • 和Spring Cloud無(wú)縫集成
    • 同時(shí)Spring Cloud還有一套非常完善的開源代碼來(lái)整合Eureka,使用起來(lái)非常方便。
    • Eureka支持在應(yīng)用自身的容器中啟動(dòng),也就是說應(yīng)用啟動(dòng)完之后,既充當(dāng)了Eureka的角色,同時(shí)也是服務(wù)的提供者。這樣就極大的提高了服務(wù)的可用性。
      +為了提高配置中心的可用性和降低部署復(fù)雜度,我們需要盡可能地減少外部依賴。
  • 開源
    +由于代碼是開源的,所以非常便于我們了解它的實(shí)現(xiàn)原理和排查問題

Apollo 于Spring Boot 結(jié)合

pom依賴

<parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.1.8.RELEASE</version>
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.ctrip.framework.apollo</groupId>
        <artifactId>apollo-client</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

yml文件

app:
  id: SampleApp
apollo:
  bootstrap:
    enabled: true
  meta: https://localhost:8080

function:
  switch:
    open: false

current:
  version: v1
server:
  port: 9000

添加Apollo配置

package com.edu.apollo.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;

@Data
public class DemoGlobalConfig {
    @Value("${current.version}")
    public String currentVersion;
    @Value("${function.switch.open}")
    public boolean switchFlag;
}
package com.edu.apollo.config;

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

@Configuration
@EnableApolloConfig
public class DemoApolloConfig {
    @Bean
    public DemoGlobalConfig globalConfig() {
        return new DemoGlobalConfig();
    }
}

相對(duì)應(yīng)的Controller

package com.edu.apollo.controller;

import com.edu.apollo.config.DemoGlobalConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


@RestController
public class ApolloConfigController {
    @Autowired
    DemoGlobalConfig demoGlobalConfig;

    @Autowired
    Environment environment;

    @CrossOrigin
    @RequestMapping(value = "/config", method = RequestMethod.GET)
    public ResponseEntity<String> getApolloConfig() {
        String currentVersion = demoGlobalConfig.getCurrentVersion();
        return new ResponseEntity<String>(currentVersion,HttpStatus.OK);
    }
    //check whether the parameter is valid or not
    @CrossOrigin
    @RequestMapping(value = "/parameter", method = RequestMethod.GET)
    public ResponseEntity<String> getApolloConfigByParameter(@RequestParam String parameter) {
        String result = environment.getProperty(parameter);
        if (result == null){
            result = "defaultValue";
        }
        return new ResponseEntity<String>(result,HttpStatus.OK);
    }
}

添加開關(guān)

package com.edu.apollo.service;

public interface SwitchService {
    public String getSwitchData();
}
package com.edu.apollo.service.impl;

import com.edu.apollo.config.DemoGlobalConfig;
import com.edu.apollo.service.SwitchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SwitchServiceImpl implements SwitchService {
    @Autowired
    private DemoGlobalConfig demoGlobalConfig;

    @Override
    public String getSwitchData() {
        if (demoGlobalConfig.isSwitchFlag()) {
            return "new";
        } else {
            return "old";
        }
    }
}
package com.edu.apollo.controller;

import com.edu.apollo.service.SwitchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SwitchController {

    @Autowired
    private SwitchService switchService;

    @GetMapping(value = "/switch")
    public ResponseEntity<String> getSwitchOpen(){
        return new ResponseEntity<String>(switchService.getSwitchData(),HttpStatus.OK);
    }
}

在啟動(dòng)程序的時(shí)候,需要添加環(huán)境變量:-Dapollo.configService=http://localhost:8080

Apollo啟動(dòng)過程

start config service  for client 
start admin service for portal 8090
start portal service 8070
eureka 8080
apollo cache:/opt/data/{appid}/config-cache  要有讀寫權(quán)限

運(yùn)行步驟

校驗(yàn)是否啟動(dòng)成功

在程序啟動(dòng)之后,需要進(jìn)行校驗(yàn): http://localhost:9000/config

返回值為v1

校驗(yàn)Apollo是否生效

在Apollo界面上更改配置為current.version=v2
在程序啟動(dòng)之后,需要進(jìn)行校驗(yàn): http://localhost:9000/config

返回值為v2

開關(guān)功能校驗(yàn)

在程序啟動(dòng)之后,需要進(jìn)行校驗(yàn): http://localhost:9000/switch

返回值為old

在Apollo界面上更改配置為function.switch.open=true

在程序啟動(dòng)之后,需要進(jìn)行校驗(yàn): http://localhost:9000/config

返回值為v2

參考文獻(xiàn)

Apollo配置中心設(shè)計(jì)
微服務(wù)架構(gòu)~攜程Apollo配置中心架構(gòu)剖析
source code

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、總體設(shè)計(jì) 1.1 基礎(chǔ)模型 如下即是Apollo的基礎(chǔ)模型: 用戶在配置中心對(duì)配置進(jìn)行修改并發(fā)布 配置中心通知...
    蝸牛先森1230閱讀 5,394評(píng)論 0 4
  • 配置中心發(fā)展背景隨著程序功能的日益復(fù)雜,程序的配置日益增多:各種功能的開關(guān)、參數(shù)的配置、服務(wù)器的地址……對(duì)程序配置...
    緘默_8421閱讀 15,951評(píng)論 3 19
  • Apollo(阿波羅)是攜程框架部門研發(fā)的分布式配置中心,能夠集中化管理應(yīng)用不同環(huán)境、不同集群的配置,配置修改后能...
    BeckJin閱讀 3,997評(píng)論 0 1
  • 在Spring Boot 2.0 整合攜程Apollo配置中心一文中,我們?cè)诒镜乜焖俨渴鹪囉昧薃pollo。本文將...
    AaronSimon閱讀 17,881評(píng)論 1 24
  • 引子 皇城的夜,向來(lái)是不寂寞的。城南的簫聲仿佛愣是要將這肅殺的嚴(yán)冬挽成楊柳依依的四月。亦河兩岸熙熙攘攘的人群似乎完...
    碧空_96ed閱讀 165評(píng)論 0 1

友情鏈接更多精彩內(nèi)容