【密码学】全同态加密张量运算库解读 —— TenSEAL

项目地址:https://github.com/OpenMined/TenSEAL

论文地址:https://arxiv.org/pdf/2104.03152v2

TenSEAL 是一个在微软 SEAL 基础上构建的用于对张量进行同态加密操作的开源Python库,用于在保持数据加密的状态下进行机器学习和数据分析。

TenSEAL 库使用了Microsoft SEAL库作为其加密引擎。它提供了一组高级API,可以方便地进行加密、解密及密态操作,如同态加法、同态乘法和同态运算。

TenSEAL 支持多种机器学习算法,包括逻辑回归、线性回归和神经网络等。通过使用TenSEAL,用户可以在保护数据隐私的同时进行分析和计算,而无需担心数据泄漏的风险。

一、项目工程

功能

  • 基于 BFV(Brakerski/Fan-Vercauteren)方案的整数向量进行加密 / 解密;

  • 基于 CKKS(Cheon-Kim-Kim-Song)方案的实数向量进行加密 / 解密;

  • 密文 - 密文向量以及密文 - 明文向量进行逐元素的加法、减法和乘法操作。

  • 点积和矩阵乘法。

  • tenseal.sealapi 封装了完整的 SEAL API。

示例

# pip install tenseal==0.3.15
import tenseal as ts# Setup TenSEAL context
context = ts.context(ts.SCHEME_TYPE.CKKS,poly_modulus_degree=8192,coeff_mod_bit_sizes=[60, 40, 40, 60])
context.generate_galois_keys()
context.global_scale = 2**40v1 = [0, 1, 2, 3, 4]
v2 = [4, 3, 2, 1, 0]# encrypted vectors【编码和加密】
enc_v1 = ts.ckks_vector(context, v1)  
enc_v2 = ts.ckks_vector(context, v2)# 密文 + 密文
result = enc_v1 + enc_v2
result.decrypt() # ~ [4, 4, 4, 4, 4]# 点积:<密文,密文>
result = enc_v1.dot(enc_v2)
print(result.decrypt()) # ~ [10]matrix = [[73, 0.5, 8],[81, -5, 66],[-100, -78, -2],[0, 9, 17],[69, 11 , 10],
]
# 密文向量 * 明文矩阵
result = enc_v1.matmul(matrix)
print(result.decrypt()) # ~ [157, -90, 153]

参数

  • SCHEME_TYPE:ts.SCHEME_TYPE.CKKS。

  • poly_modulus_degree:8192。

  • coeff_mod_bit_sizes:系数模数大小,这里的[60, 40, 40, 60]表示系数模数将包含4个素数,分别为60位、40位、40位和60位。

  • global_scale:缩放因子(scaling_factor),即 2^{40}

(1)缩放因子(scaling_factor

CKKS方案的第一步是将实数向量编码为明文多项式,采用固定缩放因子进行定点运算。 缩放因子指的是编码精度,用数字二进制表示。如下图所示:

scaling_factor 是CKKS中用于将浮点数编码为整数以进行加密的缩放比例因子,用于控制加密方案的计算精度。即是在加密和解密过程中使用的缩放倍数,通常是某个 2 的幂次(如2^{40}2^{50})。它决定了加密时将浮点数扩展为整数时的精度。

的作用是在计算过程中对数据进行缩放,以管理噪声的增长。通过适当的缩放,可以在一定程度上减少噪声对计算结果的影响,从而保持计算的准确性。

精度控制缩放因子越大,计算结果的精度越高。它直接影响浮点数在加密过程中保持的精度,较小的缩放因子可能导致精度损失。

噪声积累较大的缩放因子能减少噪声的相对影响,因为密文的精度更高。然而,如果缩放因子过大,会增加密文大小和计算复杂度。

数值范围缩放因子决定了能表示的数值范围。如果缩放因子太小,可能无法表示足够精确的浮点数;而过大的缩放因子可能导致密文噪声增长过快。

计算精度方面,缩放因子的选择直接影响着计算结果的精度。如果缩放因子选择不当,可能会导致计算结果的精度下降,尤其是在进行多次同态计算后。

计算次数方面,缩放因子与 CKKS 算法能够支持的计算次数相关。不合适的缩放因子可能会导致噪声过快增长,从而限制了能够进行的同态计算次数。例如,如果缩放因子过大,可能会在较少的计算步骤后就使噪声超过可接受的范围,无法继续进行准确的计算。因此,需要根据具体的计算需求和数据特点,合理选择缩放因子,以平衡计算精度和计算次数。

(2)多项式模数次数(poly_modulus_degree

poly_modulus_degree 表示CKKS加密方案中多项式环的维度,即多项式的最大次数。多项式环通常表示为R_q = \mathbb{Z}_q[X] / (X^N + 1),其中 N 就是 poly_modulus_degree

这个参数定义了多项式的最大次数,从而决定了加密数据的 “容量”。较高的poly_modulus_degree可以表示更大范围的数值,但同时也会增加计算复杂度。

它决定了多项式环的维度,即加密方案的基本操作空间,通常取为2的幂(例如 1024、2048、4096、8192 、16384、32768)。

性能和存储开销增大多项式模数次数会增加加密密文的大小和计算的开销,因为多项式操作的复杂度与多项式模数次数成正比。

安全性多项式模数次数越大,安全性越高。通常,较大的值提供更好的抗量子攻击能力,但也需要权衡计算效率。

并行化计算较大的多项式模数次数允许更多的并行计算。

如果选择过大的poly_modulus_degree,可能会导致计算速度过慢,不适合实际应用场景。例如,在某些资源受限的环境中,如移动设备或边缘计算节点,过高的多项式次数可能会使加密计算变得不切实际。

(3)多项式系数模数(coeff_mod_bit_sizes

coeff_mod_bit_sizes 表示CKKS的模数链中每个系数模数的位数(通常以比特为单位)。模数链由多个模数组成,随着每次乘法和重新缩放操作,模数链中的模数逐渐减少。 它是一个列表,表示在模数链中的每个模数的比特大小。例如,[60, 40, 40, 60] 表示模数链有 4 个模数,其中每个模数的比特长度分别为 60、40、40 和 60。

由这个参数决定是一组素数coeff_modulus,决定了"新鲜密文""的噪音预算。coeff_modulus 至少有两个素数组成,最好是少的,最合理的使用2~8个素数,单个素数可以达到60bit,噪音预算和这些素数的总比特呈线性关系。

支持的乘法深度多项式系数模数决定了支持的乘法深度(即能执行的最大乘法次数)。模数链越长,支持的乘法次数越多,但计算开销也越大。

噪声控制每次乘法后,密文的噪声会增加。重新缩放操作减少模数链的长度以控制噪声,因此较大的模数链可以处理更多次乘法。

计算精度模数链的大小决定了运算精度。如果模数链太短,重新缩放后剩余的模数不足以支持高精度运算。

coeff_mod_bit_sizes会影响方案的安全性:如果其他参数保持不变,总比特越大,安全性越低。但是为了获得更大的计算力,也就是说要提升噪音预算,就要增加coeff_mod_bit_sizes的总比特数,所以为了安全性,需要增大poly_modulus_degree,这可能会对批处理的性能产生影响,所以计算性能也会改变。从计算性能角度看,较大的系数模数比特大小会增加计算的复杂性。因为在同态运算中,涉及到对系数的操作,更大的比特大小意味着更多的计算步骤。在安全性方面,系数模数的选择也会影响加密方案的安全性。不合适的系数模数可能会导致加密系统容易受到攻击。因此,在选择coeff_mod_bit_sizes时,需要在计算性能和安全性之间进行权衡。

其中,n表示分圆多项式的度数(poly_modulus_degree),logq表示系数模的比特长度(coeff_mod_bit_sizes的总比特数)。security level表示安全级别。

总结

  • poly_modulus_degree:决定多项式环的维度,影响加密系统的安全性、并行计算能力和性能。

  • coeff_mod_bit_sizes:定义模数链的比特长度,决定加密方案的精度和支持的乘法深度。

  • scaling_factor:控制加密和运算的精度,较大的缩放因子提供更高的精度,但也增加了计算复杂度和密文大小。

这些参数的选择通常需要在安全性、性能、精度和计算深度之间做出权衡。

密钥

  • 公钥:用于加密。

  • 私钥:用于解密,不共享,TenSEALContext对象中保存。

  • 重线性化密钥(Relinearization Keys)【可公开】:用于重线性化(密钥交换),在乘法后用于降低密文维数

  • 伽罗瓦密钥(Galois Keys)【可公开】:用于批处理密文的旋转。批处理向量的旋转的应用是密文求和

默认情况下,会自动执行重线性化后和重缩放。

二、论文解读

摘要

机器学习算法已经取得了显著的效果,并被广泛应用于各个领域。这些算法通常依赖于敏感和私有数据,如医疗和财务记录。因此,进一步关注隐私威胁和应用于机器学习模型的相应防御技术至关重要。在本文中,我们介绍了TenSEAL,这是一个使用同态加密保护隐私数据的机器学习开源库,可以轻松地集成到流行的机器学习框架中。我们使用MNIST数据集对我们的实现进行了benchmark测试,结果显示加密的卷积神经网络可以在不到一秒钟的时间内进行计算,通信量不到0.5MB。

1、介绍

近年来,机器学习狂奔发展。在典型场景中,用户需要将数据发送给服务提供商,服务提供商将对数据执行一些计算并返回结果。这种方法有两个关键问题。首先,出于隐私考虑,用户可能不想将其数据发送给服务提供商。其次,如果用户不向服务提供商发送数据,那服务提供商就无法向用户提供模型。使用同态加密,可以解决该问题,用户的数据将始终加密,服务提供商将看不到输入和输出,并且仍然可以对这些加密数据进行计算。然而,在机器学习中采用同态加密的速度很慢。原因之一,虽然目前可用的密码库为密码学家提供了一个优秀的API,但对于数据科学家来说,使用它们可能具有挑战性。另一个原因,是计算成本,包括通信和计算成本。

贡献
  • 我们提出了一个灵活的开源库,使用同态加密进行密文的张量计算。该库可以直接将张量从当前流行的机器学习框架(如 PyTorch 或 Tensorflow)转换为加密版本。

  • 我们在不到一秒的时间内在加密数据上评估卷积神经网络,推理过程中的通信时间不到0.5MB。

论文的其余部分,我们在第2节中描述了库的架构。在第 3 节中详细介绍在加密空间中计算卷积神经网络所需的算法。在第 5 节中,我们对我们的库进行了实验性测试,并在第 6 节中总结了我们工作的一些局限性。

2、架构

TenSEAL 是一个将经典机器学习框架与同态加密功能联系起来的库。它管理着在加密数据进行张量运算的所有复杂性。TenSEAL 依赖于 Microsoft SEAL 中 CKKS方案的实施。客户端可以使用一种受支持的前端语言(C++ 或 Python)处理明文张量或密文张量。在客户端 - 服务器方案中,消息交换是使用协议缓冲区完成的。核心 API 围绕三个主要组件构建:环境(context)、明文张量和密文张量。

环境 context

TenSEAL的context是库的核心组件。它生成并存储加密计算所需的必要密钥。context生成用于加密的公钥、用于解密的私钥、用于旋转的伽罗瓦密钥以及用于密文重新线性化的重新线性化密钥。

这个context对象还将处理 thread-pool,它控制在执行可并行化操作时应并行运行多少个 job。同时context还可以配置为在计算期间执行自动进行密文重新线性化(relinearization)和重新缩放(rescaling)。

明文张量

明文张量(PlainTensor)是一个将未加密张量与加密实现相连接的类。下图描述了张量的转换过程。

张量(Tensor):

是深度学习中广泛使用的数据结构,本质上就是一个高维的矩阵,甚至将其理解为NumPy中array,Pandas中的DataFrame。

单个元素叫标量(scalar),一个序列叫向量(vector),多个序列组成的平面叫矩阵(matrix),多个平面组成的立方体叫张量(tensor)。在深度学习的范畴内,标量、向量和矩阵都统称为张量。

密文张量

EncryptedTensor 接口提供了一个 API,需要由库公开的每个张量实现。接口有一个 TenSEALContext 对象,这是进行任何同态加密操作所必需的。派生类公开了不同的张量风格,例如:

  • CKKSVector 派生 EncryptedVector 接口,并且可以通过将实数向量加密为单个密文。

  • CKKSTensor 将实数的 N 维张量加密为密文的 N 维张量。但是,它可以批处理轴以及每个密文中可用的槽,因此只需要 (N-1) 维的密文张量。

3、方法

在同态加密方案上构建张量时,需要解决两个重要问题: 1,如何在加密之前对张量进行编码? 2、使用特定编码时可以执行哪些操作?

CKKS 方案的批处理功能允许将一个 N \times N 矩阵加密为 N 个密文,每行或每列为一个密文。另一种可能性是将整个张量加密为单个密文。根据我们将明文张量放入密文的方式,我们可以执行不同的操作,具有不同的复杂度。目标是使用最少数量的密文,并在最小运行时间内具有最大深度,从而优化内存和计算。为了寻求这个理想目标,我们发现我们可以使用单个密文对输入图像进行加密,并在卷积神经网络上对其进行计算。这需要在客户端进行预处理步骤,将图像编码为矩阵,由卷积窗口作为行组成,然后通过垂直扫描将其展平为向量。在 TenSEAL 中,所有这些功能都是围绕 CKKSVector 实现的。一个CKKSVector 包含 N/2个实数值,其中 N 是多项式模数的次数。我们可以与其他加密或明文向量执行逐元素操作(加法、减法和乘法)。我们有一种方法用于计算加密向量的幂(逐元素),该方法使用最优电路,从而使用最小乘法深度。此外,因为我们需要不同激活函数的多项式近似,所以我们构建了一种方法,用于以密文向量作为变量求值多项式,确保使用最小电路。除了逐元素操作外,我们还需要矩阵操作来执行机器学习任务。我们实现了 Halevi 和 Shoup(2014)提出的密文向量与明文矩阵乘法的变体,该变体可以使用多个线程以更快地运行。

A.2

可以查看附录中的表3,以获取库的密文张量支持的操作列表。

点积(dot)

TenSEAL为点积提供了与 Halevi & Shoup(2014)类似的计算方法,但支持的向量大小不是2的幂,或者未填满密文的所有插槽。先前方法中的这一限制是由于右旋转期望最后一个元素为第一个元素,而对于我们处理的情况并非如此。如果向量大小不是 2 的幂,我们的方法在点积数量上受到特定限制。然而,通常不会达到此限制,因为该方案允许的乘法数量可能更低。我们通过将输入向量尽可能多次复制到密文插槽中,并在计算期间仅进行左密文旋转来实现。我们的方法与 Halevi & Shoup(2014)具有相同的算法复杂度。我们使用 CKKS实现了它,用于加密向量与明文矩阵之间的点积运算。因此,它可以扩展为支持加密矩阵与明文矩阵之间的点积(矩阵乘法)。

A.3

附录中的图 3 展示了如何在密文向量与明文矩阵之间执行点积运算:

卷积(conv2d)

TenSEAL还支持计算卷积,即提供当前流行的机器学习框架(例如PyTorch)计算卷积的类似实现。我们使用了Image Block to Columns (im2col)技术,该技术将卷积层转换为单个矩阵乘法运算。这种技术需要密文矩阵乘明文向量,我们通过对矩阵转置与复制的明文向量进行逐元素乘法来实现。最后,将结果旋转并累加到单个密文向量中。

此操作仅使用一个乘法运算和log2(N)个旋转和加法,其中N表示矩阵中的行数。下面解释如何将“图像块-》列”算法应用于加密输入。需要注意的是,转换发生在明文数据中,转换后的输入图像进行编码和加密为单个密文。这直接意味着堆叠两个卷积是不可能的,因为重新组织密文的插槽并非易事。j

A.4

可以使用单个矩阵乘法来执行二维卷积,而不是在每个窗口上重复乘法。这种方法称为图像块到列的卷积( image block to column),或图像到列的卷积(image to column)。下图显示了如何使用此方法执行卷积。它首先将输入矩阵重新组织成表示卷积窗口的行,然后用扁平化的卷积核执行点积,如图4所描述。

将此技术应用于加密矩阵(加密为一个密文)并不是一件小事,因为重新组织slot并不那么简单。我们需要在加密之前将矩阵重新组织为预处理步骤,以便为卷积做好准备。

密文矩阵(输入图像)和 明文向量(kernel)的计算可以通过逐元素乘法和一系列旋转和累加来执行。图5、图6显示了执行此操作的步骤。第一步显示了密文矩阵(彩色)是如何编码并与明文向量(kernel)相乘的。第二步是对向左旋转不同的不同版本的输出求和。

 第4小节:相关工作、第5小节:实验性测试、第6小节:总结 ---- 略

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/58089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聊一聊 C#中有趣的 SourceGenerator生成器

一&#xff1a;背景 1. 讲故事 前些天在看 AOT的时候关注了下 源生成器&#xff0c;挺有意思的一个东西&#xff0c;今天写一篇文章简单的分享下。 二&#xff1a;源生成器探究之旅 1. 源生成器是什么 简单来说&#xff0c;源生成器是Roslyn编译器给程序员开的一道口子&#xf…

单体架构VS微服务架构

单体架构&#xff1a;一个包含有所有功能的应用程序 优点&#xff1a;架构简单、开发部署简单缺点&#xff1a;复杂性高、业务功能多、部署慢、扩展差、技术升级困难 如上示意图&#xff0c;应用前端页面&#xff0c;后台所有模块功能都放在一个应用程序中&#xff0c;并部署在…

Safari 中 filter: blur() 高斯模糊引发的性能问题及解决方案

目录 引言问题背景&#xff1a;filter: blur() 引发的问题产生问题的原因分析解决方案&#xff1a;开启硬件加速实际应用示例性能优化建议常见的调试工具与分析方法 引言 在前端开发中&#xff0c;CSS滤镜&#xff08;如filter: blur()&#xff09;的广泛使用为页面带来了各种…

使用上下文管理器和 `yield` 实现基于 Redis 的任务锁定机制

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

预训练 BERT 使用 Hugging Face 和 PyTorch 在 AMD GPU 上

Pre-training BERT using Hugging Face & PyTorch on an AMD GPU — ROCm Blogs 2024年1月26日&#xff0c;作者&#xff1a;Vara Lakshmi Bayanagari. 这篇博客解释了如何从头开始使用 Hugging Face 库和 PyTorch 后端在 AMD GPU 上为英文语料(WikiText-103-raw-v1)预训练…

Qgis 开发初级 《ToolBox》

Qgis 有个ToolBox 的&#xff0c;在Processing->ToolBox 菜单里面&#xff0c;界面如下。 理论上Qgis这里面的工具都是可以用脚本或者C 代码调用的。界面以Vector overlay 为例子简单介绍下使用方式。Vector overlay 的意思是矢量叠置分析&#xff0c;和arcgis软件类似的。点…

[大模型学习推理]资料

https://juejin.cn/post/7353963878541361192 lancedb是个不错的数据库&#xff0c;有很多学习资料 https://github.com/lancedb/vectordb-recipes/tree/main/tutorials/Multi-Head-RAG-from-Scratch 博主讲了很多讲解&#xff0c;可以参考 https://juejin.cn/post/7362789…

JMeter详细介绍和相关概念

JMeter是一款开源的、强大的、用于进行性能测试和功能测试的Java应用程序。 本篇承接上一篇 JMeter快速入门示例 &#xff0c; 对该篇中出现的相关概念进行详细介绍。 JMeter测试计划 测试计划名称和注释&#xff1a;整个测试脚本保存的名称&#xff0c;以及对该测试计划的注…

【原创】统信UOS如何安装最新版Node.js(20.x)

注意直接使用sudo apt install nodejs命令安装十有八九会预装10.x的老旧版本Node.js&#xff0c;如果已经安装的建议删除后安装如下方法重装。 在统信UOS系统中更新Node.js可以通过以下步骤进行&#xff1a; 1. 卸载当前版本的Node.js 首先&#xff0c;如果系统中已经安装了N…

4.1.2 网页设计技术

文章目录 1. 万维网&#xff08;WWW&#xff09;的诞生2. 移动互联网的崛起3. 网页三剑客&#xff1a;HTML、CSS和JavaScriptHTML&#xff1a;网页的骨架CSS&#xff1a;网页的外衣JavaScript&#xff1a;网页的活力 4. 前端框架的演变基于CSS的框架基于JavaScript的框架基于MV…

【Django】继承框架中用户模型基类AbstractUser扩展系统用户表字段

Django项目新建好app之后&#xff0c;通常情况下需要首要考虑的就是可以认为最重要的用户表&#xff0c;即users对应的model&#xff0c;它对于系统来说可以说是最基础的依赖。 实际上&#xff0c;我们在初始进行migration的时候已经同步生成了相应的user表&#xff0c;如下&am…

spygalss cdc 检测的bug(二)

当allow_qualifier_merge设置为strict的时候&#xff0c;sg是要检查门的极性的。 如果qualifier和src经过与门汇聚&#xff0c;在同另一个src1信号或门汇聚&#xff0c;sg是报unsync的。 假设当qualifier为0时&#xff0c;0&&src||src1src1&#xff0c;src1无法被gat…

xss-labs靶场第十七关测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、注入点寻找 2、使用hackbar进行payload测试 3、绕过结果 四、源代码分析 五、结论 一、测试环境 1、系统环境 渗透机&#xff1a;本机(127.0.0.1) 靶 机&#xff1a;本机(127.0.0.…

Jenkins发布vue项目,版本不一致导致build错误

问题一 yarn.lock文件的存在导致在自动化的时候&#xff0c;频频失败问题二 仓库下载的资源与项目资源版本不一致 本地跑好久的一个项目&#xff0c;现在需要部署在Jenkins上面进行自动化打包部署&#xff1b;想着部署后今后可以省下好多时间&#xff0c;遂兴高采烈地去部署&am…

提升数据处理效率:TDengine S3 的最佳实践与应用

在当今数据驱动的时代&#xff0c;如何高效地存储与处理海量数据成为了企业面临的一大挑战。为了解决这一问题&#xff0c;我们在 TDengine 3.2.2.0 首次发布了企业级功能 S3 存储。这一功能经历多个版本的迭代与完善后&#xff0c;逐渐发展成为一个全面和高效的解决方案。 S3…

python 实现一个简单的浏览器引擎

1. 浏览器引擎工作原理 浏览器引擎是用来处理、渲染和显示网页内容的核心组件。其主要任务是将用户输入的URL所代表的网页资源加载并呈现出来&#xff0c;通常包括HTML、CSS、JavaScript以及各种多媒体内容。浏览器引擎的工作原理可以分为以下几个主要步骤&#xff1a; 1.1 U…

软件系统建设方案书(word参考模板)

1 引言 1.1 编写目的 1.2 项目概述 1.3 名词解释 2 项目背景 3 业务分析 3.1 业务需求 3.2 业务需求分析与解决思路 3.3 数据需求分析【可选】 4 项目建设总体规划【可选】 4.1 系统定位【可选】 4.2 系统建设规划 5 建设目标 5.1 总体目标 5.2 分阶段目标【可选】 5.2.1 业务目…

FlinkSQL之temporary join开发

在实时开发中&#xff0c;双流join获取目标对应时刻的属性时&#xff0c;经常使用temporary join。笔者在流量升级的实时迭代中&#xff0c;需要让流量日志精准的匹配上浏览时间里对应的商品属性&#xff0c;使用temporary join开发过程中踩坑不少&#xff0c;将一些经验沉淀在…

【开源免费】基于SpringBoot+Vue.JS网上超市系统(JAVA毕业设计)

本文项目编号 T 037 &#xff0c;文末自助获取源码 \color{red}{T037&#xff0c;文末自助获取源码} T037&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

研发运营一体化(DevOps)能力成熟度模型

目录 应用设计 安全风险管理 技术运 持续交付 敏捷开发管理 基于微服务的端到端持续交付流水线案例 应用设计 安全风险管理 技术运 持续交付