2021年5月

5 月 29 日,阿里云开发者大会上,阿里云宣布开源云原生数据库能力,开源关系型数据库 PolarDB for PostgreSQL,将阿里内部沉淀多年的技术分享出来,服务于百万开发者。目前,该项目已在阿里云官网及 Github 上发布,后续将引入分布式事务、单机高性能等能力。

阿里云数据库负责人李飞飞表示:

“我们希望将阿里云在数据库技术上积累的丰富经验,通过标准技术组件和系统的方式开放出来,共建开源数据库生态。”

数据库是基础软件中的刚需,与芯片、操作系统并列为“全球技术三大件”。开源模式广受数据库用户欢迎,被认为是互联网场景的标配。

PolarDB 是阿里云自研的数据库产品家族,采用存储计算分离、软硬一体化设计,既拥有分布式设计的低成本优势,又具有集中式的易用性,可满足大规模应用场景需求。计算能力最高可扩展至 1000 核以上,存储容量最高可达 100TB,集群版单库最多可扩展到 16 个节点,性能比 MySQL 高 6 倍。PolarDB 系列产品已连续多年稳定支撑天猫双 11,处理峰值高达创纪录的 1.4亿次/秒。

为满足用户多样化的需求,PolarDB 针对不同的数据库协议开发了不同的兼容版本,包括兼容 MySQL、PostgreSQL 和 Oracle 的版本,及每个版本的分布式形态。

此次阿里云开源的是 PolarDB for PostgreSQL 分布式版,包括数据库内核、相关插件、工具脚本、测试用例以及设计文档,适用于中大型企业核心业务场景。本次开源遵循 Apache 2.0 许可证,以全共享并尊重原作者著作权的模式开源,代码可以修改和再发布。

这让我想起来前一段时间 MariaDB 宣布了将它的分布式 SQL 引擎 Xpand 作为其 DBaaS 服务的 SkySQL 系统引擎之一,然而 Xpand 是一个专有的软件。这引起了业界对开源服务之上的专有服务的隐忧,因为这失去了开源的重要优势 —— 避免供应商锁定。

在业界,开源数据库众多,但是能将分布式能力也开源出来的罕有,而能形成产品级的、可以利用现有数据库基础设施的开源产品更是不多。因此,PolarDB for PostgreSQL 的这次开源可谓是不但给 PostgreSQL 注入了一剂强心针,而且也与 Xpand 这种开源引擎之上的专有服务形成了鲜明对比。

在对李飞飞的采访中,他谈到了为什么要开源 PolarDB:

“我们开源的目的是非常纯粹的,我们在开源这一部分没有任何商业化的目的,就是要把开发者的生态做起来。”

而且,他认为没有必要重新建立一个新的生态,在原本非常繁荣的 PostgreSQL 生态上“助力一把火,让它烧得更旺。我们希望让开发者可以在现有的 PostgreSQL 上做的更好。本质上就是把我们在 PostgreSQL 上积累多年的能力开源出来,回馈给社区,而且以插件的方式。”

而且,为了鼓励社区能参与进来,阿里云也体现了极大的诚意,采用了更加宽松、自由的开源许可证 Apache 2.0,“你可以再开发,你可以商用,都没有问题,我们完全鼓励。”

为什么这样做呢,李飞飞谈到:“通过这样把开发者生态建立起来以后,我们从中获得了什么?我们获得的是开发者对 PostgreSQL 整个大生态的持续的关注和投入,然后最终我们也会从中受益,因为我们会从开发者贡献的代码里面去汲取对我们有用的部分,我相信其他的厂商不管是云厂商数据库厂商可能也会因此受益。但没关系,我们认为水涨船高,只要整个的社区做起来,我们阿里云还一定会是领导者,我们有自信,所以我们愿意去做这件事。”

李飞飞认为:

“我个人认为开源是建立生态的非常关键的一个抓手,非常关键的抓手。它和商业化一定要非常好的平衡,但绝对不是说天然的就是矛盾的两面,矛盾的地方绝对有,不然的话大家不会这么纠结,但是我个人认为要处理好平衡,是需要有非常强的定力和判断力,但你一旦处理好,它并不一定就一定会发展成矛盾体,这是我个人的一个观点。”

我想,这应该就是阿里云坚定开源战略的主要原因之一。

但是同时他也表示,不要走到另外一个极端:

“大家千万不要落到另外一个陷阱里面去,认为‘开源就是灵丹灵丹妙药,开源就能解决问题了’。我个人也是非常反对这个观点,关键还是看你后续社区的运营,是不是真的用心在做这个社区,是不是真的有高质量的贡献出来,让大家真正的从里面能够受益。我觉得这个是后面的挑战。”

根据披露的 PolarDB for PostgreSQL 开源路线图,阿里云是有计划、有步骤的将主要的、完备的部分向社区开放。我想,这将揭幕云原生数据库的新时代。

阿里云发布第七代云服务器,并全面兼容 X86、ARM、RISC-V等多种芯片架构

今天阿里云在北京召开 2021 阿里云峰会,一句发布多款新品,包括第七云服务器、一站式数据服务平台、湖仓一体 2.0 等;

阿里云智能总裁张建锋表示,阿里云自研的云计算操作系统飞天已经全面兼容 X86、ARM 、RISC-V 芯片架构。

阿里云作为国内的云计算的先行者, 领头羊,他们的一举一动都会带来行业的跟随,下一步就可以期待各家都对 ARM、RISC-V 等芯片架构的支撑,真正推动 ARM 架构落地服务器领域。

Ubuntu 用户被 DMCA 组织滥发 DMCA 通知

美国电信公司 Comcast 的一个用户在 Reddit 上透露,他通过 BT 下载了 Ubuntu 官方的 ISO 镜像后收到了 DMCA 侵权通知。

DMCA 全称是千禧年数字版权法,用于保护软件创作者作者的原始权利。但法律无罪,人有罪, 当人将法律用在一些坏的途径上时,这法律就成了恶法。

FaceBook 赞助的研究抨击苹果的隐私问题

苹果在 iOS 14.5 后为每一个 App 加入了强制的信息追踪弹窗,以允许用户禁止 App 的针对性追踪。而最近,佛罗里达大学莱文学院的丹尼尔 · 索科尔与哈佛大学商学院的朱锋撰写的论文《Harming Competition and Consumers under the Guise of Protecting Privacy: An Analysis of Apple’s iOS 14 Policy Updates》抨击了这一功能。

学术沦为资本的工具,可叹可笑。

在将嵌入式系统操作系统移植到不同的芯片架构时,RT-Thread 的维护者们从中学到了什么。

 title=

曾经有人问我,为什么计算机被称为“计算机”,它们做的事情可远不止计算数字。一台现代的个人电脑可以浏览互联网、播放音频和视频、为视频游戏和电影生成漂亮的图形、模拟和预测复杂的天气模式和流行病风险、将建筑和工程蓝图变为现实等等。

计算机之所以能做到这些,是因为所有这些问题都可以归结为数字方程,而计算机的 CPU —— 其中央处理单元 —— 实际上不过是一个简单的计算器。

为了让 CPU 向硬盘驱动器发送信号以写入数据,或向显示器发送信号以显示图像,它必须接收指令。这些指令是以 “代码” 的形式出现的,这是一种简明的说法,即必须有人写一个 程序 ,与CPU “说” 同样的语言。CPU 理解的是 机器语言,这是一个大多数人都无法理解的比特阵列,大多数人都不可能手动写出来。相反,我们使用像 C、C++、Java、Python 等编程语言。这些语言被解析并编译成机器语言,然后交付给 CPU。

如果你试图用一种它不理解的语言来指示 CPU,它不知道该怎么做。你可以通过尝试用 x86\_64 RHEL 镜像启动 树莓派 来体验这种误传尝试的尴尬结果。如果它能工作就好了,但是不能。

将一个操作系统移植到一个新的架构上

RT-Thread 项目 为嵌入式系统程序员提供了一个开源的操作系统(OS)。嵌入式领域是非常多样化的,有很多物联网(IoT)、定制工业和业余设备。RT-Thread 的目标是使嵌入式编程对每个人来说都很容易,无论你使用什么设备。有时,这意味着要将一个操作系统移植到一个新的架构上,不管是用于相同架构但指令集略有不同的的芯片,还是用于全新的架构。

一开始处理这个问题可能会有点吓人 —— 你可能不知道从哪里开始或如何开始。这篇文章收集了 RT-Thread 维护者在将 RTOS 移植到新的芯片架构时学到的经验。

你在开始之前需要知道什么

这里是一个看似难以逾越的过程的高屋建瓴的观点。这对你的项目来说可能有所不同,但从概念上来说,这是相对普遍的,即使一些具体的细节是不同的:

  1. 准备好一个 C 语言的执行环境
  2. 确认可以通过串行端口发送和接收字符
  3. 确认上下文切换代码可以工作
  4. 获取支持的硬件定时器
  5. 确认中断程序可以通过串口接收和解析数据

执行模式

对于大多数先进的体系结构,操作系统和用户应用程序运行在不同的权限级别上。这可以防止有功能故障的代码影响操作系统的集成和安全。例如,在 ARMv7-A 架构中,操作系统通常在系统模式下运行,而在 ARMv8-A 中,操作系统可以在 EL2 或 EL3 权限级别上运行。

通常情况下,芯片在通电时以最高权限级别执行启动代码。但在此之后,操作系统会将特权级别切换到其目标模式。

1、执行 C 代码

这一步的关键动作是将 块起始符号 block starting symbol (.bss)部分设置为零,并设置堆栈指针。

在 C 语言的实现中,未初始化的全局变量和静态变量通常存储在 .bss 部分,它不占用存储设备的任何空间。当程序被加载时,相应的空间被分配到内存中,并被初始化为零。当操作系统启动时,它必须自己做这项工作。

另一方面,操作系统必须初始化堆栈空间并设置堆栈指针。由于 C 语言程序在进入和退出函数时在堆栈上保存和恢复局部变量,所以在调用任何 C 函数之前必须设置堆栈指针。RT-Thread 必须为每个新创建的线程做这个步骤。

2、至少使用一个串行驱动器

RT-Thread 通过串口输出信息和日志,这也有助于在移植过程中对代码进行调试。在这个阶段,通过串口 接收 数据是不必要的。当我们第一次在串口上看到我们友好的、熟悉的 RT-Thread 的标志时,我们就知道我们走对了路!

3、确认上下文切换逻辑

一个任务的上下文是它的整个执行环境,它包含通用寄存器、程序计数器、堆栈帧的位置等等。当一个新的线程被创建时,RT-Thread 必须手动分配和设置它的上下文,这样调度器就可以切换到新的线程,就像它对其他线程一样。

有三件事需要注意:

  • 首先,当 RT-Thread 启动时,默认情况下中断是禁用的。当任务调度器第一次被启用时,它们就会被启用;这个过程是在上下文切换期间用汇编语言实现的。
  • 第二,当一个线程退出时,下一个调度将开始,这时拥有的资源会被空闲的线程回收。
  • 第三,数据被推入堆栈的顺序必须与从堆栈中弹出数据的顺序一致。

一般来说,你希望正常进入主函数和 msh 控制台。然而,在这个阶段无法实现输入控制,因为串行输入中断还没有实现。当串行中断实现后,就可以进行 msh 输入了。

4、设置定时器

RT-Thread 需要一个定时器来定期产生中断;它被用来计算自系统启动以来所经过的“滴答”。计数器的编号用于提供软件中断功能,并指示内核何时开始调度一个任务。

设置时间片的值可能是一件棘手的事情。它通常是 10ms 到 1ms。如果你在一个慢速的 CPU 上选择一个小的时间片,大部分时间就会花在任务切换上 —— 不利于完成其他事情。

5、确认串口工作正常

在这一步,我们通过串口与 RT-Thread msh 进行交互。我们发送命令,按回车键,然后看着 msh 执行命令并显示结果。

这个过程通常不难实现。不过,有一点要提醒大家。在某些平台上,在处理完串口中断后,别忘了清除中断标志。

一旦串口工作正常,移植过程基本上就完成了。

实践

为了将你的项目移植到不同的芯片架构上,你需要非常清楚地了解你所针对的芯片的架构。熟悉你的项目中最关键的部分的底层代码。通过对照芯片的手册结合大量的实际工作经验,你会了解芯片的特权模式、寄存器和编译方法。

如果你没有需要移植到新芯片的项目,请加入我们;RT-Thread 项目总是需要帮助将 RTOS 移植到新的芯片上!作为一个开源项目,RT-Thread 正在改变开源嵌入式编程的面貌。请在 RT-Thread 俱乐部介绍你自己并寻求帮助!


本文基于 DEV 社区上的 如何将操作系统移植到不同的芯片架构上?,并经许可转载。


via: https://opensource.com/article/21/5/port-chip-architectures

作者:Alan Smithee 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

探索一些未被充分利用但仍然有用的 Python 特性。

 title=

这是 Python 3.x 首发特性系列文章中的第三篇。其中一些 Python 版本已经推出了一段时间。例如,Python 3.2 是在 2011 年首次发布的,但其中引入的一些很酷、很有用的特性仍然没有被使用。下面是其中的三个。

argparse 子命令

argparse 模块首次出现在 Python 3.2 中。有许多用于命令行解析的第三方模块。但是内置的 argparse 模块比许多人认为的要强大。

要记录所有的 argparse 的特性,那需要专门写系列文章。下面是一个例子,说明如何用 argparse 做子命令。

想象一下,一个命令有两个子命令:negate,需要一个参数,multiply,需要两个参数:

$ computebot negate 5
-5
$ computebot multiply 2 3
6
import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

add_subparsers() 方法创建一个对象,你可以向其添加子命令。唯一需要记住的技巧是,你需要添加通过 set_defaults() 调用的子命令:

negate  = subparsers.add_parser("negate")
negate.set_defaults(subcommand="negate")
negate.add_argument("number", type=float)
multiply  = subparsers.add_parser("multiply")
multiply.set_defaults(subcommand="multiply")
multiply.add_argument("number1", type=float)
multiply.add_argument("number2", type=float)

我最喜欢的一个 argparse 功能是,因为它把解析和运行分开,测试解析逻辑特别令人愉快。

parser.parse_args(["negate", "5"])
    Namespace(number=5.0, subcommand='negate')
parser.parse_args(["multiply", "2", "3"])
    Namespace(number1=2.0, number2=3.0, subcommand='multiply')

contextlib.contextmanager

上下文是 Python 中一个强大的工具。虽然很多人 使用 它们,但编写一个新的上下文常常看起来像一门黑暗艺术。有了 contextmanager 装饰器,你所需要的只是一个一次性的生成器。

编写一个打印出做某事所需时间的上下文,就像这样简单:

import contextlib, timeit

@contextlib.contextmanager
def timer():
    before = timeit.default_timer()
    try:
        yield
    finally:
        after = timeit.default_timer()
        print("took", after - before)

你可以这样使用:

import time

with timer():
    time.sleep(10.5)
    took 10.511025413870811`

functools.lru\_cache

有时,在内存中缓存一个函数的结果是有意义的。例如,想象一下经典的问题:“有多少种方法可以用 25 美分、1 美分、2 美分和 3 美分可以来换取 1 美元?”

这个问题的代码可以说是非常简单:

def change_for_a_dollar():
    def change_for(amount, coins):
        if amount == 0:
            return 1
        if amount < 0 or len(coins) == 0:
            return 0
        some_coin = next(iter(coins))
        return (
            change_for(amount, coins - set([some_coin]))
            +
            change_for(amount - some_coin, coins)
        )
    return change_for(100, frozenset([25, 10, 5, 1]))

在我的电脑上,这需要 13ms 左右:

with timer():
    change_for_a_dollar()
    took 0.013737603090703487`

事实证明,当你计算有多少种方法可以做一些事情,比如用 50 美分找钱,你会重复使用相同的硬币。你可以使用 lru_cache 来避免重复计算。

import functools

def change_for_a_dollar():
    @functools.lru_cache
    def change_for(amount, coins):
        if amount == 0:
            return 1
        if amount < 0 or len(coins) == 0:
            return 0
        some_coin = next(iter(coins))
        return (
            change_for(amount, coins - set([some_coin]))
            +
            change_for(amount - some_coin, coins)
        )
    return change_for(100, frozenset([25, 10, 5, 1]))
with timer():
    change_for_a_dollar()
    took 0.004180959425866604`

一行的代价是三倍的改进。不错。

欢迎来到 2011 年

尽管 Python 3.2 是在 10 年前发布的,但它的许多特性仍然很酷,而且没有得到充分利用。如果你还没使用,那么将他们添加到你的工具箱中。


via: https://opensource.com/article/21/5/python-32

作者:Moshe Zadka 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

微软发布其官方的包管理器 WinGet 1.0

微软在昨天(2021年5月27日)发布了 WinGet Cli 的 1.0 版本,该版本可以实现在 Windows 命令行中安装、更新、卸载软件等操作。

微软为 Windows 配置包管理器是一个很「Linux」的事情,Windows 的软件安装方式太过多元化不一定适合每一个场景。而 winget 这种官方的工具,想来要比 Chocolatey 之类的第三方工具获得更好的发展。

长期工作每年导致数十万人死亡

世界卫生组织和世界劳工组织的一项新研究表明,长时间工作每年导致数十万人死亡。2016年,每周工作超过55小时的带薪工作导致74.5万人死亡,高于2000年的59万人。2016年,约39.8万人死于中风,34.7万人死于心脏病。作者认为,生理应激反应和行为改变(如不健康饮食、睡眠不良和体力活动减少)都是长时间工作对健康产生负面影响的“可想而知”原因。每周工作超过55小时是危险的。与每周工作35-40小时相比,它与中风风险和心脏病风险分别高出35%和17%相关。

对于我们每一个人来说,奋斗是必要的,但身体是最重要的,切不可丢了西瓜,捡了芝麻。

HaveIBeenPwned 服务开源

HaveIBeenPwned 是一个可以帮助你查询你的邮箱、手机号及相关密码是否泄漏的服务。其创始人 Troy Hunt 将 HaveIBeenPwned 源代码开放在 Github 上。

近年来的数据安全泄漏事故频发。HaveIBeenPwned的出现可以让我们检测自己是否有密码泄漏;除了 Have I Been Pwned ,你还可以试试 Mozila 推出的 Firefox Monitor。

ScummVM 是在现代硬件上玩老式视频游戏的最直接的方法之一。

 title=

玩冒险游戏一直是我使用计算机经验的一个重要部分。从最早的基于文本的冒险游戏到 2D 像素艺术、全动态视频和 3D 游戏,冒险游戏类型为我提供了很多美好的回忆。

有时我想重温那些老游戏,但它们很多都是在 Linux 出现之前发布的,那么我如何去重玩这些游戏呢?我使用 ScummVM,说实话,这是我最喜欢的开源项目之一。

什么是 ScummVM

 title=

ScummVM 是一个设计用来在现代硬件上玩老式冒险游戏的程序。ScummVM 最初是为了运行使用 卢卡斯艺术 LucasArt 疯狂豪宅脚本创作工具 Script Creation Utility for Maniac Mansion (SCUMM)开发的游戏,现在支持许多不同的游戏引擎。它可以支持几乎所有经典的 雪乐山娱乐 Sierra On-Line 和卢卡斯艺术的冒险游戏,以及其他发行商的大量冒险游戏。ScummVM 并不支持所有的冒险游戏(目前),但它可以用来玩数百种冒险游戏。ScummVM 可用于多个平台,包括 Windows、macOS、Linux、Android、iOS 和一些游戏机。

为什么使用 ScummVM

有很多方法可以在现代硬件上玩老游戏,但它们往往比使用 ScummVM 更复杂。DOSBox 可以用来玩 DOS 游戏,但它需要调整设置,使其以正确的速度进行游戏。Windows 游戏可以用 WINE 来玩,但这需要游戏及其安装程序都与 WINE 兼容。

即使游戏可以在 WINE 下运行,一些游戏仍然不能在现代硬件上很好地运行,因为硬件的速度太快了。这方面的一个例子是《 国王密使 6 King's Quest VI 》中的一个谜题,它涉及将点燃的鞭炮带到某个地方。在现代硬件上,鞭炮爆炸的速度太快了,这使得在角色不死很多次的情况下不可能到达正确的位置。

ScummVM 消除了其他玩复古冒险游戏的方法中存在的许多问题。如果是 ScummVM 支持的游戏,那么它的配置和玩都很简单。在大多数情况下,将游戏文件从原始游戏光盘复制到一个目录,并在 ScummVM 中添加该目录,就可以玩该游戏了。对于多张光盘上的游戏,可能需要重命名一些文件以避免文件名冲突。需要哪些数据文件的说明以及任何重命名的说明都记录在 每个支持的游戏 的 ScummVM 维基页面上。

ScummVM 的一个奇妙之处在于,每一个新版本都会增加对更多游戏的支持。ScummVM 2.2.0 增加了对十几种互动小说解释器的支持,这意味着 ScummVM 现在可以玩数百种基于文本的冒险游戏。ScummVM 的开发分支应该很快就会变成 2.3.0 版本,它整合了 ResidualVM 对 3D 冒险游戏的支持,所以现在 ScummVM 可以用来玩《 冥界狂想曲 Grim Fandango 》、《神秘岛 3:放逐者Myst III: Exile》和《 最长的旅程 The Longest Journey 》。其开发分支最近还增加了对使用 Adventure Game Studio 创建的游戏的支持,这为 ScummVM 增加了成百上千的游戏。

如何安装 ScummVM

如果你想从你的 Linux 发行版的仓库中安装 ScummVM,过程非常简单。你只需要运行一个命令。然而,你的发行版可能会提供一个旧版本的 ScummVM,它不像最新版本那样支持许多游戏,所以要记住这一点。

在 Debian/Ubuntu 上安装 ScummVM:

sudo apt install scummvm

在 Fedora 上安装 ScummVM:

sudo dnf install scummvm

使用 Flatpak 或 Snap 安装 ScummVM

ScummVM 也可以以 Flatpak 和 Snap 的形式提供。如果你使用这些方式之一,你可以使用以下命令来安装相关的版本,它应该总是 ScummVM 的最新版本。

flatpak install flathub org.scummvm.ScummVM

snap install scummvm

编译 ScummVM 的开发分支

如果你想尝试 ScummVM 尚未稳定的开发分支中的最新和主要的功能,你可以通过编译 ScummVM 的源代码来实现。请注意,开发分支是不断变化的,所以事情可能不总是正确的。如果你仍有兴趣尝试开发分支,请按照下面的说明进行。

首先,你需要为你的发行版准备必要的开发工具和库,这些工具和库在 ScummVM 维基上的 编译 ScummVM/GCC 页面列出。

一旦你安装了先决条件,运行以下命令:

git clone <https://github.com/scummvm/scummvm.git>
cd scummvm
./configure
make
sudo make install

向 ScummVM 添加游戏

将游戏添加到 ScummVM 是你在游戏前需要做的最后一件事。如果你的收藏集中没有任何支持的冒险游戏,你可以从 ScummVM 游戏 页面下载 11 个精彩的游戏。你还可以从 GOG.com 购买许多 ScummVM 支持的游戏。如果你从 GOG.com 购买了游戏,并需要从 GOG 下载中提取游戏文件,你可以使用 innoextract 工具。

大多数游戏需要放在自己的目录中(唯一的例外是由单个数据文件组成的游戏),所以最好先创建一个目录来存储你的 ScummVM 游戏。你可以使用命令行或图形化文件管理器来完成这个工作。在哪里存储游戏并不重要(除了 ScummVM Flatpak,它是一个沙盒,要求游戏存储在 ~/Documents 目录中)。创建这个目录后,将每个游戏的数据文件放在各自的子目录中。

一旦文件被复制到你想要的地方,运行 ScummVM,并通过点击“Add Game…”将游戏添加到收藏集中,在打开的文件选择器对话框中选择适当的目录,并点击“Choose”。如果 ScummVM 正确检测到游戏,它将打开其设置选项。如果你想的话,你可以从各个标签中选择高级配置选项(也可以在以后通过使用“Edit Game…”按钮进行更改),或者你可以直接点击“OK”,以默认选项添加游戏。如果没有检测到游戏,请查看 ScummVM 维基上的 支持的游戏 页面,以了解特定游戏的数据文件可能需要的特殊说明的细节。

现在唯一要做的就是在 ScummVM 的游戏列表中选择游戏,点击“Start”,享受重温旧爱或首次体验经典冒险游戏的乐趣。


via: https://opensource.com/article/21/4/scummvm-retro-gaming

作者:Joshua Allen Holm 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出