阿里云ACM英文版上线,论“全局配置”在电商国际化微服务平台建设中的妙用

这是一个最好的时代。中国的品牌正在走向世界。希望我们的云服务商们,能够助力它所承载的中国企业出海,以国际化的视野和全球化的高度,为世界各地的客户提供我们最好的服务。

ACM 英文版上线

近日,依托于阿里云的整体国际化战略的持续推进,阿里云应用配置管理产品 ACM 英文版 点我 上线,成为了国内第一个支持纯英文版本的配置管理产品。

Screen Shot 2018-06-06 at 16.28.47.pngScreen Shot 2018-06-06 at 16.28.47.png

中文版产品页对比 中文版 点我

Screen Shot 2018-06-06 at 16.27.08.pngScreen Shot 2018-06-06 at 16.27.08.png

ACM 上线英文版背后的故事

如果问,对于一帮E文水平仅停留在纸面上的程序员来说,产品国际化当中最让大家懵逼的是什么?那一定是要达到 Native 水准的大段大段的英文文档的撰写。

幸好阿里云产品背后有强大的产品文档团队支持,其实这也是一个严肃的商业化产品和开源产品的区别,一个成熟的商业化产品,背后会有强大的专业团队的支持,这包括专业的文档,完善的售前咨询,售后技术支持服务,不过阿里云公有云上的ACM的服务是免费的

下面就摘抄ACM的产品介绍段落让大家就感受一下

What is ACM?

Application Configuration Management (ACM) enables you to centralize the management of application configurations and accomplish real-time configuration push in a distributed environment. With ACM, you can greatly reduce the workload of configuration management and enhance service capabilities in scenarios such as microservices, DevOps, and big data.

Application configuration is one of the common ways to manage application changes. When developing an application, developers usually extract some configuration items or metadata of the application from the code and manage them in a separate configuration file, which is called application configuration. After the application is published, the maintenance personnel or the end user can change the configuration to adjust application behaviors and adapt to environment changes.

ACM serves as the configuration center in a distributed system. It offers a series of functions such as configuration modification, configuration push, historical version management, gray release, and configuration modification audit. With these features, ACM helps you centralize the management of configurations in every application, reduce the cost of configuration management in distributed systems, and lower the risks of availability issues or even failures caused by incorrect configuration changes.

“全局配置”在电商国际化微服务平台建设中的妙用

新闻播报完毕,下面就进入技术干货环节,我们以阿里巴巴电商微服务平台建设为背景,阐述在业务国际化的过程中,如何基于Spring Boot结合ACM的多租户以及全局配置能力做货币、文字、时间的本地化(Localization)管理,来阐释配置中心在微服务架构中的妙用。

背景

Lazada 是阿里巴巴收购的东南亚电商平台,该平台现有业务覆盖到六个东南亚国家(新加坡、越南、印尼、泰国、马来西亚、菲律宾),涉及五亿人群。跨两个时区,同时每个国家都有自己的货币、文字、时间使用习惯等,与国内电商平台设计相比,在整个微服务系统设计时多了一个需要关心的本地化的维度,那就是各区域间多方面的差异,这些差异在系统设计上往往最终可以映射为一个元数据或者配置信息。

挑战分析

DDD - Domain Driven Design

按照微服务DDD划分的方式,一个简单的电商平台可能包含如购物车,订单管理,商品管理,交易管理等,每个子系统通过暴露微服务的方式为其它系统所调用,如下示意图所示:

Screen Shot 2018-06-06 at 17.36.49.pngScreen Shot 2018-06-06 at 17.36.49.png

一套平台代码,多国多实例部署

如下图所示,为了节省开发成本,维护方便,6国电商平台采用了一套平台代码(多个微服务应用)多实例部署的方案。即一套代码分别部署在为不同国家站点服务的多个单元,单元与单元之间数据相互隔离。

Screen Shot 2018-06-06 at 18.23.26.pngScreen Shot 2018-06-06 at 18.23.26.png

如下图所示,这里要做到平台一套代码到处部署的其中一个关键点就是如何严格的将配置和代码分离,因为多国平台数据隔离,每个国家的电商平台连接自己的数据库,也即数据源配置不一样。当然了每个国家部署的平台的货币、文字、时间的管理等配置也不一样,阿里云ACM为应用提供了多租户以及多环境隔离的能力,即使是同一个配置项,也可以根据不同的租户或者namespace设置完全不同的值。

本地化挑战

在上面那个大的架构下。在国际化这个领域里我们面临的挑战简单讲就是,如何实现一套支持多端的、服务间全链路透传的、业务低耦合度低的本地化业务处理API。主要涉及以下几个方面,我们用一个表格来说明问题。

PC WAP APP Background-Server
本地化文字展示
本地化货币计算
本地化货币展示
跨时区的时间计算
本地化时间展示
  • 本地化文字展示

这个部分就是我们通常理解的i18n,文案的多语言展示。要求在一套代码中用统一的方式实现在不通语言下展示对应的文字。

  • 本地化货币计算

不同国家使用的是不同货币。要求在一套代码中用统一方式实现不同币种的金额计算。包括基本的加、减、乘、除、除不尽的情况下进位方式等。此外还包括未来的货币兑换等。

  • 本地化货币展示

不同地区的货币展示是不同的。而且这个也没有统一的标准,很多时候时根据业务方自己的喜好指定。这就要求实现可配置化的针对不同地区的货币展示。

  • 跨时区的时间计算

因为平台部署了6套实例,但其实6套实例都是部署在同样的2个IDC内,IDC内所有的机器时间是在同一个时区,但业务层面在不同的国家,时区不同,这就要求我们在一套代码中确保所有时区标准一致。

  • 本地化时间展示

这个需求是从上述要求中延伸出来的。当我们为时间计算正确采用统一时区时,本地化的展示问题就自然而然摆上台面来了。且时间的展示方式是多样化的,不同的业务方有不同的想法。有的需要展示小时数,有的需要展示两个时间之间的间隔,有的只展示年份等。

解决方案

基于上述对需求的分析,我们这回在设计国际化的框架时有几个指标必须做到

    1. 可配置
    1. 对业务透明
    1. 请求级本地化信息传递和识别
    1. 抽象化对上述问题的处理

平台服务端总体架构图

Screen Shot 2018-06-06 at 18.49.30.pngScreen Shot 2018-06-06 at 18.49.30.png

可以将所有的国际化相关的服务打成了一个富客户端(Spring Boot Starter),部署到各个微服务应用中, 该客户端的结构如上图所示。

  • LocalizationProxyService

    该服务负责总览全局,它持有当前应用所有可用的本地化信息(LocalizationInfo)及其对应的文字、货币、时间、格式化服务。同时具备请求适配功能。能将来自于不同端的请求适配到相关的服务进行处理。

  • Text (ILocalizedTextService)

    文字服务接口,该接口对外提供了丰富的通过key,Locale 获取对应文案的api, 通过基本的key+locale获取对应文案外,还做了批量获取,namespace等特性以保证使用的效率。

  • Monetary (ILocalizedMonetaryService)

    货币服务接口, 基于新的JSR354标准设计。之所以做这个选型是因为,它对货币相关的问题较之其他API做了很好的抽象,有良好的扩展性和严谨的操做线程安全等特点。此外,我们强制要求所有的业务开发团队在存储金额时,使用货币的最小单位+币种的方式。这样就能将所有币种的处理逻辑统一了。上述这些操作,我们都在该接口提供了对应的API支持。

  • Time ( ILocalizedTimeService)

    时间服务,基于JDK8的时间工具类ZoneDateTime设计。之所以做这个选型,原因跟货币类似,因为它对跨时区的时间描述做了很好的抽象,操作API丰富且线程安全。此外,在存储层面我们强制要求业务开发团队在存储时间时一律使用epochMills(从GMT 1970年1月1日0点0分0秒开始)。这样做的好处时在数据层面统一了时区。在代码中使用这个+zoneId就能构造ZonedDateTime进行业务处理了。

  • Format (ILocalizedFormatService)

    格式化服务。该服务专门负责提供各种style的时间、货币输出格式化api。之所以从专用的日期时间服务中独立出来是因为很多时间这项工作出了需要时区,币种作为入参外,还需要Locale,地区和语言信息。因此为了代码的逻辑结构清晰所以独立设计。

  • Request adapter

    请求适配器。为了从来自于不同的端的请求中获取LocalizationInfo而设计。因为不同端对locale信息的处理是不同的,所以需要做适配。

ES Starter与配置中心ACM的关键交互代码示例

private List listConfigLocalizationInfo() {
        List propertiesInfoList = null;
        ...

        if (CollectionUtils.isEmpty(this.properties.getLocalizationInfoList())) {

            ByteArrayInputStream bis = null;

            try {

                String localeCfg = ConfigService.getConfig("lazada_locale.cfg", "localization", 3000);

                Properties localeProp = new Properties();
                propertiesInDiamond.load(new ByteArrayInputStream(localeCfg.getBytes()));
                PropertiesPropertySource source = new PropertiesPropertySource("localizationInfoList",
                propertiesInDiamond);
                MutablePropertySources propertySources = new MutablePropertySources();
                propertySources.addFirst(source);

                RelaxedDataBinder resoler = new RelaxedDataBinder(this.properties, Constant.PREFIX_CONFIGURATION);
                resoler.bind(new PropertySourcesPropertyValues(propertySources));
            } catch (Throwable e) {
                //Log ex info
                processEx(e);
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e1) { //Log ex info
                        processEx(e1); 
                    }
                }
            }
        }

}

Localization Configuration

配置了当前应用所有支持的LocalizaitonInfo列表。在应用启动时,我们根据这个配置把所有的额可用LocalizationInfo加载到LocalizationProxyService中供调用方使用。这个基于ACM的实现很简单可以做到,那么我们怎么理解LocalizationInfo呢。其实它就是一个本地化信息方案。包含了我们做本地化输出所需要的信息,现在我们的一个localziationInfo里所包含的信息如下

field desc
key 一个方案的唯一标识,上述适配器需要从请求中解析出这个值从而获得对应的LocalizationInfo
zoneId 时区Id,如“GMT+X”,”UTC+X”
CurrencyUnit 货币标识
locale 语言国家信息

关键配置内容示例如下:

Screen Shot 2018-06-06 at 19.49.38.pngScreen Shot 2018-06-06 at 19.49.38.png

总结

在本篇文章中,我们以阿里巴巴国际化电商平台Lazada为例,介绍了采用微服务架构构建平台时,使用阿里云配置中心ACM处理国际化当中一些诸如语言、货币、时区等本地化信息的一个可行方案。

即使在非国际化场景中,本文中讲述的方案,即将一个平台中多个微服务系统的公共配置抽象到ACM的公用配置(全局配置)中,同时提炼出平台公用的spring boot starter来控制平台的整体行为(本例中的货币、语言、时区切换),也有很大的实用价值。

更多配置管理 ACM 产品最佳实践

企业级互联网架构Aliware,让您的业务能力云化:https://www.aliyun.com/aliware