官方文档存在的问题

可能由于 Apollo 配置中心的客户端源码一直处于更新中,导致其相关文档有些跟不上节奏,部分文档写的不规范,很容易给做对接的新手朋友造成误导。

比如,我在参考如下两个文档使用传统 .NET 客户端做接入的时候就发现了些问题。

问题一:两个文档关于标识应用身份的AppId的配置节点不一致。

问题二:第二个文档关于应用配置发布环境的Environment配置节点的描述出现明显错误。

当然,这些问题随时都有可能被修复。若您看到文档内容与本文描述不符,请以官方文档为准。

传统 .NET 项目快速接入

快速进入正题。

安装依赖包

在您项目的基础设施层,通过 NuGet 包管理器或使用如下命令添加传统 .NET 项目使用的客户端:

Install-Package Com.Ctrip.Framework.Apollo.ConfigurationManager -Version 2.0.3

从上面的包名能看出什么?我这里选装的是2.0.3的版本。还有,这应该是一个 Javaer 起的名字。

配置应用标识 & 服务地址

在您的启动项目中,打开App.configWeb.config配置文件,在<appSettings>节点中增加如下节点:

<!-- Change to the actual app id -->
<add key="Apollo.AppID" value="R01001" />
<add key="Apollo.MetaServer" value="http://localhost:8080" />

若您部署了多套 Config Service,支持多环境,请参考如下配置:

<!-- Change to the actual app id -->
<add key="Apollo.AppID" value="R01001" /> <!-- Should change the apollo config service url for each environment -->
<add key="Apollo.Env" value="DEV" />
<add key="Apollo.DEV.Meta" value="http://localhost:8080"/>
<add key="Apollo.FAT.Meta" value="http://localhost:8081"/>
<add key="Apollo.UAT.Meta" value="http://localhost:8082"/>
<add key="Apollo.PRO.Meta" value="http://localhost:8083"/>

配置完成后,就可以准备在我们项目中使用 Apollo 客户端了。

二次封装代码

我们习惯在项目中使用第三方库的时候封装一层,这种封装是浅层的,一般都是在项目的基础设施层来做,这样其他层使用就不需要再次引入依赖包。

不说了,直接上代码吧。

代码结构大致如下:

├─MyCompany.MyProject.Infrastructure         # 项目基础设施层
│ │
│ └─Configuration
│ ApolloConfiguration.cs # Apollo 分布式配置项读取实现
│ ConfigurationChangeEventArgs.cs # 配置更改回调事件参数
│ IConfiguration.cs # 配置抽象接口,可基于此接口实现本地配置读取

IConfiguration

using System;
using System.Configuration; namespace MyCompany.MyProject.Infrastructure
{
/// <summary>
/// 配置抽象接口。
/// </summary>
public interface IConfiguration
{
/// <summary>
/// 配置更改回调事件。
/// </summary>
event EventHandler<ConfigurationChangeEventArgs> ConfigChanged; /// <summary>
/// 获取配置项。
/// </summary>
/// <param name="key">键</param>
/// <param name="namespaces">命名空间集合</param>
/// <returns></returns>
string GetValue(string key, params string[] namespaces); /// <summary>
/// 获取配置项。
/// </summary>
/// <typeparam name="TValue">值类型</typeparam>
/// <param name="key">键</param>
/// <param name="namespaces">命名空间集合</param>
/// <returns></returns>
TValue GetValue<TValue>(string key, params string[] namespaces); /// <summary>
/// 获取配置项,如果值为 <see cref="null"/> 则取参数 <see cref="defaultValue"/> 值。
/// </summary>
/// <param name="key">键</param>
/// <param name="defaultValue">默认值</param>
/// <param name="namespaces">命名空间集合</param>
/// <returns></returns>
string GetDefaultValue(string key, string defaultValue, params string[] namespaces); /// <summary>
/// 获取配置项,如果值为 <see cref="null"/> 则取参数 <see cref="defaultValue"/> 值。
/// </summary>
/// <typeparam name="TValue">值类型</typeparam>
/// <param name="key">键</param>
/// <param name="defaultValue">默认值</param>
/// <param name="namespaces">命名空间集合</param>
/// <returns></returns>
TValue GetDefaultValue<TValue>(string key, TValue defaultValue, params string[] namespaces);
}
}

ConfigurationChangeEventArgs

using Com.Ctrip.Framework.Apollo.Model;
using System.Collections.Generic; namespace MyCompany.MyProject.Infrastructure
{
public class ConfigurationChangeEventArgs
{
public IEnumerable<string> ChangedKeys => Changes.Keys;
public bool IsChanged(string key) => Changes.ContainsKey(key);
public string Namespace { get; }
public IReadOnlyDictionary<string, ConfigChange> Changes { get; }
public ConfigurationChangeEventArgs(string namespaceName, IReadOnlyDictionary<string, ConfigChange> changes)
{
Namespace = namespaceName;
Changes = changes;
}
public ConfigChange GetChange(string key)
{
Changes.TryGetValue(key, out var change);
return change;
}
}
}

ApolloConfiguration

using System;
using System.Configuration;
using System.Globalization;
using Com.Ctrip.Framework.Apollo;
using Com.Ctrip.Framework.Apollo.Model; namespace MyCompany.MyProject.Infrastructure
{
public class ApolloConfiguration : IConfiguration
{
private readonly string _defaultValue = null; public event EventHandler<ConfigurationChangeEventArgs> ConfigChanged; private IConfig GetConfig(params string[] namespaces)
{
var config = namespaces == null || namespaces.Length == 0 ?
ApolloConfigurationManager.GetAppConfig().GetAwaiter().GetResult() :
ApolloConfigurationManager.GetConfig(namespaces).GetAwaiter().GetResult(); config.ConfigChanged += (object sender, ConfigChangeEventArgs args) =>
{
ConfigChanged(sender, new ConfigurationChangeEventArgs(args.Namespace, args.Changes));
}; return config;
} public string GetValue(string key, params string[] namespaces)
{
key = key ?? throw new ArgumentNullException(nameof(key));
var config = GetConfig(namespaces);
return config.GetProperty(key, _defaultValue);
} public TValue GetValue<TValue>(string key, params string[] namespaces)
{
var value = GetValue(key, namespaces);
return value == null ?
default(TValue) :
(TValue)Convert.ChangeType(value, typeof(TValue), CultureInfo.InvariantCulture);
} public string GetDefaultValue(string key, string defaultValue, params string[] namespaces)
{
key = key ?? throw new ArgumentNullException(nameof(key));
var config = GetConfig(namespaces);
return config.GetProperty(key, defaultValue);
} public TValue GetDefaultValue<TValue>(string key, TValue defaultValue, params string[] namespaces)
{
var value = GetDefaultValue(key, defaultValue, namespaces);
return value == null ?
default(TValue) :
(TValue)Convert.ChangeType(value, typeof(TValue), CultureInfo.InvariantCulture);
}
}
}

正确使用姿势

在使用之前需要先把ApolloConfiguration注册到应用容器中,请参考如下代码:

public class DependencyRegistrar : IDependencyRegistrar
{
public void Register(ContainerBuilder builder, ITypeFinder typeFinder)
{
// 我们项目使用的 DI 框架是 Autofac,注册这个地方按需修改吧,注意将实例注册成单例。
builder.RegisterType<ApolloConfiguration>()
.As<IConfiguration>()
.Named<IConfiguration>("configuration")
.SingleInstance(); ...
} public int Order
{
get { return 1; }
}
}

接下来就可以在项目中使用了,请参考如下代码:

public class UserController : BaseController
{
private readonly IConfiguration _configuration; public UserController(IConfiguration configuration)
{
_configuration = configuration;
} public ActionResult Add(AddUserInput model)
{
if (ModelState.IsValid)
{
// 从 Apollo 分布式配置中心 项目 R01001 默认命名空间`application`下 读取配置项。
model.Password = _configuration.GetValue("DefaultUserPassword");
...
}
...
}
}

携程 Apollo 配置中心传统 .NET 项目集成实践的更多相关文章

  1. Spring Boot 2.0 整合携程Apollo配置中心

    原文:https://www.jianshu.com/p/23d695af7e80 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够 ...

  2. 携程Apollo配置中心架构深度剖析

    转自:http://www.uml.org.cn/wfw/201808153.asp 一.介绍 Apollo(阿波罗)[参考附录]是携程框架部研发并开源的一款生产级的配置中心产品,它能够集中管理应用在 ...

  3. 携程apollo配置中心服务端如何感知配置更新?

    引言 前面有写过一篇<分布式配置中心apollo是如何实时感知配置被修改>,也就是客户端client是如何知道配置被修改了,有不少读者私信我你既然说了client端是如何感知的,那服务端又 ...

  4. 基于winserver的Apollo配置中心分布式&集群部署实践(正确部署姿势)

    基于winserver的Apollo配置中心分布式&集群部署实践(正确部署姿势)   前言 前几天对Apollo配置中心的demo进行一个部署试用,现公司已决定使用,这两天进行分布式部署的时候 ...

  5. SpringBoot 整合携程Apollo配置管理中心

    携程官网对apollo的使用讲解了很多种方式的使用,但是感觉一些细节还是没讲全,特别是eureka配置中心地址的配置 这里对springboot整合apollo说一下 >SpringBoot启动 ...

  6. 携程的配置中心(阿波罗apollo)

    https://github.com/ctripcorp/apollo https://pan.baidu.com/s/1dFEGMIX#list/path=%2Fmeetup%20ppt%2F040 ...

  7. Apollo配置中心的实战

    31.携程 Apollo 配置中心介绍~1.mp4 32.Apollo核心概念~1.mp4 32.Apollo核心概念~1.mp4 每个应用需要有一个唯一的AppID 要在指定的机器上的server. ...

  8. 携程apollo系列-客户端集成

    本文讲解如何在 Java 程序中集成 Apollo 配置, 主要涉及到一些基础用法. 对于一些高级用法, 比如如何加密/解密配置项 (可用于数据库密码配置), 如何动态切换数据源地址,如何动态切换日志 ...

  9. (转)实验文档3:在kubernetes集群里集成Apollo配置中心

    使用ConfigMap管理应用配置 拆分环境 主机名 角色 ip HDSS7-11.host.com zk1.od.com(Test环境) 10.4.7.11 HDSS7-12.host.com zk ...

随机推荐

  1. shell遍历文件

    取文件每行的数据,需要按列取  可以 sed 加管道 使用 awk 取列 platform="list.txt" line=`grep -vc '^$' $platform` ; ...

  2. Appium+python自动化(十五)- Android 这些基础知识,你知多少???(超详解)

    简介 前边具体操作和实战已经讲解和分享了很多了,但是一些android的一些基础知识,你又知道多少了,你都掌握了吗?这篇就由宏哥给小伙伴们既是一个分享,又是对前边的一次总结.为什么要对这些做一个简单的 ...

  3. python的is与==的区别

    is is比较的是两个变量的地址值,如果地址值正确,则返回True,否则返回False,实例如下: 如图所示,a,b列表的数值相等,但地址是不相等的,所以返回True,与值无关 == ==比较的是两个 ...

  4. PAT L3-016:二叉搜索树的结构(暴力)

    https://www.patest.cn/contests/gplt/L3-016 题意:中文. 思路:暴力构造,暴力查询就好了.只不过操作很多,很麻烦.比赛的时候再给我10分钟就打完了,手速太慢好 ...

  5. 截图编辑器 PicPick Biz v4.1.6/v5.0.3 Lite 绿色便携版

    下载地址:点我 PicPick 是由NGWIN 软件科技公司推出的一款实用的.多功能屏幕截图与图像编辑神器.软件具备屏幕截取.取色器.调色板.放大镜.标尺.量角器.坐标轴.白板等功能,支持全屏.活动窗 ...

  6. Adobe全系软件下载安装工具 CCMaker 1.3.6

    CCMaker是俄罗斯大神El Sanchez开发的一款集Adobe软件全家桶下载.安装.激活一条龙服务的小工具. 程序小巧强大,使用微软通用运行库开发,效率高体积小. 注意,此程序需要安装微软通用C ...

  7. SQL Server 表结构操作

    一.创建表 --直接定义主外键 create table wallet( ID ) primary key, ,) not null, Name ) default '余额', Member_ID ) ...

  8. 提升布局性能____Making ListView Scrolling Smooth

    listview是一个比较重要的UI组件,一切影响UI的操作,比如适配器从磁盘.网络或者数据库中加载数据的操作,最好都放在子线程中完成.子线程可以使用thread,不过那样比较老土,官方推荐使用Asy ...

  9. Python解释器安装教程以及环境变量配置 以及 pycharm的安装与激活

    计算机的组成 主板:人的骨架,用于拓展设备 CPU:人的大脑,用于计算和逻辑处理 硬盘:存储数据(永久储存),比如电脑上的 C盘,D盘 内存:临时记忆(断电即消失) 操作系统:XP win7 win1 ...

  10. 洛谷P3877 [TJOI2010]打扫房间 解题报告

    首先整理一下条件: 1.恰好进出每个需打扫的房间各一次 2.进出每个房间不能通过同一个门 (其实前两个条件是一回事) 3.要求每条路线都是一个闭合的环线 4.每条路线经过的房间数大于2 让你在一个n* ...