2024年1月

本文分享自华为云社区《
【标准解读】物联网安全的系统回顾:研究潜力、挑战和未来方向
》,作者:MDKing。

1 引言

内容提要:物联网(IoT)包括嵌入传感器、软件和数据处理技术的物理对象网络,这些物理对象可以通过互联网与其他设备和系统建立连接并交换数据。物联网设备被融入到各种产品中,从普通的家庭用品到复杂的工业电器。尽管人们对物联网的需求越来越大,但安全问题一直阻碍着它的发展。本文系统回顾了IoT安全研究,关注漏洞、挑战、技术和未来方向。它对该领域的171篇近期出版物进行了调查,对物联网的发展现状、挑战和解决方案进行了全面的讨论。本文概述了物联网架构模式和典型特征,评估了现有的限制,并探索了增强物联网安全性的策略。此外,本文还深入探讨了已知的物联网攻击,并讨论了应对这些挑战的安全对策和机制。对物联网安全的功能需求进行了探索,并对相关技术和标准进行了探索。最后,本文讨论了物联网安全的潜在未来研究方向。

随着物联网技术的发展与普及,消费者网络、工业网络、公共网络等都协同物联网基础设置、云计算等完成支撑物联网设备在线化、自动化、智能化的网络闭环。随着全球物联网规模不断扩大,消费时长涌现了大量的物联网应用,由于大多数制造商在这个时期主要追求市场、关注成本,安全的优先级放的比较低,不会在安全上做过多投入,也不会提供响应的安全补丁与更新,导致长期以来积攒了大量的物联网相关的安全漏洞、隐患(如默认密码、明文传输等),物联网安全事件频发的现象也愈发严重。

本文介绍了

  • 物联网架构、基础设施、标准物联网无线技术;
  • 基于该领域171篇同行出版物进行了安全攻击(及其缓解措施)的分类;
  • 物联网安全的挑战与策略;
  • 物联网安全领域未来的研究方向;

2 物联网架构

核心由传感器、执行器、网关、协议、云服务、网络和应用服务器组成。物联网网络需要将所有资源、硬件、软件和系统整合到一个框架中,形成一个集成的、可靠的、高性价比的解决方案。对于不同的物联网应用领域,由于其业务、功能、实现、基础设置的质量等的不同,架构层的复杂度与数量也会不同,但是大致是符合三层或者五层架构规律的。三层是五层的子集。五层架构具体为:

  • 感知层:也成为传感器层,使用传感器或者嵌入式系统来识别物体并从他们中收集数据。攻击者会热衷于使用对齐进行攻击,使用攻击者的传感器进行替代。
  • 网络层:以有钱或者无线的方式承载与传输传感器收集到的数据。还跟各种只能对象、网络设备以及服务器进行连接。与信息认证、完整性相关的安全问题发生在这一层。
  • 中间件层:中间件或者服务管理层具有数据存储、计算、处理和分析等功能。该层通过对接收到的数据进行处理来做出决策,并根据设备地址和名称提供相应的服务。
  • 应用层:管理所有的基于从中间件层获取的信息的应用进程。该层对接IoT设备、网络、用户交互。为用户提供高质量的满足需求的应用服务。例如,包括智能家居、智能交通、工业自动化等垂直市场。
  • 业务层:管理整个IoT系统,构建流程图、图形、分析结果、IoT设备改进。它对底层的四层进行监控和管理,将每一层的输出与预期进行比较,以确保数据的一致性和有效性,从而改善服务,维护用户隐私。

3 IoT无线技术

LPWAN:低功耗广域网提供了运行在小型、廉价电池上的(可使用数年)大规模物联网网络所需的低功耗、低成本、长距离通信的收发器。连接适合低频、低速传输数据,低移动性设备的场景。该系列技术专为支持大型工业和商业园区的大规模物联网网络而建,应用包括消耗品监控、环境监测、占用检测与资产跟踪。LPWAN包含不同的技术和相互竞争的标准。技术在授权(例如NB-IoT、LTE-M)和非授权(例如MYTHING、LoRa、Sigfox)频谱中运行,在关键网络因素上表现不同。例如,可扩展性和服务质量对于非授权技术和授权LPWAN的功耗可能是重大问题。

蜂窝(3G/4G/5G):为移动消费市场提供可靠的宽带通信,支持各种语音、视频流应用。这些无线技术具有较高的功耗、运营成本,适用无电池供电的传感器网络应用(例如交通路由和车队远程信息处理)。蜂窝连接作为一个出色的回传,使用LPWAN连接到物联网设备和传感器,然后蜂窝网络连接到云端以提供物联网数据,这使得它们成为特定用例的理想选择,如互联汽车或运输和物流车队管理。此外,NB-IoT和LTE-M等新型蜂窝技术旨在通过降低每个传感器的功率要求和数据成本来支持不同的物联网应用。此外,这些支持NB-IoT的设备将从远程位置提供定期更新,同时确保低功耗。

Wi-Fi:无线保真(WiFi)为附近特定范围内的设备提供互联网连接。另一种方式是创建热点,手机或电脑可以通过广播信号与其它设备共享无线或者有线互联网连接。WiFi使用无线电波以特定频率广播信息,其互联网连接的范围和速度取决于环境和它提供的内部或外部覆盖范围。与其他无线技术的一个关键区别是,Wi-Fi以更高的频率传输,这意味着它可以承载更多的数据。但Wi-Fi对功率要求高,覆盖范围有限。这些问题和可扩展性限制使得Wi-Fi在物联网领域不那么受欢迎。此外,由于高能耗要求,Wi-Fi通常不是电池供电的物联网传感器的大型网络的可行解决方案,尤其是在工业物联网和智能建筑场景中。相反,它更适合连接容易连接到电源插座的设备,例如智能家居小工具和电器、数字标牌或安全摄像头。

Zigbee和其他网状协议:ZigBee协议采用802.15.4标准,是一种低功耗、高可靠性的无线网络技术,设计用于短期通信,通常通过在多个传感器节点上中继传感器数据来部署在网状拓扑中。与LPWAN相比,Zigbee提供了更高的数据速率,但同时,由于网状配置,它的能效要低得多。由于其物理距离短(<100米),Zigbee和类似的网状协议(例如,Z-Wave、Thread)非常适合于均匀分布在节点附近的终端物联网应用。因此,Zigbee是家庭自动化应用的绝佳选择,如HVAC控制、智能照明、智能电表、家庭能源、安防监控和智能温控器。此外,Thread专为智能家居产品而设计,并具有IPv6连接功能,可使连接的设备通过Thread移动应用程序进行通信、访问云中的服务或与用户进行交互。

蓝牙和BLE:蓝牙是一种允许各种电子设备无线连接的技术,是IEEE 802.15.1规范【30】中描述的开放标准。为了将蓝牙的应用扩展到无线传感器等功率受限设备,低功耗、灵活性和可扩展性的低功耗蓝牙(BLE)于2010年推出。经典蓝牙最初旨在用于消费设备之间的点对点或点对多点数据交换。低功耗蓝牙针对功耗进行了优化,后来推出来解决小型消费类物联网应用。与Wi-Fi不同,BLE协议是一种高带宽、低范围的无线连接选项,其设计具有成本效益和更低的功耗,只需极少的设备功耗。这项技术经常被用于健身和医疗可穿戴设备(例如,智能手表、血糖仪、脉搏血氧仪等)和智能家居设备(例如,门锁),数据可以很容易地传输到智能手机上并存储在智能手机上。但是,当频繁传输大量数据时,BLE可能不是最有效的解决方案。

RFID:射频识别(RFID)是一种利用无线电波识别和寻找物体的无线通信技术。它包括一个RFID标签、阅读器、天线和后端数据库服务器。RFID阅读器将无线电波转换为数据形式,然后转发到后端服务器,供用户访问和分析数据。RFID使用无线电波在短距离内将少量数据从RFID标签传输到阅读器,为物联网应用提供了定位解决方案。这种物联网无线技术在看不见的情况下工作,并附有标签,在英寸甚至米内即可读取。该技术主要应用于供应链管理和物流。通过将RFID标签链接到各种产品和设备,公司可以实时跟踪其库存和资产,从而实现更好的库存和生产计划以及优化的供应链管理。

4 物联网安全漏洞/缺陷

问题主要特点有:

  • 缺乏内置的安全措施;
  • IoT设备的受限环境与有限的计算能力;
  • 低功耗的设备无法适应强大的安全机制与数据保护;
  • 种类繁多的传输技术导致标准化保护方案和协议难建立;
  • 关键组件存在漏洞;
  • 用户意识不足。

加密不当:保护静态、传输中或处理期间的物联网数据对物联网应用的可靠性和完整性非常重要。尽管许多IoT供应商专注于安全存储,但确保数据在传输中保持安全却经常被忽视。传输中缺乏加密涉及设备与云之间、设备与网关之间、设备与移动应用之间、一个设备与另一个设备之间以及网关与云之间的通信不安全。由于加密算法的强度会受到物联网应用的资源限制的影响,攻击者可以利用加密算法的漏洞泄露敏感信息或控制操作。在整个物联网数据生命周期中进行强加密将有助于保护物联网数据免受损坏和破坏。

认证机制不充分:由于有限的能源和算力限制,在物联网设备上实现复杂的认证机制并不容易。目前支持物联网系统认证的协议有消息队列遥测传输(MQTT)、数据分发服务(DDS)、Zigbee和Zwave。然而,即使开发人员提供了物联网通信、配对和消息传递所需的身份验证工具,物联网设备和网络通信仍有被劫持的机会。例如,认证密钥由于没有安全存储或传输而存在丢失、破坏或损坏的风险。

不正确的补丁管理功能:保持物联网操作系统和嵌入式固件/软件的更新和修复非常重要。随着时间的推移,物联网设备系统中会出现安全漏洞,从而使物联网设备易受攻击。因此,物联网设备需要使用没有已知漏洞的最新系统,并且系统必须具有更新功能,在设备部署后修补任何已知漏洞。此外,网络管理员还应注意更新机制。

访问控制不足:访问控制是连接的物联网设备的一组权限,用于指定哪些用户被授予访问权限,以及允许他们执行的操作。访问控制攻击是指未经授权的用户访问物联网网络。攻击者可以利用ACL(Access Control List)中的漏洞访问机密信息,使个人和组织面临数据泄露的风险。

安全可配置性不足:由于在物联网设备中经常使用硬编码的凭证,它导致安全可配置性不足。弱密码、默认密码和硬编码密码是攻击者入侵物联网设备并进一步发动大规模僵尸网络和其他恶意软件的最简单方式,导致硬编码凭证很容易被破坏。此外,物联网设备附带默认的硬编码设置。因此,一旦这些设置被破坏,攻击者就可以窃取硬编码的默认密码、隐藏的后门以及设备固件中的漏洞。

物理安全不足:物理安全不足是由硬件造成的安全漏洞。由于物联网设备部署在分布式远程环境中,攻击者可以访问和篡改物理层,获取敏感信息,中断物联网设备提供的服务。此外,由于传感器等物联网设备的简单性,在这些物联网设备上构建完整的加密算法并不容易。但是,可以在物联网设备中实施轻量级加密,以确保用户的机密性和安全性。

不必要的开放端口:物联网设备在运行易受攻击的服务时,会开放一些不必要的端口。攻击者可以利用这些端口漏洞访问物联网设备中的敏感信息。

能源获取不足:由于IoT设备的能源有限,攻击者可能会通过生成大量合法或损坏的消息耗尽IoT设备存储的能源,从而使设备对有效进程或用户不可用。

审计机制不足:大多数物联网设备没有完整的日志记录程序,导致物联网设备或服务中产生的恶意活动被隐藏。

5 物联网安全攻击分类

物联网系统的通信架构由感知层、网络层、中间件层和应用层组成。这四层在功能上发挥着不同的作用,本节将这四层中各种可能的物联网攻击进行分类。

感知层

恶意节点攻击:恶意节点是拒绝为网络中其他节点提供服务的节点,其目的是攻击网络中的其他节点或整个网络。恶意节点会通过篡改、重传、丢弃等方式进行攻击。业界专家提出了基于在线学习算法的恶意节点信任检测机制、基于人工神经网络(ANN)的恶意节点检测方法(分类成功率为77.51%)。

边信道攻击(SCA):可用于从设备检索任何敏感信息。敏感信息的泄露可能与时间、功率、电磁信号、声音、光线等因素有关。SCA是一种非侵入式和被动式攻击,在不移除芯片的情况下执行,以获得对设备内部组件的直接访问或主动篡改其任何操作。SCA最常用于针对加密设备。SCA不是针对标准加密算法,而是针对它们在物理设备上的实现,通过测量和分析泄漏的信息(如功率分析、时序分析、电磁分析等)来恢复保密的参数。

虚假数据注入攻击:攻击者可以利用劫持的节点向物联网系统注入错误数据,从而破坏数据完整性。此攻击可导致物联网系统崩溃或故障。或者,攻击者也可以利用这种方法进行DDoS攻击。

窃听/嗅探攻击:窃听也称为嗅探攻击,利用不安全的网络流量访问用户发送或接收的数据。由于执行攻击时网络流量似乎正常,因此很难检测到。此外,它通常发生在无保护或未加密的网络上,攻击者通过在客户端和服务器上安装网络检测嗅探器来截获数据。窃听可能导致个人或组织的重要隐私信息丢失或被截获,存在财务损失和身份被盗的风险。

硬件故障:由于物联网设备用于大多数物联网应用,例如智能家居、智能电网、智能医疗等,因此保护它们免受物联网攻击至关重要。一旦这些设备出现产品故障或遭受任何形式的网络攻击,将严重影响设备系统和用户的生活。有业界专家提出了一种在不干扰IC涉及的情况下使用功率分析、网络流量数据检测恶意活动的技术,可以有效地防止IC设计和测试过程中基于HT的攻击。作者研究了五种随机攻击的IoT-ED行为:隐蔽信道、DoS、ARQ、电力耗尽和模拟攻击。结果表明,所提出的技术可以在不需要设计时干预的情况下,以高达99%的准确率单独检测每个攻击。此外,该技术可以以92%的准确率同时检测所有攻击。

电池耗尽攻击:攻击者通过不断发送请求耗尽资源受限的物联网设备的电池电量,从而导致物联网应用中的节点因电池电量耗尽而拒绝服务。此外,攻击者可以通过使用恶意代码在IoT设备中运行无限循环来耗尽设备的电池,或者人为地增加IoT设备的功耗,以防止设备进入睡眠或省电模式。

对设备的未授权访问:由于物联网设备的数量和种类不断增长,以及生产者使用默认密码和内置凭证,物联网设备容易受到无人值守的攻击。此外,开发人员故意将不安全的API留给远程访问,并忽略定期的系统审计,对物联网设备构成了安全威胁。

网络层

身份仿冒攻击:是一种攻击者伪装身份,通过身份验证获取信任的攻击方法。攻击者利用身份验证机制中的缺陷将自己伪装成他人,并使用各种方法和技术窃取受害者的敏感信息。欺骗攻击包括电子邮件欺骗、DNS欺骗、IP欺骗、DdoS欺骗和ARP欺骗。

路由攻击:路由攻击是指通过发送伪造的路由信息,产生错误的路由,干扰正常的路由。路由攻击有两种类型。一种是通过伪造带有错误路由信息的合法路由控制报文,在合法节点上生成错误的路由表项,增加网络传输成本,破坏合法路由数据,或者将大量流量引向其他节点,快速消耗能量。另一种攻击是伪造带有非法头域的数据包。

恶意节点攻击:恶意节点是拒绝为网络中其他节点提供服务的节点,其目的是攻击网络中的其他节点或整个网络。恶意节点会通过篡改、重传、丢弃等方式进行攻击。业界专家提出了基于在线学习算法的恶意节点信任检测机制、基于人工神经网络(ANN)的恶意节点检测方法(分类成功率为77.51%)。

窃听/嗅探攻击:窃听也称为嗅探攻击,利用不安全的网络流量访问用户发送或接收的数据。由于执行攻击时网络流量似乎正常,因此很难检测到。此外,它通常发生在无保护或未加密的网络上,攻击者通过在客户端和服务器上安装网络检测嗅探器来截获数据。窃听可能导致个人或组织的重要隐私信息丢失或被截获,存在财务损失和身份被盗的风险。

分布式拒绝服务(DDos)/Dos攻击:使用多台/单台计算器或机器来泛洪目标资源,直到目标流域流量过载而无法响应正常请求或者崩溃,从而阻止合法用户访问预期的服务或者资源。

中间人(MITM)攻击:中间人(Man-in-the-Middle,MITM)攻击的目标是捕获和修改两个独立系统之间的通信,并截获其中的信息。由于物联网设备实时共享数据,因此MITM攻击可以同时攻击多个物联网设备,导致严重的故障。常见的MITM攻击类型包括电子邮件劫持、Wi-Fi窃听、会话劫持和域名系统(DNS)欺骗。

访问控制攻击:访问控制(Access control)是连接物联网设备的一组权限,用于指定哪些用户被授予访问权限,以及允许他们执行的操作。访问控制攻击是指未经授权的用户可以访问物联网网络。攻击者可以利用ACL(Access control List)中的漏洞访问机密信息,使个人和组织面临数据泄露的风险。

中间件层

中间人(MITM)攻击:中间人(Man-in-the-Middle,MITM)攻击的目标是捕获和修改两个独立系统之间的通信,并截获其中的信息。由于物联网设备实时共享数据,因此MITM攻击可以同时攻击多个物联网设备,导致严重的故障。常见的MITM攻击类型包括电子邮件劫持、Wi-Fi窃听、会话劫持和域名系统(DNS)欺骗。

SQL注入攻击:随着SQL驱动的物联网应用的快速增长,中间件层的SQL注入攻击(SQLIA)威胁显著增加。SQL注入(SQLi)是一种针对使用SQL的数据库的网络攻击。该攻击通过向应用程序中注入恶意SQL语句来干扰或操纵数据库,并获得对潜在有价值的信息的访问。

泛洪攻击:泛洪攻击是DoS攻击的一种,其目的是向特定设备发送一系列数据包请求,使目标服务器泛洪,从而消耗其资源,使其无法处理来自合法用户的请求。

云恶意软件注入:云恶意软件注入攻击将恶意代码或虚拟机注入到云中。攻击者通过尝试创建虚拟机实例或恶意服务模块来伪装成合法服务,然后设法获得来自受害服务的服务请求的访问权限,并捕获敏感数据。

签名包装攻击:在签名包装攻击中,攻击者通过破坏签名算法或利用SOAP(Simple Object Access Protocol)中的漏洞来执行或修改窃听消息。

应用层

虚假数据注入攻击:攻击者可以利用劫持的节点向物联网系统注入错误数据,从而破坏数据完整性。此攻击可导致物联网系统崩溃或故障。或者,攻击者也可以利用这种方法进行DDoS攻击。

分布式拒绝服务(DDos)/Dos攻击:使用多台/单台计算器或机器来泛洪目标资源,直到目标流域流量过载而无法响应正常请求或者崩溃,从而阻止合法用户访问预期的服务或者资源。

身份仿冒攻击:是一种攻击者伪装身份,通过身份验证获取信任的攻击方法。攻击者利用身份验证机制中的缺陷将自己伪装成他人,并使用各种方法和技术窃取受害者的敏感信息。欺骗攻击包括电子邮件欺骗、DNS欺骗、IP欺骗、DdoS欺骗和ARP欺骗。

访问控制攻击:访问控制(Access control)是连接物联网设备的一组权限,用于指定哪些用户被授予访问权限,以及允许他们执行的操作。访问控制攻击是指未经授权的用户可以访问物联网网络。攻击者可以利用ACL(Access control List)中的漏洞访问机密信息,使个人和组织面临数据泄露的风险。

暴力/字典攻击:暴力攻击使用试错来破解密码、登录凭证和加密密钥,从而允许对个人账户以及组织的系统和网络进行未经授权的访问。攻击者通过在计算机上测试各种用户名和密码来获取用户的登录信息。字典攻击是暴力破解攻击的一种基本形式。与暴力破解攻击(攻击者只攻击单个用户)不同,字典攻击会破坏密码数据库的加密,从而获得对所有服务或网络用户帐户的访问权限。攻击者选择一个目标,并通过遍历字典并使用特定字符或数字修改单词来针对该个人的用户名测试可能的密码。

其它(网关)

后门接口:攻击者利用IoT网关的额外端口进行后门认证,导致用户信息泄露。因此,物联网网关制造商应仅实现必要的接口和协议,并限制最终用户使用的服务和功能。

端到端加密:Suresh和Priyadarsini 提出了一种增强的现代对称加密方法来保护数据,以确保在云端物联网数据传输和存储中的数据安全。提出的增强型现代对称数据加密(EMSDE)是一种使用单个密钥加密和解密数据的分组密码加密技术,旨在保护基于云的物联网环境中的数据。结果表明,与其他现有加密技术相比,提出的EMSDE需要更少的加密和解密时间,并且它是专门为保护存储在云中的数据免受物联网设备的侵害而量身定制的。

固件更新:由于大多数物联网设备都是资源受限的,因此它们没有用户界面或计算能力来下载和安装固件更新。但是,物联网网关可用于下载和应用固件更新。因此,请确保物联网网关下载当前版本和新版本的固件,并检查签名的有效性。

6 当前物联网的安全对策

针对IoT安全挑战与机制,对当前的IoT安全解决方案进行分类

应对IoT安全挑战的安全对策

数据安全相关:由于物联网设备的不断增加,产生了大量的数据,其中不乏个人信息等机密数据,会带来敏感数据丢失等安全问题。因此,物联网设备和服务需要正确、安全地处理敏感数据,同时保证传输数据的机密性和真实性。密码学是解决这一挑战的有效方法。数据加密和解密可以确保数据的隐私和机密性得到保护,并将数据被盗的风险降至最低。

对称密钥加密:也称为秘密密钥加密,其中消息的发送者和接收者使用相同的密钥对消息进行加密和解密。它是一种简单的加密形式,但问题是发送方和接收方必须安全地交换密钥,以避免密钥被泄露。

非对称密钥密码学又称公钥密码学,使用一对密钥(公钥和私钥)对消息进行加密和解密。公钥用于加密,私钥用于解密。与对称密钥密码不同的是,即使使用公钥进行加密,也没有办法用它来解密消息,只能使用私钥来解密消息。而且,私钥不能从公钥推导出来,但公钥可以从私钥推导出来。私钥不应该被分发,而只保留给所有者。公钥可以在网络上共享,因此可以通过公钥传输消息。

哈希函数:是不可逆的单向函数,算法不使用任何密钥。它将给定的字符串转换为固定长度的字符串,使明文内容不可恢复。它是安全的,因为破解哈希的唯一方法是尝试所有可能的输入,直到攻击者得到相同的哈希。业界专家提出了混合密码系统、新颖的随机秘钥技术(在物联网设备之间共享一个随机矩阵)等为物联网系统提供更适合的加密算法。

身份验证和访问控制:物联网设备的认证和访问控制是物联网的安全挑战之一。如果IoT设备在没有正确认证的情况下接入IoT网络,则IoT设备可能成为攻击者的目标,从而危害系统。因此,物联网设备应严格规范远程和直接服务器访问,防止未经授权的访问。

  • 业界专家提出了一种呼和访问控制(HAC)模型,通过将新的属性插入到基于角色的访问控制(RBAC)实体中,实现了角色级别上对COI(动态权益冲突)的有效处理。

弱口令:弱口令可能导致物联网设备受到安全攻击。易受攻击的密码包括人类经常使用的默认密码,存在安全隐患。因此,需要一种可靠的密码管理机制来降低弱口令带来的安全风险。一种解决方案是将密码设置为区分大小写的混合字符,个人应避免在不同的设备上使用相同的密码。此外,重要设备上的密码需要经常修改。

  • 业界专家提出了一种基于图形的密码方案,使用网格图和眼睛凝视来推断文本密码、无需接触用户界面。该方案有易于记忆、不易被破解、资源消耗最小、随机性强、可更改等优点。

安全更新机制缺失:保持物联网设备的更新和维修非常重要。随着时间的推移,物联网设备系统中会出现安全漏洞,从而使物联网设备易受攻击。它要求物联网设备使用最新的系统,没有任何已知的漏洞,并且系统必须具有更新功能,以在设备部署后修补任何已知的漏洞。此外,网络管理员还应注意更新机制。

安全设备机制缺失:物联网设备的安全挑战包括受限设备、未授权设备和使用不支持的旧操作系统。旧的遗留系统和连接设备(如患者监护仪、呼吸机、输液泵和恒温器)的组合具有非常差的安全功能,特别容易受到攻击。受限设备是指CPU、内存和电源资源有限的小型设备。它们可以组成一个网络,其中它们被称为约束节点。通常,这些受限节点通过低功耗无线协议(如BLE)进行通信。

恶意软件和勒索软件:黑客可以通过发现物联网网络中的漏洞,并将其与恶意软件或勒索软件相结合来发动勒索软件攻击。在勒索软件攻击中,黑客控制系统或加密有价值的信息,然后向受害者索要赎金。

  • 业界专家提出了一种基于可打印字符串的跨平台物联网恶意软件分类方法,通过不同的特征选择方法获得有用的特征,使用一组ML算法对恶意软件进行分类,训练集上有98%的准确率。
  • 业界专家提出了一种基于CNN模型的物联网恶意软件检测动态分析,旨在减轻恶意软件对物联网是被的损害,在嵌套的云环境中动态分析物联网恶意软件,并使用调试、特征提取、特征预处理、特征选择和分类来训练、验证和测试以创建推荐模型。能够准确地检测出具有多种智能攻击技术的新型和变种物联网恶意软件。

物联网安全机制的安全对策

物联网安全中的机器学习(ML):通过使用复杂的算法分析大量数据,ML可以构建模型并预测研究对象的未来行为。ML架构一般分为三种,即监督学习、无监督学习和强化学习。对于将ML应用于物联网安全的研究兴趣激增。

物联网安全中的边缘计算:边缘计算使用云的概念,将边缘服务器放在最终用户和云服务器之间,在数据源或附近进行计算,而不是依赖云来完成所有工作。边缘计算解决了云计算的时延、通信速度等问题。边缘的近即时计算和分析减少了延迟,从而大幅提高了性能,而且边缘计算可以处理大量数据,这些数据不再需要昂贵的带宽,从而降低了云服务的负载和成本。此外,边缘计算还可以分析私有网络中的敏感物联网数据,以保护这些数据.

  • 业界专家借助边缘计算提出了自动平衡功耗来节能的方案;自动检测缓解欺骗攻击和网络入侵攻击的方案;轻量级边缘服务器身份认证的方案等来解决IDS、网络性能、功耗、欺骗攻击、网络入侵、认证等物联网安全问题.

物联网安全中的云计算:云计算是一种基于应用的软件基础设施,可以通过互联网向云数据中心传输和存储数据。云计算是一种按需计算服务,允许用户轻松访问集中式云系统中的数据和程序。云计算架构包括前端和后端两个基本组件。在云计算架构中,前端作为客户端工作,通过互联网与后端通信。服务提供商使用后端管理云计算服务所需的所有资源,包括大容量数据存储设备、安全机制、虚拟机、服务器、流量控制机制等。云计算可以分为三种模式,即基础设施即服务(IaaS)、平台即服务(PaaS)和软件即服务(SaaS)。

  • 云计算是物联网的重要组成部分,它聚合服务器,分析从传感器获得的信息,提高处理能力,并提供良好的存储容量[12]。云计算为用户提供了强大的安全措施。云计算系统可以对用户的访问进行管理和验证,防止数据泄露。此外,云计算还可以实现数据加密和身份验证程序,以防止未经授权的用户访问物联网设备或网络
  • 云计算可以解决DoS攻击、访问控制、欺骗攻击、DDoS攻击、数据完整性、认证授权等物联网安全问题。

区块链在物联网安全中的应用:区块链系统的核心由系统参与者共享的分布式数字分类账组成,该分类账驻留在互联网上。已验证的交易或事件记录在台账中,不可修改或删除。此外,区块链允许用户社区记录和共享信息。区块链提供强大的数据篡改保护,锁定对物联网设备的访问,并允许关闭物联网网络中的损坏设备。

  • 区块链可以解决数据完整性、隐私保护、安全通信、数据保密、安全存储、认证、访问控制等物联网安全问题。

7 未来研究方向

网关安全措施增强:物联网设备通过网关接入互联网,但由于网络管理内部缺乏完善的安全机制,如缺乏认证认证等,需要在这些网关上实施更多的安全措施,以提高物联网系统的整体安全性。

通过机器学习、区块链技术探索系统吞吐量和共识算法问题:由于连接的物联网设备数量众多,需要考虑系统吞吐量和共识算法问题。否则会降低系统处理效率,导致物联网设备无法正常工作。可以探索机器学习和区块链技术来解决这些问题。

轻量级加密安全协议:为了满足物联网设备的资源约束,安全协议需要设计轻量级的加密方案,并考虑物联网的可扩展性。

轻量级认证:轻量级认证也是未来安全研究方向之一。这一点非常重要,因为验证用户身份可以避免敏感数据泄露并提高物联网网络性能。

生物识别认证机制:生物识别安全是一种身份验证机制,它使用人类的生理或行为特征来验证个人的身份。未来的研究需要考虑使用生物识别技术对用户进行身份验证的成本效益以及生物识别技术的稳定性。

打造物联网安全技术标准生态圈:打造物联网生态圈,推动物联网安全技术标准和合规。此外,研究人员还需要考虑提高物联网应用的安全算法的计算速度,以及考虑授权和访问控制。

物联网隐私数据存储安全:另一个未来的研究方向是保护物联网数据存储的安全。使用基于云计算和区块链的解决方案是解决这一问题的方法之一。由于区块链中的交易是公开的,因此在未来的研究中需要考虑个人隐私问题。此外,还需要考虑使用云计算的成本。

边缘计算的能耗平衡:使用边缘计算可以缓解欺骗攻击,但在未来的研究中需要考虑边缘物联网设备有限的功率容量,因为攻击者可以在CPU上执行大量操作以缩短电池寿命。

8 结论

这篇调查文章详细介绍了物联网,分析了物联网架构、基础设施和无线技术。此外,本文还介绍了当前的安全漏洞和缓解策略。此外,文章还分析了针对不同层次的常见物联网安全攻击,并研究了当前针对这些攻击的解决方案。为了解决IoT的安全问题,本文介绍了IoT的安全目标,并根据挑战和机制对现有的解决方案进行了分类。本文介绍了这些解决方案的详细架构,以及它们如何解决IoT安全挑战,并对这些解决方案进行了比较。最后,详细讨论了提高物联网安全的未来研究方向,有助于进一步开展物联网安全研究,为个人和组织提出新技术和解决方案奠定基础。

点击关注,第一时间了解华为云新鲜技术~

作者:来自 vivo 互联网中间件团队

本文根据罗亮老师在“2023 vivo开发者大会"现场演讲内容整理而成。公众号回复【2023 VDC】获取互联网技术分会场议题相关资料。

vivo微服务平台为全球5亿+用户背后的全网十万级机器、万级微服务提供服务,在高效实践过程中,vivo中间件平台团队输出了一套业务适用的微服务架构最佳实践--架构能力矩阵、高效的开源中间件组件全生命周期管理策略,走出了一条从开源到开源+自研的技术演进路径,通过微服务引擎升级和统一平台建设较好解决了面临的问题与挑战。

一、vivo 从 0 到 1 的微服务架构工程实践

1.1 为什么需要微服务及落地挑战

伴随业务的高速发展,业务的复杂度越来越高,用户规模和访问量也越来越大;项目的迭代速度越来越快,交付效率要求也越来越高。与此同时,服务的集群规模越来越大,部署架构越来越复杂,故障范围也越来越不可控。此外,突增的业务流量时刻考验着服务的水平扩容能力,创新业务的快速孵化也对服务的可扩展性提出了更高的要求。想要解决以上问题,业务架构会朝着微服务架构方向演进。

图片

正是在这样的背景下,vivo于2015年开始微服务架构改造,在落地过程中碰到了以下问题:

一是
:服务数量多,配置修改生效、服务发布等变更场景效率低下;

二是
:业务链路长,高可用保障难,问题与故障定位耗时长,服务的维护成本高;

三是
:大量的跨服务通讯,性能和访问体验优化提升难度大;

四是
:一个业务链路涉及大量的上下游团队,对接沟通的协作成本高;

为了解决以上落地过程中的开发、运维、团队协作等难题,我们需要建设配套的微服务架构技术体系。

1.2 vivo 微服务架构最佳实践-架构能力矩阵

建设一套微服务架构技术体系,助力业务又快又好地构建微服务工程,需要哪些技术能力?我们对微服务架构的主要业务场景进行了分析,在业务实践过程中,微服务主要会涉及同步、异步、定时任务三大核心业务场景。

图片


同步调用
场景:涉及的技术能力主要是RPC框架、注册中心、服务治理;


异步调用
场景:涉及的技术能力主要是消息中间件;


定时任务
场景:涉及的技术能力主要是分布式任务调度。

除了上面介绍的框架和系统,业务在微服务架构改造过程中,需要的能力全貌是怎样的?

在深度参与业务微服务架构改造过程中,我们对最佳实践能力项进行了抽象,从而形成了vivo内部的微服务架构最佳实践总结-架构能力矩阵,总计近30项能力。为了更直观的呈现这些能力,我们从接入层、服务层、数据层的三层架构分层,开发、运维等DevOps的关键环节对架构能力进行了梳理,如下图所示。

图片

在开发环节:

  • 在开发接口时
    ,我们要实现内外网接口分离,保障接口的安全性,为此我们要接入网关来隔离内外网接口;在接入层和服务层,我们可以通过治理平台来实现限流、熔断、降级等能力,保障业务的高可用。

  • 在构建内部服务时
    ,我们要尽可能实现服务无状态,通过RPC框架实现内部接口的RPC相互调用,具备异常重试能力,提升服务的鲁棒性;在编码过程中,我们通过接入配置中心实现代码与配置分离,具备运行时动态调整配置的能力,提高服务的变更效率。

  • 在异步调用场景
    ,我们可以通过接入消息中间件实现业务间的相互解耦、流量削峰;在定时任务场景,我们可以通过分布式任务调度系统,实现失败任务的自动转移能力。

  • 此外,我们可以通过落地存储与计算分离能力,实现服务层和数据层的解耦,便于分层扩容,具备面向未来更大规模业务的扩展能力。

  • 在数据层
    ,通过落地读写分离、冷热分离等能力,提升系统性能,节省存储成本;同时将这些能力通过研发框架进行封装,便于业务侧复用。

在运维环节:

  • 我们可以借助CDN实现网站的动静分离访问,减小系统的请求压力;在日常运维过程中,我们要实现服务的可灰度、可回滚;服务节点无单点;同时借助容器技术快速实现弹性伸缩能力;提升系统的故障恢复速度。

  • 在部署时
    ,通过部署与发布分离,可以较好规避发布变更时产生的问题,即服务部署成功,并且健康检查通过后再发布到生产环境,减小故障的影响范围。

  • 在遇到严重的系统故障时
    ,需要具备使用备份数据从零恢复的能力,同时对所有已知的故障场景要有对应的预案,提升系统的故障应对能力。

  • 在数据运维上
    ,我们要确保数据属主唯一,避免多个业务对同一个数据库进行访问;同时也要实现业务数据和大数据的存储隔离,避免相互影响。

除了以上能力之外,我们
还要
实现业务的安全合规,建设覆盖Metric、Trace、Log的可观测能力体系,便于对故障问题的定位排查;在多机房层面,需要具备同城双活、异地多活等跨机房容灾能力。

1.3 vivo 微服务平台能力

为了更好落地以上最佳实践,我们构建了一套从接入层、服务层、消息层、框架层到存储层的平台能力,完整的平台能力地图如下图所示:

图片


接入层
,我们提供了四层流量网关和七层微服务API网关;在服务层提供了服务/流量治理平台、配置中心、注册中心、接口管理平台、分布式任务调度等系统。


消息层
提供了消息中间件;在框架层提供了脚手架,可快速集成日志、配置、限流/熔断、MySQL/Redis等SDK,以及RPC框架。


存储层
提供了DaaS平台,包含MySQL、Redis、ElasticSearch、MongoDB、文件服务等系统能力。

为了更好排查故障问题,我们在可观测领域构建了监控中心、日志中心、调用链等系统;此外,还有更好支撑服务构建、变更发布的CICD系统和IT基础设施的配置管理系统CMDB。

截止2019年,vivo基本完成了从0到1的微服务平台能力烟囱式建设。

快速构建这些能力的过程,离不开开源组件的赋能。例如微服务API网关背后的zuul,注册中心背后的ZooKeeper和etcd,RPC框架的Dubbo和bRPC;配置中心的Apollo和Nacos,流量治理的hystrix和sentinel,消息中间件的RabbitMQ和RocketMQ,任务调度的xxl-job;如下图所示。

图片

在此,我们也通过VDC(vivo 开发者大会)平台,感谢开源社区的赋能,助力vivo微服务架构技术体系从0到1的快速构建。

1.4 vivo 微服务现状

截止当前,vivo的微服务平台为全球分布在60+个国家/地区的5亿+用户提供服务;其中vivo现有万级的微服务,覆盖全网机器规模十万级,每天处理高达8000亿次的RPC调用次数,流量的峰值QPS达到千万级以上。

图片

在支撑如此规模的微服务过程中,特别是在2020年以后,我们碰到了较多的问题与挑战,为了解决这些问题,我们使用了微服务引擎升级和统一平台建设的解决方案;下面来一起看看我们碰到了哪些问题与挑战?

二、微服务引擎升级与统一平台建设

2.1 面临的问题与挑战

我们知道,注册中心和配置中心是微服务架构领域的技术基石;下面给大家说明下我们在这两个基石系统实践过程中遇到的
问题与挑战

图片

首先是注册中心,众所周知,ZK是CP特性,在注册中心场景有较多不可用的问题,此外还有跨机房多活能力缺失,集群故障半径大等问题;写性能无法水平扩展,在大规模Dubbo服务场景中,接口级注册模型注册的数据量大,在业务高频变更期间网卡的带宽峰值会超过1000Gbps。此外还有业务易混用,功能缺失;内部的多个技术栈使用不同的注册中心,跨技术栈调用的研发运维成本高等问题。

在配置中心场景,存在应用、组件配置的变更通道不统一,故障场景配置回滚慢,变更审计日志分散,业务恢复耗时长等问题;配置变更下发的时效不满足业务要求,内部存在多套配置中心,都需要和业务研发流程打通,存在审批、审计、回滚等功能没有对齐的问题;此外在功能和安全上,还需要实现内部的配置定时生效,配置加解密等需求,配置访问通道符合公司的安全要求。

从以上的问题与挑战中可以看出,基于开源组件快速构建的微服务底层引擎在vivo的内部业务场景中存在较多的可用性、性能&容量、研发运维、功能&安全问题与挑战。

2.2 注册中心引擎升级

为了解决以上的问题与挑战,我们需要进行技术升级,首先给大家介绍的是注册中心的
解决方案

图片

针对Dubbo接口级服务发现导致ZK注册中心流量过大的问题,业界同行都在往应用级服务发现迁移来构建解决方案;通过Dubbo开源社区官网的介绍,我们可以看到,应用级服务发现是适应云原生,支持更大规模的服务发现模型;

将Dubbo接口级服务发现模型升级为应用级,可降低单机50%的内存消耗,降低注册中心集群90%的存储与推送压力,从架构上支持百万实例集群规模;

因此我们需要将Dubbo框架服务发现模型从接口级升级为应用级,彻底解决注册数据量大,对注册中心请求压力大的问题,同时具备面向云原生微服务架构的扩展能力。

此外,针对注册中心的可用性、性能&容量、研发运维等问题,我们需要建设满足AP特性、支持跨机房多活的统一注册中心,使用Session+Data分离架构,Data层持久化数据,Session层处理和客户端的长连接,无状态Session层能较好收敛客户端请求,实现读写流量隔离,具备较好的横向扩展能力,真正解决注册中心的性能、容量和扩展性问题。

综上
,我们需要构建Dubbo应用级服务发现能力,构建Session+Data分离的统一注册中心,内部的项目代号为vns。

从上面的技术方案分析中,我们可以看到,通过应用级注册可以彻底解决注册中心的流量突刺问题;通过Session+Data双层分离架构可以实现业务无感知的多集群拆分,有效缩小故障半径,那如何来
落地
呢?

图片

我们首先想到的就是上图左侧的技术方案,通过构建暴露gRPC协议、支持应用级注册的vns系统,海量的Dubbo服务通过双注册来实现迁移;但是在经过详细的技术分析之后,我们发现该方案存在明显的
耦合问题:

首先是Dubbo应用级注册升级的进展依赖vns系统的建设进度,Dubbo框架依赖稳定的vns SDK,Dubbo框架和vns系统之间存在进度依赖问题;

其次还存在回滚依赖问题,当vns系统因灰度异常回滚时,Dubbo应用级注册升级进度也会同步回滚;

同理当Dubbo流量切换异常回滚时,vns的业务接入进度也会回退。

此外,部分不迭代的业务可能需要继续使用接口级注册,无法实现ZK注册中心的完全下线。

为了解决以上问题,我们对技术方案进行了升级,改用通过vns系统暴露和支持ZK协议,实现Dubbo应用级注册升级和vns系统的能力建设解耦;当vns系统的能力建设进展还未达到生产环境要求时,我们可以通过引入一套新的ZK集群来支持Dubbo的应用级注册模型升级;当vns的能力成熟度达到生产环境的要求后,可以对引入的ZK集群进行替代,整个过程可以根据系统建设进展和可用性保障要求,进行可控的灰度放量和回滚操作,控制变更风险;最终,vns通过暴露ZK+gRPC双协议满足业务的接入诉求。

在整个技术方案落地过程中,我们始终坚持业务导向原则,实现业务升级和迁移的零|低成本;采用稳妥、完善的升级迁移方案,确保过程可灰度、可回滚、可观测;大家可以看到,我们通过兼容ZK协议,最大限度的保障Dubbo业务的平滑升级,切换方案做到了可灰度可回滚可观测,在减少升级成本的同时,降低项目落地风险,最终实现ZK注册中心的完全下线。

2.3 配置中心引擎升级

介绍完注册中心,我们再来看看配置中心的解决方案,配置中心主要解决的是配置通道不统一,性能不达标,无法满足内部的业务需求等问题。

图片

上图左侧是我们最新的配置中心技术架构图,右侧是统一配置通道的示意图,我们通过支持应用配置与组件配置的统一配置通道,实现了配置管理能力的收敛统一,在此基础上,建设一键审批/审计/回滚等能力,实现了和内部业务研发流程的打通,减少人力运维投入;此外,在新版配置中心上,我们也实现了较多的高可用、性能、安全、可观测能力增强等业务诉求;在配置中心升级过程中,我们追求业务的无感知升级,通过兼容原有配置中心对外开放的接口,实现了新系统的平滑升级,原有系统优雅下线。

大家可以看到,和注册中心的升级方案类似,在配置中心的技术方案设计中,我们也较好的遵循了业务导向原则。

2.4 统一微服务平台建设

介绍完注册中心和配置中心等微服务引擎的技术升级方案,我们再来看下从0到1快速构建的烟囱式微服务平台会面临哪些问题和挑战?

图片

从上图左侧示意图中可以看到,我们快速构建的微服务平台存在10个以上的模块,每个模块都有独立的入口,用户使用平台的易用性很低;此外,这些模块在建设过程中,还需要重复对接云平台、单点登录、权限、工单、监控、CMDB等公共服务系统;系统审计日志分散,不便于快速定位因变更引起的问题;综上,烟囱式微服务平台存在多入口,功能重复对接,运维、研发成本高,故障排查与恢复效率低,易用性不足等问题。

要解决烟囱式微服务平台的问题,需要构建更合理的产品方案,我们对用户的使用现状进行了分析:

图片

通过系统埋点数据发现,烟囱式微服务平台中用户使用频率最高的两个系统分别是配置中心、服务治理。

通过上图左侧的PV/UV饼状图数据,大家可以发现:

配置中心的用户访问主要集中在配置的【查询与变更】、【变更记录与审批】和配置变更相关的2个页面上,服务治理的用户访问主要集中在【服务概览】、【服务查询】和服务相关的2个页面上。

基于埋点数据,我们可以看到用户的访问集中在少数的几个功能上,通过整合各个系统模块高频使用的功能,建设统一的平台入口,实现系统间联动,这也给我们如何建设统一平台提供了较好的思路。

此外,在对各个模块的技术架构进行分析时,我们识别到了位于最底层、技术依赖程度最高的两个系统:配置中心、注册中心,这两个系统非常适合作为统一平台建设的技术底座。

图片

区别于烟囱式微服务平台的多个系统模块独立对接CICD等研发平台,在统一微服务平台建设中,我们升级为统一平台对接CICD等研发平台;我们的建设思路是,以配置中心/注册中心为底座来建设统一微服务平台:

一是
:基于统一的配置通道与CICD等研发平台系统进行联动,建设一键审批、回滚能力,整合研发流程,降低对接成本;

二是
:通过统一平台的建设,实现平台间联动,建设高阶的自动化水平,支撑业务进一步提升持续服务能力。

2.5 引擎升级&统一平台建设总结

接下来,对我们前面讲到的内容做一个总结:在大规模、海量业务的微服务架构实践过程中,我们通过引擎升级和统一平台能力建设较好的解决了碰到的问题与挑战。

图片

在升级和建设过程中,我们需要保证现有业务的连续性,保障不发生因底层引擎升级和平台建设导致的可用性问题。因此,引擎升级和统一平台建设的工作需要建立在高可用保障的基础上;换句话来说,可用性是我们所有工作的底座。

在这个基础上,我们实现注册中心和配置中心的引擎升级,完成应用级注册模型升级;在这个过程中,解决底层引擎的扩展性、容量、性能、可维护性和安全性等问题;最后,我们要建设统一的微服务平台能力,实现平台间联动,构建自动/自助化使用能力;赋能业务。

大家可以看到,通过完整的方案介绍,在上图右侧我们呈现了微服务架构实践过程中的价值分层逻辑,即在可用性的基础上,提升系统的扩展性、容量、性能、可维护、安全性等能力;然后再在此基础上,交付更高的研发效率,更好的用户使用体验。

三、微服务架构升级的总结与展望

介绍完我们的解决方案后,最后来说明下我们对微服务架构升级的总结与思考,以及对未来的展望。

3.1 拥抱开源的实用主义

在构建微服务架构技术体系的过程中,我们始终坚持拥抱开源,迭代业务适用的技术平台;结合内部业务的实际情况,我们走出了一条从开源到开源+自研的研发路径。

图片

在从0到1的平台能力建设过程中,我们引入开源组件进行能力快速构建,快速交付满足业务的需求;始终坚持业务适用原则,不过度设计,支撑业务的快速迭代;以上阶段,我们称之为“拿来主义”。

在面向更大规模、海量业务实践过程中,为了解决碰到的问题与挑战,我们在开源的基础上进行增强,自研部分能力来解决亿级用户规模下内部业务的功能,性能,容量,研发流程打通等需求;这个阶段,我们称之为“实用主义”。

在技术平台迭代过程中,我们始终坚持2个原则,一是简单有效原则,坚持用最简单的解决方案来解决问题;二是迭代和演进原则,坚持平台持续迭代和演进的原则;前期基于开源组件快速搭建能力,再基于实际的业务需求和痛点来落地自研架构;在这个过程中,始终坚持业务适用,不为了技术而技术,避免大而全的技术架构。

此外,也要说明一个常见的误区,我们为什么不完全自研?vivo的微服务平台建设从开源社区获益良多,坚持不闭门造车,站在巨人肩膀上,持续引入优秀特性来支撑业务的快速发展,同时也会考虑将部分行业适用的通用优秀特性反馈给社区,和社区共同成长。

3.2 中间件组件全生命周期管理

大家可以看到,vivo的微服务架构技术体系引入了较多的开源组件,在实践过程中,我们摸索出了一套完整的中间件组件全生命周期管理策略。

图片

我们先来看看业务的诉求和底层技术的
特点

首先是业务的诉求:

  1. 业务期望更高的迭代交付效率;

  2. 快速引入新技术,使用新技术助力业务创新,但很多时候新技术往往意味着成熟度不足,可能存在较多问题;

  3. 业务的不断创新与发展,对组件的性能、容量要求越来越高;

对业务来说,高效迭代交付需求是第一位的。

然而,底层技术有它自己的特点:

  1. 技术的发展有它的客观规律,需要经历萌芽期 → 膨胀期 → 低谷期→ 复苏期→ 成熟期等多个阶段;

  2. 缺乏约束的技术体系必然随着时间推移而腐化,治理不及时会成为技术债务,阻塞业务发展;

  3. 同类中间件组件的快速引入会有重复建设的效率问题;

  4. 中间件组件的技术升级周期客观上都比较长。

实践证明,只有足够稳健的底层技术能力才能更好支撑业务的高效迭代。在这个过程中,如何兼顾效率与质量?尊重客观规律,确保整个过程都有明确的目标和方向,避免走偏,慢就是快。

我们认为,完善的中间件组件全生命周期管理策略,首先需要在所有的技术团队中形成价值共识;再通过组件扫描和组件地图等手段及时对组件全貌进行洞察;在组件的标准化治理和运营阶段实现有规范,补短板;同时在新技术引入时,通过完善的新技术引入规范,覆盖功能/性能/容量/扩展性/成熟度/使用成本等维度;在组件的版本治理上,使用基线版本治理方案,输出明确的使用标准/版本升级方案/版本收敛策略;最后,在组件的成熟度管理上,我们可以借助Gartner(高德纳)技术成熟度说明和组件能力矩阵,不断提升组件的成熟度。

综上,为更高效的支撑业务,在组件管理上我们使用了更加入宽松的引入策略,同时也会对组件的全生命周期进行严格管理,践行宽入严出策略,通过完善的中间件组件全生命周期管理助力业务跑的更快,走的更远。

3.3 引擎升级探索

展望未来,我们会坚持和践行引擎升级和平台建设的
持续迭代思路

首先是对引擎升级的探索,通过引入新技术来解决当前碰到的研发效率、成本等痛点问题:

图片

在研发效率方向
,存在的痛点问题如下:

一是
,组件SDK的升级周期长,碎片化问题严重;

二是
,当前vivo内部主要的是Java、C++技术栈,新业务形态孵化可能会引入新的技术栈,需能够较好解决跨技术栈的问题。

想要较好的解决以上问题,需要探索基于Java Agent/SideCar技术的标准ServiceMesh模式,将RPC、MQ等中间件能力下沉,透明化实现微服务治理、高可用等能力增强,同时组件具备热升级能力。

此外,
在成本方向
,存在的痛点问题如下:

一是
, MQ等重资源型应用的CPU、存储资源利用率差异大;

二是
,部分事件驱动场景机器资源利用率低。

要解决以上问题,我们可以通过升级MQ组件,落地存算分离技术,探索计算存储资源利用率优化方案。另外,还可以探索Serverless技术,实现平台化托管运维,降低资源成本,天然适合小程序、快应用等事件驱动业务场景。

综上
,在引擎升级探索上,我们会基于业务需求和痛点问题,探索和落地ServiceMesh/Serverless/存算分离等云原生技术。

3.4 平台建设探索

讲完引擎升级探索,我们再来看看在平台建设上的探索:

图片

作为技术平台团队,我们在持续积极的探索“平台工程”理念,从现在的DevOps实践到平台工程,也是团队协作理念的再次升级。

我们知道,DevOps于2009年出现,2015年在国内火起来,它是一种文化、方法论,是敏捷理念从开发到运维的延伸。DevOps的理念是:践行谁构建谁运行,开发运维一体化,实现业务的高效交付。

但是,DevOps在实际落地过程中存在以下问题:

“DevOps团队”的中心化与去中心化取舍问题


  • 中心化
    】指的是,独立的DevOps团队,即不在业务团队中配置DevOps能力,而把DevOps人员集中起来组建团队,这种完全中心化的模式本质上和DevOps文化相矛盾。同时根据康威定律,可能会制造新的效能瓶颈。“独立的DevOps团队”在2014年被Thoughtworks“技术雷达”列为Hold (停止采用)。


  • 去中心化
    】指的是,将DevOps能力分散在业务团队,这种做法会将大量的和基础设施相关的工作职责划给业务团队;这种方式会随之出现基础设施和服务治理缺失、系统稳定性降低、研发和DevOps效能浪费等诸多问题。

因此,想要践行好DevOps,必须在中心化与去中心化之间取得平衡。

此外,从平台能力上讲,DevOps平台往往更侧重于建设流程和工具链,而在使用这些建设的工具技术平台过程中会大大增加业务开发团队的认知负荷,存在无法较好向业务开发团队屏蔽底层基础设施复杂性的问题。

平台工程的概念,是在2017年首次出现,于2022年在国内兴起。平台工程的定义是,一套用来构建和运营支持软件交付和生命周期管理的自助式内部开发者平台的机制和架构;它的特点是:平台在演进中提供足够的透明度、敏捷性,在建设过程中形成适合业务架构的高效协作模式。在这一过程中逐步将知识体系固化到平台中,从而使得工程方式标准化、流程化和规模化并持续改善;它践行的理念是:一个可用的、高效的平台并非一个技术团队埋头苦干就可以产出的;恰恰相反,一个成功的平台工程需要企业各个组织部门合作、协调、推广并根据实际使用反馈不断迭代。

在具体实践中,平台工程约定了“业务团队”和“平台团队”两个团队,其中“业务团队”负责业务研发,“平台团队”负责平台建设;“平台团队”通过将技术知识沉淀到“平台工程”,隐藏和抽象底层基础设施的复杂性,实现基础设施即代码,为“业务团队”赋能增效;同时,基于“业务团队”在使用“平台工程”的过程中的不断反馈来持续改进平台的自助化产品能力,构建一整套覆盖DevOps全链路的简单易用平台产品;可以看到,平台工程是一种最佳实践,和我们当前的团队协作模式匹配度非常高。

图片

在平台建设的整体规划上:

当前阶段
:我们构建的统一微服务平台会持续探索“平台工程”理念,沉淀配置中心、注册中心等平台的技术知识与最佳实践,构建和打磨业务自助化使用的平台能力。

展望未来
:我们会通过明确的北极星指标,牵引平台提供更高的研发效率和更好的开发者体验。

在研发效率上
,我们追求单位时间内更多的代码产出和需求交付;此外我们也追求更好的开发者体验,通过降低用户使用平台的打断次数和平台问题的人工支撑次数,提升业务团队和平台团队两个团队的开发体验。

在具体的落地路径上
,我们始终以开发者用户为中心,针对研发工作中时间消耗较多的场景进行优化,通过北极星指标牵引,形成覆盖 IDE+PaaS 的平台工程实践路径,持续迭代优化平台能力,提升研发效率与开发者体验。

作为一个混迹开源界多年的技术人,以往开发的项目中用过了许多验证码工具,比较经典选择的的有 easy-captcha,但是它支持简单的图形、gif、中文、算术等类型验证码。直到我遇见了 tianai-captcha,我愿称之为开源界最好用的行为验证码。

tianai-captcha 简介

tianai-captcha 简称 tac,是一款集成滑动类、点选类的一款行为验证码,以使用简单、安全性强、界面美观、接入方便,集好看、功能多、安全性强的一款开源行为验证码工具。

image
image

tianai-captcha 目前支持的行为验证码类型

  • 滑块验证码
  • 旋转验证码
  • 滑动还原验证码
  • 文字点选验证码
  • 图标验证码
  • 语序验证码
  • 刮刮乐验证码
  • 后面会陆续支持市面上更多好玩的验证码玩法... 敬请期待

在线文档:
http://doc.captcha.tianai.cloud

体验地址:
http://captcha.tianai.cloud/

源码地址

https://gitee.com/dromara/tianai-captcha

https://github.com/dromara/tianai-captcha

演示 GIF

image
image

对比市面上其他的开源行为验证码工具,大家可以观看 tianai-captcha 项目的演示 GIF 后自行评定。

技术细节

目前 tianai-captcha 包含前端以及后端两部分。前端开源项目 captcha-web-sdk 支持 html 原生引入,

image

也支持 vue2 项目引入,

image

后端支持 Java Maven 方法引入,传统项目直接引入 tianai-captcha 依赖,Spring Boot 项目直接引入 tianai-captcha-springboot-starter 依赖后稍加配置即可。

image

作者介绍

95 后大龄程序员,一名野生的民间技术爱好者,15 年学习编程技术,迫于生计于 17 年就职于某电商公司, 在从业生涯中,本项目 2020 年发布后,后续也是改改停停,自古闲人出金货,也许有一天作者自由了,会好好的完善这套框架。

后续发展

在与 tianai-captcha 作者沟通交流后,tianai-captcha 后续发展如下,

  1. 添加更多好玩的行为验证码方式
  2. 新增验证码平台 Server 端,方便更多项目接入
  3. 考虑新增更多语言的 sdk 接入包,如 php、python、go、nodejs 等。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!

个人用户管理是业务系统中非常基础且重要的一个公共服务系统,我们写的绝大多数应用都和个人用户或会员有关,用户(会员)数据安全无小事,必须有一个完备的用户管理平台系统。

因为不同公司的主业务不同,个人用户管理的侧重点也会有不同,PowerDotNet这里介绍的个人用户管理平台,只是个人用户管理系统中很基础的通用功能的一部分。

当然,在我自己开发过的所有公共服务系统中,PCRM是中规中矩一般复杂甚至我个人认为是架构很简单的系统,真正混乱且困难的是订单、支付、财务、结算、库存、生产加工、配送等复合型系统。

曾经在某司接手过一个复杂繁琐另类但其实不中看更不中用的个人用户管理系统,功能极其凌乱,划分非常随意,实现也很恶劣,行业水平之低令人发指,总之就是稀烂到自己人都看不下去,咩哈哈。

因为个人在支付、财务、结算、账户和票券等系统有丰富的开发经验,对PCRM和这些系统的紧密联系耳濡目染,所以也认同某些模块或功能放到PCRM更合理,比如混合支付中的公司账户和积分功能。

在介绍
支付平台
的文章中,我们提到混合支付的概念,认为“不同的公司有不同的虚拟货币系统,混合支付是指公司的虚拟货币和外部的支付方式一起支付完成支付请求的一种玩法”。

混合支付设计和实现有很大的技术挑战,我已经不止一次开发维护过混合支付代码,尤其是涉及到虚拟货币(账户)、积分和票券等系统,恐怖程度堪称夜能止小儿啼哭,日可令恶犬夹尾,咩哈哈。

虚拟货币(账户)系统每家公司实现的方式可能都不一样,本来可以另开篇幅说明,但根据我的开发经验,这部分工作量也不小,为了快速开发需要,只要设计抽象合理,不拆分也能高效使用,所以就偷懒了^_^。

考虑到虚拟货币(账户)系统和个人用户的紧密联系,将这两个系统划分到一起也无可厚非,我就把用户虚拟货币(账户)系统抽象到PCRM中进行讲解,当然要独立出来也很容易,根据数据表结构前缀拆分即可。

有一种类似账户系统的票券系统,主要处理优惠券相关的业务逻辑,虽然处理方式可以参考虚拟货币系统部分处理逻辑,但又和订单、活动等系统“耦合”较为紧密,这个可以抽象出独立系统,等有空再写写这方面的内容。

根据个人经验,账户和票券系统,设计和实现的不好,往往会造成业务灾难,比如支付金额不准确,财务对账不匹配,同时账户和票券系统容易滋生腐烂代码,这也对社会主义精神文明建设有直接伤害。

支付平台、财务平台和个人用户管理平台在个人多年开发经验里算是投入较多钻研较深入的系统了。我亦无他,唯手熟尔,除了公共组件,业务逻辑同样非常考验程序设计实现水平。

支付、财务和CRM设计实现的不好或者考虑不周到,很容易出错,而根据墨菲定律,任何可能出错的事情最终都会出错。业务逻辑型公共服务的稳定性和可扩展性也非常重要,值得深度开发和积累。

PowerDotNet的设计和实现做了很多取舍,很多特定行业或定制化业务没有吸收进去,毕竟PowerDotNet的重要目标是要实现一套能够被绝大多数公司通用的公共服务。

环境准备

1、(必须).Net Framework4.5+

2、(必须)关系型数据库MySQL或SqlServer或PostgreSQL或MariaDB四选一

3、(必须)PowerDotNet
数据库管理平台
,主要使用DBKey功能

4、(必须)PowerDotNet配置中心
Power.ConfigCenter

5、(必须)PowerDotNet注册中心
Power.RegistryCenter

6、(必须)PowerDotNet缓存平台
Power.Cache

7、(必须)PowerDotNet消息平台
Power.Message

8、(必须)PowerDotNet文件平台
Power.File

9、(必须)PowerDotNet支付平台
Power.Payment

10、(必须)PowerDotNet财务平台
Power.Finance

11、(必须)PowerDotNet人员管理平台
Power.HCRM

12、(必须)PowerDotNet基础数据平台
Power.BaseData

一、用户管理

1、用户基础

对于用户的基本管理,包括基础资料、等级、状态、黑名单等。

针对用户的资料管理:

考虑到用户基础信息非常多,借鉴了经典的“分表”思想,将
常用的不常更新的字段(user_info)
和不常用且会变更的字段(user_extend)分两张数据表管理起来,这应该是比较常见的拆分方法,我待过的公司至少有两家是这样实现的。

用户黑名单的设计也是重要的功能:

下面再介绍下个人用户管理的一些常见功能。

修改密码(支持短信和邮件提醒):


找回密码:

用户头像:


其他如用户变更记录、登录等等基础功能,常见的人员关系场景管理后台都要有完善支持。

PCRM经常会有各种各样“我的XX”功能,“我的XX”功能和系统边界及系统解耦有直接关系。通常我们会根据需要划分出两个主要模块:用户单据和用户社交。

2、用户单据

有些用户业务数据,和用户关系看上去也比较紧密,但界面展示通常直接调用各个平台系统提供的接口就行,不需要直接在PCRM中进行数据维护。

典型的如我的订单、我的购物车、我的钱包、我的卡包、我的票券、我的财务、我的配送地址、我的开票公司信息、我的常旅客管理等功能模块可以直接划归到分解好的各个平台系统中去。

当然,有些用户电商购物单据划归到PCRM中也行得通,目前PowerDotNet实现的PCRM就将用户配送地址和开票公司信息直接划归到PCRM中管理,当然把它们分别放到配送平台和财务平台才是最合理的。

根据个人开发经验,我的XX数据经常因为划分和归属而产生各种各样的推诿扯皮,尤其是中大型的电商项目,互联互通非常复杂,公共服务性质的共用系统就经常面临模块和数据划分及归属管理的困境。

我的XX数据一个简单的经验之谈,稳定的变动极少的我的XX数据可以优先划归到PCRM中进行管理,比如我的配送地址或我的开票公司,这些就是改动较少的静态数据,放到PCRM中其实是很合适的。

当然稳定的变动极少的数据放到某系统中这个做法只是经验之谈,并不通用,具体划归到哪里,还是需要按照实际业务需要和成本控制来确定,比如我的银行卡号之类的静态数据放在支付平台管理更好。

3、用户社交

用户社交数据通常都和公司主业务强相关,我们可以将这些数据维护在PCRM中,也可以独立开发出子系统,很显然普通公司的用户社交和PCRM联系更紧密。

比如我的评论、我的随笔、我的投诉、我的相册、我的消息、我的关注、我的粉丝、我的好友、我的收藏、我的点赞、我的标签等可以直接划归到PCRM系统中。

用户单据和社交的设计和实现非常考验开发人员的水平,所谓夏虫不可语冰,井蛙不可语海,凡夫不可语道,没写过这方面代码的人很容易不知不觉中造成系统重大缺陷,这也是个人多年开发填坑经验之谈。

二、用户账户管理

根据个人开发过的虚拟货币系统,这里再提取抽象简化为个人用户账户系统,站在巨人的肩膀上,我也积累了一套完善的通用的用户账户处理单据流程。

用户账户和金钱有直接关系,这样就会产生这样那样的流水,以及对账红冲等常见功能。


基本的对账功能:

在产生流水的过程中,可以抽象出不同的流水单据进行处理。

用户账户的主要单据如下:

1、充值订单

充值订单支持对支付成功的订单记录进行财务入账和申请开票等操作。

2、充值流水

3、冻结流水

4、解冻流水

5、扣款(消费)流水

6、退款流水

每个处理单据,都有基本的对账功能。这里仅以退款示例下:

1、一次全额退款

2、多次部分退款,直至全额退款成功

3、部分退款

对于用户账户系统的提现功能,需要抽象出
提现单
,不过这个支付平台功能更紧密,这里不列在主要单据里。

三、账户提现

如果支付平台做得好,账户提现完全可以在支付平台里搞定,不需要在业务系统里单独开发功能。

PowerDotNet的支付平台完全可以应付常规的账户提现需求,之所以在这里还抽象出提现单进行介绍,主要就是:

在某厂我这么实现过,而且用户的反馈极其良好,不介绍有点可惜^_^

1、提现申请单

终端用户通过PCRM接口创建好提现申请单,接口支持同步和异步处理

上述两个接口基本满足了提现的常规需求。

2、提现流水

创建好的提现申请单,最终需要向支付平台发起真实退款请求才能完成用户的提现需求,提现成功后,提现申请单会对应产生相关提现流水。

3、提现补偿工具

有时候退款会发生这样或那样的问题,比如自己开发的支付系统在发布或维护,用户账户异常风控不通过,银行服务维护,支付宝、微信等账户注销或锁定,秘钥过期等等原因,这样用户提现需求就要进行补偿重试或者人工处理。

PowerDotNet结合个人开发和运营经验,开发了几个补偿小工具,能帮助开发和支持人员快速定位并解决问题。

上述补偿工具,严格来说是对支付平台接口的再次封装和调用。

再次说一遍,PowerDotNet的支付平台完全可以应付常规的账户提现需求,真没必要又包一层产生这么多单据,就是这么自信,咩哈哈。

四、财务记账

对于用户账户充值和提现,从财务角度看是一对典型的往来账,PCRM也将用户账户充值和提现设计成便于理解兼顾灵活性的入账和出账流程。

1、收款单

PCRM账户充值,用户通过支付平台完成账户充值后,支付平台回调通知PCRM扣款结果,PCRM完成充值业务逻辑后调用财务平台接口创建财务收款单,财务系统完成入账逻辑。

2、应收退款单

PCRM账户提现,用户通过支付平台完成账户提现后,支付平台回调通知PCRM退款结果,PCRM完成提现业务逻辑后调用财务平台接口创建财务应收退款单,财务系统完成出账逻辑。

注意,对于用户下订单使用账户金额消费的场景,虽然账户金额减少,但不用PCRM创建财务应收退款单,而应该由订单系统(商户)主动调用财务接口创建收款单。

3、申请开票

PCRM用户提交开票申请,调用财务平台接口创建应收发票,财务审核后完成开票。

在PCRM中进行开票申请:

在财务平台审核用户开票信息:

五、用户积分

严格来说,用户积分也是虚拟货币的一种,不过很多公司都会独立出来,毕竟积分相对虚拟账户而言,有一些特殊处理方式,比如积分有效期、积分比率、特定活动动态支付参数,单独抽象出来未尝不可。

PowerDotNet抽象出来的积分处理方式,借鉴了前厂的部分逻辑,并且去掉了具体业务有关的特殊逻辑,和用户虚拟账户已经有极大多数相同的处理单据。

在产生流水的过程中,可以抽象出不同的积分流水单据进行处理。

1、积分充值流水

2、积分冻结流水

3、积分解冻流水

4、积分扣款(消费)流水

5、积分退款流水

对账功能也基本和用户账户相同,不过因为绝大多数积分有效期的关系,有些功能,如退款和解冻的对账功能需要调整。

根据我的个人开发经验,积分有效期这个东西是个巨大的陷阱,因为很多业务逻辑和性能问题都由它引起,设计积分系统的时候,如果没有有效期,那真可以减少百分之八十的工作量。

六、混合支付

混合支付功能其实我是非常拒绝再写的,个人已对接过的混合支付特别费力不讨好,还容易造成现有系统出错,哪怕你给对方提需求并且定义了标准接口,奈何现状所限,挡不住出问题,效果聊胜于无。

1、接口抽象

混合支付在支付平台里已经简单介绍过,本文就简单梳理下混合支付常用的冻结、解冻、扣款、退款四个接口:


现实中,用户账户和用户积分是分别处理的,无法保证事务性。完善的后台管理系统,是混合支付处理的关键保障。如果在特定定时任务都无法保证混合支付正常的情况下,通过后台人工介入也是很轻松的事情。

2、流水日志

对混合支付,需要有完善的日志,便于排查问题。

交易的每一笔流水都要记的一清二楚,必要时可对日志进行数据统计,本文省略数据统计。

3、支付风控

严格来说,任何支付功能,包括虚拟货币(如账户、积分等)的充值、消费和提现都应该有严格的风控,独立的风控系统是必不可少的,但是鉴于某些弱鸡公司孱弱的研发能力,风控聊胜于无。

小结:用户账户管理、账户提现、财务记账、用户积分、混合支付等模块设计实现很容易造成各种混乱,尤其是账户系统,我已经不止一次维护过这种容易造成用户投诉的类虚拟货币系统。

没有结果的爱情往往更加动人,缺少规范的系统常常麻烦缠身,个人经验中,只要系统形象磕碜,往往公司的技术管理水平极其低下,流程规范严重缺失,哪怕是规模庞大的上市公司。

七、信息安全

PCRM中有大量的根据用户Id或者用户名查询用户信息、账户、用户单据或用户社交数据的接口,这些涉及到用户数据的接口,一定要注意信息安全管理。

1、越权漏洞

越权访问(Broken Access Control,简称BAC)是应用程序中一种常见的漏洞,越权,顾名思义,就是获得了本不应该有的权限。

越权漏洞是指应用在检查授权时存在纰漏,使得攻击者在获得低权限用户账户后,利用一些方式绕过权限检查,访问或者操作其他用户或者更高权限。

越权漏洞往往是基于业务逻辑的漏洞,常见的比如在PCRM系统中有大量的CRUD接口,由于过分相信接口消费者而遗漏了权限的判定,这样的漏洞很难被WAF保护。

在实际的代码审计中,这种越权漏洞往往很难通过工具进行自动化监测,开发(甚至测试)理所应当的认为接口调用方便是第一位的,只要功能正常,授权管理是调用者的事情,这种想法危害极大。

根据越权漏洞经验统计,目前存在着两种显而易见的越权操作类型,即横向越权操作(水平越权)和纵向越权操作(垂直越权)。

(1)、水平越权

水平越权指相同权限下不同的用户可以互相访问。典型示例:用户A登录后,用户A操作却影响到B用户。

水平越权是相当常见的漏洞,多年前在某电商工作的时候,碰到过一个订单页面get方式传入UserId查看用户订单的漏洞,正常情况是登录用户只能查看当前自己的订单,但后端页面业务逻辑缺少这个校验。

(2)、垂直越权

垂直越权指使用权限低的用户可以访问到权限较高的用户。典型示例:低权限用户使用高权限用户的功能,比如普通用户可以使用管理员的功能。

2、越权防范

避免越权漏洞,尤其是水平越权,需要遵循一个简单的原则:用户只能看到属于自己的内容。

个人总结的常见防范越权漏洞措施包括:

(1)、
服务治理平台
做好接口认证、鉴权和授权,比如验签和(或)校验token

(2)、严格的功能权限控制,权限到页面或者按钮,调用功能前验证用户是否有权限

(3)、数据权限控制,执行关键操作前必须验证用户身份,验证用户是否具备操作数据的权限

(4)、双重验证,前后端同时对用户输入信息进行校验,永远不要相信来自用户的输入,对于可控参数进行严格的检查与过滤

(5)、对于系统中各种有规律的流水号,比如自增,设计时取舍务必小心,防止穷举漏洞攻击,对流水型资源ID加密,防止攻击者穷举ID

(6)、敏感信息脱敏,在配置中心做好敏感信息脱敏开关,防止意外发生时可及时兜底处理

八、水平分表

个人碰到过的PCRM的最大挑战在于用户数据量过大,一些数据量巨大的表需要分库分表处理。

常见的分库分表类型包括
垂直分库

垂直分表

水平分库

水平分表
。具体到PCRM分库分表,通常可使用
水平分表
策略。

水平分表是指将单张表的数据分片拆分到多台服务器节点上,每个节点具有相同的库与表,表结构都一样,每个表的数据不一样,没有交集,所有表的并集是全量数据。

比如用户信息user_info和用户扩展user_extend两张表,单库不足以支撑的时候必须要水平分表(常见算法如用户id取模、用户id范围分区等),几乎均匀的分片保存到不同服务器PCRM数据库中。

水平分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、CPU、内存、连接数、其他硬件资源等的限制,但是也带来了业务逻辑上的很多挑战,比如:连接查询、事务、跨节点分页、排序等。

举例来说,在PCRM中,水平分表后,以前单库单表相对简单的登录功能就会变得很复杂。

常见的PCRM支持用户名、手机号、邮箱、证件号码、OpenId等进行登录,没有水平分表前,很可能一个SQL连接查询就能搞定,分库分表后就需要考虑分区、跨库连接甚至引入其他中间件的查询问题。

正如我们所知道那样,软件的很多问题都可以通过加一层来解决,如果加一层还不能解决,那就再加一层^_^。

解决水平分表造成的查询问题的常见方法是添加冗余关系索引表,通常分为两种:

1、冗余全量数据

PCRM支持手机号登录,那么我们就把用户信息user_info和用户扩展user_extend两张表根据手机号分库分表。

优点:只需要查询一次就能定位数据。

缺点:占用空间大,每增加一个维度查询就得增加一倍的空间, 数据存储与变更时需要维护多张表。

2、冗余关系索引

PCRM支持手机号登录,那么我们就维护一个手机号和用户id的关系映射表。

优点:占用空间比冗余全量数据小很多。

缺点:必须查询两次, 先从映射表中查到用户id, 再根据用户id定位数据,性能略有下降。

冗余关系索引可以存储在RDBMS中,也可以存储在Redis、MongoDB、Cassandra、ElasticSearch等NewSQL中,得益于NewSQL集群海量数据存储和快速查询能力,功能性能都能满足业务需要。

3、PowerDotNet分表

PowerDotNet自研的ORM工具集成了常用的分库分表功能,配合代码生成器和DBKey服务,很容易实现分表。我们以PCRM数据库为例,ORM实现的分库分表常见三种情形:

同库不同表:PCrmDB下UserInfo0、UserInfo1...UserInfoN表

不同库相同表:PCrmDB1下UserInfo0、UserInfo1...表, PCrmDB2下UserInfo0、UserInfo1...表

不同库不同表:PCrmDB1下UserInfo0、UserInfo1...表, PCrmDB2下UserInfo2、UserInfo3...表

目前PCRM的用户和用户扩展信息就是根据用户Id进行哈希取模实现不同库相同表的分表形式,对分片的用户和用户扩展等表,不建议复杂连接查询,单表查询也能满足业务同时也保证线上运行稳定可靠。


PowerDotNet自研的ORM虽然看上去远没有TDDL、ShardingSphere、MyCat等强大,却也基本满足中小公司的分库分表需求,配合DBKey服务和代码生成器走出了自己的特色,等我有空再详细介绍。

九、系统交互

前面在用户管理一节已经提过各种“我的XX”管理,PCRM也和很多内部业务系统保持互通关系,尤其是ToC业务离开PCRM基本活不下去,整理下个人开发和对接过的几种常见互联系统。

1、订单系统

经典的”我的订单“模块。直接需求就是在界面查询我的订单而不是别人的订单,记得业务逻辑不严谨导致不同用户查询串号这种经典漏洞也不是没有发生过,咩哈哈。

2、购物车系统

”我的购物车”和”我的订单”类似,查询不能串号,同时还需要维护一个不同终端如PC、APP等未登录用户购物车和实际登录用户购物车的关系,这种也非常考验开发者的设计和实现水平。

3、支付系统

支付调用用户的地方还是比较频繁的,如果用户账户和积分也设计集成在PCRM中,那么混合支付的地方就必然和PCRM交互,还有比如查询用户基本信息如手机号、邮件等发送消息,这种也很常见。

4、风控系统

风控到人,懂的都懂。

5、财务系统

”我的财务”,很常见,基本需求比如查询统计下个人某个时间段内收入支出消费趋势曲线啥的。

6、票券系统

”我的票券”,各种电商活动送出的优惠券、购物券等等,设计实现不同,和个人用户的关系也不同,有些票券系统设计基本很少直接调用PCRM接口,因为可能不需要直接绑定到个人用户。

7、消息系统

发送验证码,这种需求随处可见,比如改密、找回密码等。

8、其他系统

其他系统,诸如开放平台、活动等,和PCRM没有那么紧密,但是又需要直接或间接调用PCRM接口。

十、其他

写到这里才发现前面画风有点偏账户、积分和混合支付了,PCRM真正的核心功能还没有介绍完全,限于篇幅,本文截图没有介绍的PowerDotNet的PCRM已经实现的公共服务基本功能,包括:

1、验证码管理

包括常见的字符验证码、运算验证码和滑动验证码等。

2、登录注册管理

支持传统的用户名(手机、邮箱)密码登录,扫码登录,以及OAuth登录,还包括单点登录(Single Sign On,简称SSO)功能,LDAP(轻量级目录访问协议)也有简易实现。

登录注册在CRM中算是非常普通常见的功能,但是千万别小瞧登录注册,至少个人接触过的PCRM系统,绝大多数登录注册都只是充斥HelloWorld级代码的CRUD玩具型Demo而已。

虽然有很多可以借鉴的经验和实践,但架不住乱来的需求和变更,看上去简单的登录注册,改来改去也容易事件多发。正如黑格尔所说,人类从历史中得到的唯一教训就是人类无法从历史中学到任何教训。

3、基于token+redis的token管理

万能token管理,主要实现基于加密token+redis,早期实现的jwt token可按照配置启用,绝大多数场景下不需要再启用jwt。

4、第三方关联用户管理

第三方关联用户业务场景也比较常见,通常涉及到不同公司的用户或会员的数据打通,设计实现考虑不周到,容易有安全风险。

==========分隔线==========

验证码管理、登录注册管理、基于token+redis的token管理在
HCRM
中已经被广泛使用,可复用的公共模块没有再次说明的必要,没错,我就是觉得简单懒得介绍了^_^。

个人用户管理是和具体公司具体业务紧密关联的公共服务业务系统,比如综合性电商、垂直类电商、酒店、机票、银行、保险、社交网站等等,它们对应的个人用户管理侧重点就不一样,所以有很多相关业务功能都需要按照业务要求去开发。

根据我的个人开发经验,个人用户或会员管理在业务领域内能衍生出很多业务功能子系统,比如账户、积分、票券、活动、投诉、论坛、广告营销、信息安全、开放平台、推荐算法等都和PCRM有千世万缕的联系,想写好也要面对很多的挑战,对于一线开发人员,学业务做设计堆代码,一个都不能少,是非常需要花时间积累和投入的公共服务。

基础设施和公共服务建设对系统稳定至关重要,我们欣赏并尊重少说多做严谨务实工作和实践的人,最讨厌不切实际夸夸其谈自以为比别人高明同时还不虚心学习也没什么逻辑和执行能力的人。

有了支付、财务和CRM的系统开发经验,在各种形态的公司或组织里开发管钱和管人的系统基本上都不会有太大问题,这就是PowerDotNet和PowerDotNetCore专注开发通用型公共服务的价值所在。

论文PDF地址:
https://arxiv.org/pdf/2110.07602.pdf

转载请备注出处:
https://www.cnblogs.com/zhiyong-ITNote/

P-Tuning v2

摘录自第三部分

image.png

桔色块指代
可训练
的prompt embedding;蓝色块是由固定(冻结)的
预训练
语言模型 存储或计算的embedding。

Deep Prompt Tuning

continuous prompts(连续提示) 仅仅能够插入到input embedding序列层。如此,有两个问题:首先由于序列长度的约束限制,可调参数的数量有限。其次,输入的embedding对模型预测有间接的影响。
为了解决这些问题,P-Tuning v2使用deep prompt tuning的方案。正如上图的b部分,prompt作为prefix token插入到不同的层中。一方面,p-tuning v2有更多可调的特定任务参数(从 0.01% 到 0.1%~3%),扩大了任务的容量也提高了参数效率;另一方面,添加到更深层的prompt对模型的预测会有更多直接的影响。

转载请备注出处:
https://www.cnblogs.com/zhiyong-ITNote/

理解

在P-tuning v2的方案中,从图直观来看,有两个关键的点:

  1. prompts会加在序列的前端,而不仅仅是插入到input embedding
  2. 每一层都会插入prompts

v2版本主要基于p-tuning和prefix-tuning技术。prompt 向量是在模型的 embedding 层与其他输入 token 的 embedding 相拼接的,且通过在预训练模型的每一层引入可训练的 prompt 向量来提高模型对特定任务的适应性。
p-tuning主要是利用一个prompt encoder,将prompt先encoder再与input embedding进行拼接。
prefix-tuning是在Transformer的Encoder和Decoder的网络中都加了一些特定的前缀。
而基于这两种技术的v2版本,则是将两者结合。在embedding与transformer模块都做了prompt向量的插入。
ChatGLM中,首先要对prompt做encode,作为前缀prefix拼接插入到input embedding与transformer模型中。


# 转载请备注出处:https://www.cnblogs.com/zhiyong-ITNote/

class PrefixEncoder(torch.nn.Module):
    """
    The torch.nn model to encode the prefix
    Input shape: (batch-size, prefix-length)
    Output shape: (batch-size, prefix-length, 2*layers*hidden)
    """

    def __init__(self, config):
        super().__init__()
        self.prefix_projection = config.prefix_projection
        if self.prefix_projection:
            # Use a two-layer MLP to encode the prefix
            self.embedding = torch.nn.Embedding(config.pre_seq_len, config.hidden_size)
            self.trans = torch.nn.Sequential(
                torch.nn.Linear(config.hidden_size, config.hidden_size),
                torch.nn.Tanh(),
                torch.nn.Linear(config.hidden_size, config.num_layers * config.hidden_size * 2)
            )
        else:
            self.embedding = torch.nn.Embedding(config.pre_seq_len, config.num_layers * config.hidden_size * 2)

    def forward(self, prefix: torch.Tensor):
        if self.prefix_projection:
            prefix_tokens = self.embedding(prefix)
            past_key_values = self.trans(prefix_tokens)
        else:
            past_key_values = self.embedding(prefix)
        return past_key_values

在ChatGLMModel中调用并插入到每一个transformer模型层中。

class ChatGLMModel(ChatGLMPreTrainedModel):
    '''
    省略其它....
    '''
    def __init__(self, config: ChatGLMConfig, empty_init=True):
        if self.pre_seq_len is not None:
            for param in self.parameters():
                param.requires_grad = False
            self.prefix_tokens = torch.arange(self.pre_seq_len).long()
            # encode prompt
            self.prefix_encoder = PrefixEncoder(config)
            self.dropout = torch.nn.Dropout(0.1)

    # 调用prompt
	def get_prompt(self, batch_size, device, dtype=torch.half):
        prefix_tokens = self.prefix_tokens.unsqueeze(0).expand(batch_size, -1).to(device)
        # 调用prompt并返回
        past_key_values = self.prefix_encoder(prefix_tokens).type(dtype)
        past_key_values = past_key_values.view(
            batch_size,
            self.pre_seq_len,
            self.num_layers * 2,
            self.num_attention_heads,
            self.hidden_size // self.num_attention_heads
        )
        # seq_len, b, nh, hidden_size
        past_key_values = self.dropout(past_key_values)
        past_key_values = past_key_values.permute([2, 1, 0, 3, 4]).split(2)
        # past_key_values = [(v[0], v[1]) for v in past_key_values]
        return past_key_values

    # 返回transformer模型
    def get_layer(layer_id):
        return GLMBlock(
            self.hidden_size,
            self.num_attention_heads,
            self.layernorm_epsilon,
            layer_id,
            inner_hidden_size=self.inner_hidden_size,
            hidden_size_per_attention_head=self.hidden_size_per_attention_head,
            layernorm=LayerNorm,
            use_bias=True,
            params_dtype=self.params_dtype,
            position_encoding_2d=self.position_encoding_2d,
            empty_init=empty_init
        )
                
	def forward(
            self,
            input_ids: Optional[torch.LongTensor] = None,
            position_ids: Optional[torch.LongTensor] = None,
            attention_mask: Optional[torch.Tensor] = None,
            past_key_values: Optional[Tuple[Tuple[torch.Tensor, torch.Tensor], ...]] = None,
            inputs_embeds: Optional[torch.LongTensor] = None,
            use_cache: Optional[bool] = None,
            output_attentions: Optional[bool] = None,
            output_hidden_states: Optional[bool] = None,
            return_dict: Optional[bool] = None,
    ) -> Union[Tuple[torch.Tensor, ...], BaseModelOutputWithPast]:
    	# 其它代码
        if past_key_values is None:
            if self.pre_seq_len is not None:
                # 调用prompt
                past_key_values = self.get_prompt(batch_size=input_ids.shape[0], device=input_ids.device,
                                                  dtype=inputs_embeds.dtype)
            else:
                past_key_values = tuple([None] * len(self.layers))

            if attention_mask is None:
                attention_mask = self.get_masks(
                    input_ids,
                    device=input_ids.device
                )
    	# 其它代码
    	for i, layer in enumerate(self.layers):

            if output_hidden_states:
                all_hidden_states = all_hidden_states + (hidden_states,)
            # 准备参数传递到layer
            layer_past = past_key_values[i]
        	# 每个layer 是一个GLMBlock即transformer模型层
            if self.gradient_checkpointing and self.training:
                # 将prompt传递到每个层中
                layer_ret = torch.utils.checkpoint.checkpoint(
                    layer,
                    hidden_states,
                    position_ids,
                    attention_mask,
                    torch.tensor(i),
                    layer_past,
                    use_cache,
                    output_attentions
                )
            else:
                layer_ret = layer(
                    hidden_states,
                    position_ids=position_ids,
                    attention_mask=attention_mask,
                    layer_id=torch.tensor(i),
                    layer_past=layer_past,
                    use_cache=use_cache,
                    output_attentions=output_attentions
                )
        # 其它代码

参考

大模型微调之P-tuning方法解析

通俗解读大模型微调(Fine Tuning)

转载请备注出处:
https://www.cnblogs.com/zhiyong-ITNote/