首页 文章 精选 留言 我的

精选列表

搜索[脑洞落地],共10001篇文章
优秀的个人博客,低调大师

NFV落地要迈过哪些坎?

作为IT行业的一员,如果要问你,“网络业界最热门的创新技术是什么?”毫无疑问,SDN(Software Defined Network,软件定义网络)与NFV(Network Function Virtualization,网络功能虚拟化)将是那个异口同声的答案。它成为业界普遍看好的促进现网升级演进、未来网络技术创新的重要技术途径。 SDN/NFV可在数分钟内——而不是数天或数周时间——动态交付服务和新应用。作为网络演进的大趋势,其中NFV将在未来为运营商实现网络重构扮演重要的角色。 落实在运营商的业务创新上,基于NFV架构的网络中,业务部署只需申请云化资源(计算/存储/网络)、进而加载软件即可完成,网络部署和业务创新变得更加简单。 也许你要问,为什么是NFV?我们的网络怎么了? 让我们回顾下,在传统网络中,网络元件一般是由专用硬件加定制的软件绑定,耦合度极高,无法分离,比如防火墙设备、DPI设备和路由交换设备等。但采用专用硬件的传统网元价格昂贵,而且定制网元软硬件紧密结合,不易升级,无法灵活部署应用,维护成本也很高,显然阻碍了部署新业务的进程。随着互联网的发展,云计算场景等多种新场景的出现,对网络提出了更多、更灵活的要求。运营商等网络基础设施提供商急需灵活的网络来满足新业务的需求。 NFV——运营商网络的演进之路 所以运营商们提出了NFV来解决这一问题。NFV主张将网元的软硬件分离,然后通过将软件部署在通用硬件平台上实现具体的网络功能。如防火墙、DNS和NAT等网络功能均可以由软件交付,然后在普通的x86服务器上运行,从而实现传统网元的功能。 采用NFV解决方案可以减低投资成本(CapEx)和运维成本(OpEx),同时还可以提供更好的弹性和敏捷性,从而满足网络业务的需求,并加快新业务部署的速度。 价格更优的通用架构的硬件,势必将大大减少企业的投资成本。而且存储和计算资源等均采用通用硬件架构,使得不同的服务可以共享同样的基础设施,增加系统的通用性,降低运维难度。此外,专用硬件升级换代周期过长,无法快速更新迭代,而相对低廉的通用硬件的升级周期比专用硬件短,所以可以缩短硬件设备升级的周期,从而提供更好的网络性能。 采用部署VNF(Virtualized Network Function,虚拟网络功能)软件的方式,也会明显地降低管理运维成本。首先,通过修改软件功能可以快速支持新功能,而无需对复杂的专用设备进行维护和升级。其次,目前已有的云管理平台等管理系统可以提供自动化的部署和运维,从而极大地提升管理运维效率。而且,通过管理平台可实现VNF软件随业务迁移到任意通用架构的服务器上,从而实现网络业务随动的功能。 由于NFV软硬件分离,软件可以在通用的硬件架构上随需迁移,所以NFV可以带来更多的弹性和敏捷性。因为NFV支持通过修改软件快速实现网络功能以及自动化部署等优点,所以采用NFV方案将极大地缩短新业务上线周期。 NFV的坎 虽然NFV相比传统网元有以上提到的明显优势,但是采用存在性能瓶颈的通用硬件使其在性能方面远不如采用专用硬件的传统硬件。尤其在对性能要求极高的电信网络、以及核心网络中,NFV和昂贵的专用设备相比并没有优势。而NFV性能不足的关键因素在于通用硬件的CPU在处理转发上的性能远不如专用硬件采用的NPU(Network Processing Unit),所以目前NFV仅能部署在对性能要求不高的网络场景。 电信业务存在高吞吐和实时性要求,尤其是针对需要进行编解码转换、协议转换的数据面网元,采用虚拟化技术基于通用硬件和虚拟层软件通常会存在性能瓶颈,无法满足数据面高吞吐量要求,为了在NFVI上减少报文调度次数,降低网络转发延迟,提高网络吞吐量,需要提供转发性能加速机制。 虚拟化后,进出VNF报文的需经过虚拟层(如vSwitch)复制和转发,影响转发性能,特别是时延/抖动,进而会影响用户的业务体验,需要优化方案。 仅应用于低性能要求的网络场景当然不是NFV的最终目的,如何才能解决NFV性能不足的问题? 英特尔为NFV提速 许多NFVI厂商都采用独特的方式将性能优化集成到NFV基础设施里,但这个问题有其复杂性,它涉及I/O、操作系统内核、协议栈和虚拟化等多个层面对网络报文的优化处理技术。虽然IT界已发展出多类小众技术来应对,但这些技术对于普通应用技术人员而言比较陌生,即使对于传统网络的开发者而言,全面掌握这些技术也存在巨大的挑战。长久以来,用户更希望在这个领域有系统性的解决方案,能把相关的技术融会贯通,并系统性地组织在一起,同时也需要更为深入的细节技术支持工作。 英特尔联合第三方软件开发公司及时推出了基于Intel x86的架构DPDK(Data Plane Development Kit,数据平面开发套件),它的到来恰逢其时。DPDK是一组库和驱动程序的快速分组处理,它被设计为在任何处理器上运行,第一个支持的CPU是Intel x86,现在已扩展支持IBM Power 8,EZchip TILE-Gx和ARM。 作为一种内核旁路机制,DPDK允许虚拟交换机旁路内核并直接与兼容的网卡通信,实现了高效灵活的包处理解决方案。已经发展成支持多种高性能网卡和多通用处理器平台的开源软件工具包,成为通用处理器平台上影响力最大的数据平面解决方案和NFV加速领域的一种标杆技术。 DPDK采用轮询方式实现数据包处理过程,无中断,并通过零拷贝技术直接从内存读取数据包。这种处理方式节省了CPU中断时间、内存拷贝时间,并向应用层提供了简单易行且高效的数据包处理方式,使得网络应用的开发更加方便,最多可提升处理器10倍的性能。由于DPDK的存在,NFV的性能问题得到了有效的解决,极大地推动了NFV的发展进程。目前,基于DPDK的解决方案是解决NFV性能不足问题的最普遍的做法。 除了DPDK,英特尔还为网络转型提供了必要的构建模块,首当其冲的是英特尔架构(IA)处理器。例如,英特尔至强E5系列处理器具备专为虚拟化环境优化的卓越性能。 英特尔还提供了其他多种关键技术,其中QuickAssist加速技术能够为最多14个单独的虚拟化实例提供加速器服务(加密、压缩和算法卸载);英特尔虚拟化技术为虚拟化软件提供了硬件辅助支持,可显著降低其规模、成本与复杂性;具备英特尔流量导向器和网络覆盖功能的10/40/100 Gbit/秒的英特尔以太网技术能够在虚拟化环境中带来最高吞吐率。 看得出,NFV要堪当大任,英特尔帮到了“心坎”上! 原文发布时间为: 2016年06月12日 本文来自云栖社区合作伙伴至顶网,了解相关信息可以关注至顶网。

优秀的个人博客,低调大师

多模态测试落地实践深度解读

在AI原生应用爆发式增长的今天,智能客服、车载语音助手、AIGC内容审核平台、医疗影像辅助诊断系统等典型场景,已不再是单一文本或API接口的交互模式——它们融合了语音输入、图像上传、视频流分析、自然语言响应与界面反馈等多种模态。传统以UI自动化或API测试为核心的测试体系,正面临前所未有的挑战:如何验证语音识别是否在嘈杂环境下鲁棒?图像OCR结果是否受光照畸变影响?多轮对话中视觉提示与语音指令是否语义对齐?

优秀的个人博客,低调大师

vivo HDFS EC 大规模落地实践

作者:Gu Ruinan - 互联网大数据团队- Zhao Yongxiang Erasure Coding(简称EC),是一种纠删码。EC编码能够对部分缺失的数据进行数据恢复,广泛应用于存储与通信领域。在Hadoop3.0版本中,作为一种新的冗余存储的方式引入进来。使用EC编码的方式替代原来的三副本存储,保证数据可靠性的同时可以节约存储。相应地,付出的代价是读取性能的下降,对于访问频率不高的数据,使用EC编码很合适。 vivo目前HDFS集群节点达万台级别,数据规模接近EB级别,并且业务数据规模还在以较高速度持续增长中。在推进压缩算法缓解存储压力的同时,EC编码的推进也是存储降本的一大有力手段。 1分钟看图掌握核心观点👇 一、背景 Reed-Soloman编码(简称:RS码),是EC里一种经典的编码算法。下面简单介绍一下Reed-Soloman编码过程(不涉及数学原理的详细解析)。 假设我们的输入数据以D1,D2,...D5的向量来表示,矩阵B为编码矩阵,进行编码后得到D和C组成的矩阵,其中D为数据块(data block),C为校验块(parity block)。我们的数据写入都需要经过编码后才能进行存储。 假设我们抹除掉了D1,D4,C2。 我们能通过编码矩阵得到一个用于恢复的矩阵,将这个矩阵与剩余块相乘,可得到原来完整的输入数据,再次进行编码后可恢复C2。 二、存储布局的改变 EC编码对HDFS的应用,使数据块存储的结构发生了改变。 在传统三副本的策略中,一个文件被划分为不同的块(block)进行存储,一个数据块对应三个副本(replication),每个副本存储的内容完全一致,数据的存储时连续的,这种布局称为连续块存储布局(Contigous Block Layout)。 在EC策略中,一个文件被划分为不同的块组(Block Group)进行存储,一个块组内划分为多个内部块(Internal Block),其中,内部块又分为数据块(Data Block)和校验块(Parity Block)。数据块存储文件的数据,校验块存储由数据块生成的校验内容。一个块组内,可容忍的块丢失数量与校验块数量相同,如果丢失块的数量大于校验块数量,则数据不可被恢复。 在块组中,数据并不像三副本策略一样连续存储在一个块中,而是将连续的数据拆分为多个Cell,分散存储在不同的内部块中,形成一个个条带(Stripe)。这种布局称为条带存储布局(Striped Block Layout)。 我们集群目前采用EC策略RS6-3-1024k,其中6表示块组中数据块数量,3表示块组中校验块数量,1024k表示Cell大小。 三副本是HDFS默认的冗余存储方式,优点是当有机器宕机,数据丢失时,不会影响用户的读取,补块的方式也仅仅是副本的复制,简单高效。缺点也很明显,存储的冗余度高,三副本的存储冗余度达到200%。 EC编码通过编码的存储方式,来进行冗余存储。优点是存储的冗余度低(具体的冗余度取决于不同的存储策略),可靠性高。缺点是写入需要编码,造成性能的下降(大概3-4倍),补块时间长(校验块越多,补块时间越长),读取时如果遇到DN宕机,也需要额外的资源与时间进行解码恢复。 三、HDFS EC 码应用实践 3.1 兼容性问题 3.1.1 服务端 早在2020年,EC已经在vivo的HDFS集群中投入使用。EC是Hadoop3.0后推出的新特性,要想正常使用,服务端和客户端都需要升级到3.0或以上版本。 由于离线集群规模庞大,升级的调研和实施需要耗费比较长的时间。因此,我们临时搭建了一套基于3.1版本的冷备专用集群,使用EC来存储冷备数据,如下图: 冷备集群使用3.1版本的Yarn,可以同时访问热数据与冷数据,3.1版本的HDFS专门用来存储EC编码的冷数据。 由于新增冷备集群的方案增加了集群运维的成本,架构也不够优雅,只是暂时的解决办法。在2021年,我们离线集群完成了HDFS从2.6到3.1的全面升级,正式支持EC编码,在2022年,我们完成绝大部分冷备集群的数据到离线集群的迁移,增量数据全部写到离线集群中。 3.1.2 客户端 我们没有对Client2.x客户端访问EC文件做兼容性的开发,更多是通过推动用户升级客户端来访问EC文件,例如Spark2任务切换至Spark3任务。该方案增加了用户迁移的成本,但同时也减少了HDFS侧的开发成本,用户任务逐步往Spark3迁移也更符合未来的规划。 3.2 EC 异步转换 由于EC编码会带来对文件读写性能的下降,对EC编码的定位主要应用在冷数据的存储,业务并不直接写EC数据,而是采用后台转储的方式,把三副本数据转储成EC数据。对不同业务而言,对"冷"的标准都不一致,不能用统一的标准来衡量数据的冷热。在推广EC编码的过程中,平台并不用统一的标准来"强制"把用户数据转为EC,是否转为EC的最终决定权在用户。我们向用户提供分区访问频率的数据作为参考,帮助用户来了解不同分区路径的访问频次,让用户更好地选择哪些分区转为EC编码。用户可以通过大数据开发者平台(Big data developer platform)设置x天前的数据转为EC存储,后台程序会将相应分区通过Hadoop distcp,将三副本写入到已设置EC策略的目录中,再用新目录替换掉原目录,其中目录名称不变,保证了元数据一致,用户无需修改代码。 3.3 Distcp 数据校验 先来介绍一下HDFS两种校验和的方式。 3.3.1 MD5MD5CRC 此方式为HDFS默认的校验方式,这种校验方式会进行两次MD5计算一次CRC计算,从名字就可以反映出来。 块级校验和:所有chunk CRC的级联的MD5值。(an MD5 of a concatenation of chunk CRCs) 文件级校验和:所有块校验和的级联的MD5值。(the MD5 of the concatenation of all the block checksums) 由定义可知,这种方式对于HDFS分块大小敏感,不同的分块大小块级校验和不一样,导致文件校验和也会不一样。 3.3.2 Composite CRC Composite CRC一个新的校验和计算方式。 当计算块校验和不是简单地将chunk CRC进行级联(concatenation),而是将chunk CRC进行数学式的组合(mathematically compose),计算文件校验和时对文件所有的chunk CRC进行数学式组合。因此,对于文件校验和,该计算方式对于分块大小并不敏感。 CRC算法相关论文。 在数据进行distcp的过程中,HDFS会进行校验和校验,确保distcp的源数据与新数据一致,但正如前文所说,EC编码会带来存储布局的改变,相同的文件三副本与EC数据存储的块大小,块数量都不一致,这让HDFS默认的MD5MD5CRC的方式变得不再适用。 需要将校验方式改为COMPOSITE CRC。 可通过 dfs.checksum.combine.mode 改变校验和校验的方式(MD5MD5CRC(默认值) or COMPOSITE_CRC)。 即使distcp过程中会进行校验,为了确保万无一失,我们还会对前后的分区目录的校验和校验。(目录校验和计算方式为将目录下文件MD5值排序,再进行MD5计算)为了保证转EC前后文件的一致性,多加一道校验的"工序"是值得的。 3.4 文件损坏与修复 文件损坏与丢块是HDFS EC应用绕不开的一个话题,原因是在Hadoop EC特性新推出的过程中,有若干与文件损坏相关的bug。EC文件损坏的过程主要发生在补块阶段,计算结果的不准确导致了新补的块与原来的块内容不一致。我们在EC推广的过程中,也狠狠地踩过文件损坏的"坑"。如何避免文件损坏,如何对补块的结果进行校验,如何修复损坏文件是三个重要的需要解决的问题。 3.4.1 如何避免文件损坏 通过对社区的调研,我们打了若干的patch来解决文件损坏与丢块的问题。 3.4.2 对补块结果的校验 我们引入了HDFS-15759,Patch提供了一个对EC补块的校验功能,在DN执行补块任务时,对补块结果进行校验。如果校验失败会抛出异常,并且补块任务会进行重试。 3.4.3 EC批量校验工具 我们对开源的EC批量校验工具进行了定制化的改造,工具能够对EC目录进行批量扫描,扫描出目录中的损坏的EC文件,在此感谢Stephen O'Donnell对工具的开源。 原理大致如下,对数据块进行EC编码,通过比对新生成的校验块和原来的校验块,来验证是否存在文件损坏。如果比对通过,则没有文件损坏,如果比对不通过,则存在文件损坏。 工具支持MR,可以分布式执行,此外,也可只对一个条带进行比对,只生成校验块的第一个条带,比对与原校验块第一个条带是否一致,这些都大大提高了批量校验EC文件的效率。 工具地址: https://github.com/sodonnel/hdfs-ec-validator 3.4.4 修复损坏文件 在我们的集群,绝大部分损坏的文件都是ORC文件,ORC文件发生损坏时,由于其元数据分布的方式,会出现元数据的损坏,ORC无法解析。 假设一个块组内,数据块编号为1~6,校验块编号为7~9,数据块1损坏,我们可以通过读取数据块2~6加上任一一个校验块,得到"完好"的文件,对于ORC文件而言,判断是否完好取决于能否正常解析。 HDFS客户端get文件的时候默认只会读取数据块,我们通过改造HDFS客户端,使我们能够读取块组内指定编号的块,通过各种排列组合,得到一个"完好"的文件,之后将"完好"的文件覆盖掉HDFS上的损坏文件,来达到文件修复的目的。 3.5 机器异构&存储策略 由于EC数据访问频率低,将EC数据存储到大存储的机器上,利用机器异构降低我们的单位存储成本。 在HDFS中,如果文件写入的路径设置了hot存储策略的目录,则会优先把文件存储到disk存储介质当中,如果设置了cold存储策略的目录,则会优先把文件存储到archive存储介质当中。 因此,当我们将大存储机器的盘都设置为Archive,并且将EC目录设置为Cold存储策略,即可将EC数据存放到大存储机器上,使TCO降低,进一步实现存储降本。 四、总结与展望 vivo的HDFS集群已存有几百PB的数据采用EC-RS6-3-1024k策略存储,相比三副本EC-RS6-3-1024k方式能带来50%的存储收益,节省了数百PB的存储空间,为公司带来了巨大的收益。目前我们推荐用户将访问频次较少的数据转为EC,因为EC会带来读取性能的下降,如何减少EC带来的读取性能下降?以及后续细化对用户数据的冷热分层,对越冷的数据采用冗余度越低的EC策略,EC补块速度优化等,都是后续继续大规模推进EC需要解决的重要难题。

优秀的个人博客,低调大师

基于 KubeSphere 的运管系统落地实践

作者:任建伟,某知名互联网公司云原生工程师,容器技术信徒,云原生领域的实践者。 背景介绍 在接触容器化之前,我们团队内部的应用一直都是基于虚拟机运管,由开发人员自行维护。 由于面向多开发部门服务,而开发人员运维能力参差不齐,所以每次部署新的环境时往往都要耗费大量时间。 针对部署难的问题,我们将部分组件、服务容器化,采用 Docker 发布管理解决了部分问题,但仍未降低对开发人员的运维技能要求。 下面是我们基于虚拟机管理开发环境的流程: 从上图中我们也能发现当前架构存在的问题: 下发虚机由各部开发人员管理,虚机安全问题难以维护、保障; 基于 shell 运维,专业性过强; 基于手动打包、发布,耗时耗力且不可靠。 选型说明 针对上述提到的痛点,我们决定对运维架构进行改造。新建运管平台,技术选型整体基于云原生,优先选取 CNCF 项目。 Kubernetes 成为了我们平台底座的不二选择, 但 Kubernetes 原生的 Dashboard 不太满足实际使用需求。 而从头开发一套 workbench 又耗时耗力,由此我们目光转向了开源社区。 此时,一个集颜值 + 强大功能于一身的开源项目进入我们视野。是的,它便是 KubeSphere。 而 KubeSphere 愿景是打造一个以 Kubernetes 为内核的云原生分布式操作系统,它的架构可以非常方便地使第三方应用与云原生生态组件进行即插即用(plug-and-play)的集成,支持云原生应用在多云与多集群的统一分发和运维管理。 对于 KubeSphere 能否作为部署平台,最终结论如下: KubeSphere 虽功能强大,但更适合作为管理端使用,不太适合面向普通用户。 我们需要本地化一套 workbench ,简化部分功能,屏蔽专业性术语(如工作负载、容器组、安全上下文等)。 本地化部分内容如下: 基于企业空间、命名空间,本地化租户、工作空间的概念,一个租户(企业空间)可管理一个到多个工作空间(命名空间),并接入独立用户体系。 本地化应用发布流程: 由拆分的应用发布流程(构建镜像+创建负载),本地化为:创建应用 -> 上传 jar -> 指定配置 -> 启动运行的串行流程。 本地化链路监控:构建镜像预先埋点,创建应用时选择是否开启链路追踪。 本地化配置、应用路由等,添加版本管理功能。 事实上,我们本地化的重点是应用管理,但是 KubeSphere 功能过于强大、特性过于灵活,导致配置起来项过于繁琐。 针对部分配置项我们采用设置默认值的方式,而非交由用户去配置。(比如:容器安全上下文、同步主机时间、镜像拉取策略、更新策略、调度策略等) 改造后的运维架构如下: 实践过程 基于 KubeSphere 的运管平台整体架构如下: 环境信息表: 名称 版本 说明 kukekey v1.0.1 KubeSphere 安装工具 kubesphere v3.0.0 基于 K8s 的面向云原生应用的分布式操作系统 kuberentes v1.18.6 容器编排系统 docker v19.03.15 容器引擎 CentOS 7 操作系统 kernel 5.4 操作系统内核 本地化部署流程如下: 镜像本地化 1️⃣ 基于 harbor 搭建私有镜像库。 2️⃣ 离线下载并上传 kubesphere 依赖镜像至私有 harbor 内,project 名称保持不变。 3️⃣ 本地化 B2I 基础镜像,本地化如下内容: 内置 Arthas,便于调试; 内置 SkyWalking Agent 用于集成链路追踪; 内置 Prometheus Agent 用于指标监控; 添加 windows 字体。 4️⃣ 本地化应用商店初始化镜像(openpitrix/release-app)。 由于预置的 chart 有很多我们实际并未使用,所以我们删除预置了 chart ,并导入实际所需 chart (包括本地化的中间件 chart 、中台 chart) 5️⃣ 镜像 GC。 针对频繁构建的 repo ,配置合理的 GC 策略: 搭建 K8s 基于 KubeKey 1.0.1 部署了三主多从节点 K8s v1.18.6 集群: 搭建 Rook 集群 使用 KubeKey 1.0.1 新增三个存储节点并打上污点标签,搭建 Rook 集群 对于存储的替换主要出于以下方面考虑: 有 Ceph 裸机部署使用经验; 对比默认存储 OpenEBS Local PV,Rook 支持多存储类型; Rook 为 CNCF 毕业项目。 搭建 KubeSphere 平台 基于 KubeKey 1.0.1 部署了 KubeSphere,未作本地化修改。 CI/CD 实践 CI/CD 部分我们并没有使用 KubeSphere 提供的流水线功能,而是选择 gitlab-runner + ArgoCD 方案。 CI 实现 CI 部分利用 gitlab-ci 切换构建时特性,我们抽象出了 provider 概念。provider 本质为工具 / 程序的容器化封装,提供某一方面能力了。如: maven-provider: java 程序构建时环境,内置私有 nexus 配置; npm-provider: nodejs 程序构建时环境,内置私有 npm 源配置; email-provider: smtp 交互程序,用于邮件通知; chrome-headless-provider: 浏览器截屏。 使用时,只需引用并传递相应参数即可: variables: AAA: xxx BBB: yyy stages: - build - scan - email build: stage: build image: harbor.devops.io/devops/maven-provider tags: - k8s-runner script: - mvn clean package only: refs: - develop changes: - src/**/* scan: stage: scan image: harbor.devops.io/devops/sonar-provider tags: - k8s-runner script: xxx rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' email: stage: email image: harbor.devops.io/devops/sendmail tags: - k8s-runner script: - /work/send-mail sonar --email-to=$EMAIL_TO_LIST --email-cc=$EMAIL_CC_LIST --sonar-project-id=$PROJECT_NAME --sonar-internal-url=$SONAR_INTERNAL_ADDR --sonar-external-url=$SONAR_EXTERNAL_ADDR rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' CD 实现 CD 部分,我们利用 chart 对应用进行定义,并将 chart 剥离于开发库,独立于配置库进行管理,用于 ArgroCD 同步。 对于配置库与开发库分离,主要出于以下考虑: 清晰分离了应用程序代码与应用程序配置。 更清洁的审计日志:出于审计目的,只保存配置库历史更改记录,而不是掺有日常开发提交的日志记录。 访问的分离:开发应用程序的开发人员不一定是能够 / 应该推送到生产环境的同一个人,无论是有意的还是无意的。 通过使用单独的库,可以将提交访问权限授予源代码库,而不是应用程序配置库。 自动化 CI Pipeline 场景下,将清单更改推送到同一个 Git 存储库可能会触发构建作业和 Git 提交触发器的无限循环。 使用一个单独的 repo 来推送配置更改,可以防止这种情况发生。 角色划分 角色方面,我们定义了三种类型角色,职责如下: 使用效果 通过引入 KubeSphere 平台以及 CI/CD,效率提升明显: 计算资源池化,不再下发虚机,计算资源统一运管; 基于容器化的流水线构建、发布应用,保障了构建的可靠性,同时解放双手; 基于本地化 workbench 运维,由于屏蔽了专业性词汇术语,降低使用者学习成本。日志查看、应用更新等操作更为便捷; 针对角色的划分,使得运维边界清晰,责任明确。 问题 & 解决 在一年多的容器平台使用过程中,我们遇到了蛮多的小问题,这里我举几个有代表性的例子: B2I 没有清理策略 存在问题: 在使用 kubesphere v3.0 的过程中我们发现:不断通过 B2I 构建应用,会产生大量的 B2I 任务记录,并且 minio 内上传的程序包文件越来越多,且并没有相应的清理策略。 解决方案: 开发定时 job , 定期进行清理。 内核版本过低,导致容器相关漏洞的发生 存在问题: 初期,我们使用 CentOS7 默认的 3.10 版本内核。 解决方案: 升级内核版本至 5.x。 链路追踪 存在问题: KubeSphere 预装的 jaeger 不支持 dubbo 协议,无法对 dubbo 应用进行监控。 解决方案: 利用 SkyWalking 用于链路追踪,并在基础镜像内埋点。 报表相关服务缺少字体 解决方案: 将缺少 windows 字体安装至 B2I 基础镜像内。 路由集群外服务 由于部分应用部署于 K8s 外部,针对这部分应用我们选择 Endpoint + ExternalName + Ingress 的方式进行路由。 未来规划或展望 1️⃣ 有状态应用的 Operator 开发 当前有状态应用依赖 helm hook 管理, 且功能单一。 未来我们计划,针对常用有状态应用,开发对应 operator,提供创建、扩容、备份等常用功能。 2️⃣ CNI 迁移至 Cilium 选取 Cilium 替换 Calico 主要出于以下考虑 : Cilium 为 CNCF 毕业项目,活跃度高; Cilium 基于 eBPF 实现,在粒度和效率上实现了对系统和应用程序的可观测性和控制; Cilium 安全防护功能更强,提供了过滤单个应用协议请求的能力,例如 : 允许所有使用 GET 方法和 /public/.* 路径的 HTTP 请求,拒绝所有其他请求; 允许 service1 在 Kafka 主题 topic1 上生产,允许 service2 在 topic1 上消费,拒绝所有其他 Kafka 消息; 要求 HTTP 报头 X-Token:[0-9]+ 出现在所有 REST 调用中。 3️⃣ cri 由 Docker 替换为 Containerd 4️⃣ 容器文件浏览器功能开发 当前阶段,开发人员下载容器内文件的需求,只能由运维人员使用 kubectl cp 的方式协助获取,后续我们规划开发容器文件浏览器相应功能。 5️⃣ 容器宿主机系统替换为 rocky,以应对 CentOS 停止维护。 本文由博客一文多发平台 OpenWrite 发布!

优秀的个人博客,低调大师

优酷弱网平台落地实践

作者:孙长浩(火炏) 弱网环境下的质量保障一直是公认的难题,实际生活中每个人都会遇到弱网环境,比如用户在景区地铁里,高铁上,电梯中,景区周边等场景使用APP大概率都会遇到弱网场景。优酷作为视频内容APP,对网络的要求特征为持续时间长,带宽平稳等,所以对弱网环境尤其敏感。在弱网环境下,用户会遇到诸如卡顿、停止播放等体验问题。我们通过分析埋点数据可以清晰的看到目前线上的错误码中,网络(弱网)相关的错误码类型占比已经超过一半以上。因此,为了提高版本上线质量,有效的模拟线上网络环境,弱网环境下的测试是不可或缺的线下测试组成部分。 基于此,优酷弱网平台从业务的实际痛点出发,针对弱网进行标准化的分级定义,对场景进行精确测量,对线上回溯数据进行精准回放,并对线下/线上弱网模型匹配训练。通过平台化的方式,提供统一的使用和接入方法,不断积累和沉淀更明确的衡量指标以及合理性的标准判断,给测试和开发人员提供更有效的弱网仿真模型。本文就将结合业务场景,展开聊聊优酷弱网测试平台的控制原理、技术实现以及具体业务的使用情况。 弱网认知及原理 弱网认知 弱网没有严格的指标进行定义,实际可以理解为用户在实际使用个人业务时因信号波动、网络拥堵等原因造成的业务使用体感差,从而进行的一种体感性描述。 根据用户的实际场景,造成弱网的原因一般有两种: 物理硬件导致:比如离路由器过远,信号强度低,也有周边干扰大,导致误码率高等情况均会导致用户弱网; IP网络传输性能弱:比如网络节点性能过载,运营商网络限制,跨网传输等等。 可参考下图进行理解 通过上图两种场景可以看到整体网络构造比较复杂,存在模拟难、无法量化的问题,无法制定统一标准。因此,我们尝试通过其他方式来进行量化。通过参考 RFC2544 文档,我们得知衡量网络性能好坏的方法可以通过吞吐量、丢包率、延时、背靠背四个维度进行衡量,定义标准。因背靠背主要测试转发能力,因此大多数采用前三项进行衡量。 弱网控制原理 由下图TCP/IP协议传输过程,弱网控制主要有两种场景:硬件控制和软件控制。 一、硬件控制 主要是通过信号衰减器和噪声发生器进行控制,通过进行信号的衰减以及噪声的大小控制网络中误码率的增高,从而影响应用层接收信号的延时,带宽和误码,目前做wifi性能测试项目主要是使用这个方法,但此种方式目前仅可以定性控制,做不到定量的控制。 二、软件控制 目前主流只通过Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制。 接收包从输入接口进来后,经过流量限制丢弃不符合规定的数据包,由输入多路分配器进行判断选择:如果接收包的目的主机是本主机,那么将该包送给上层处理,否则需要进行转发,将接收包交到转发块(Forwarding Block)处理。转发块同时也接收本主机上层(TCP、UDP等)产生的包,通过查看路由表,决定所处理包的下一跳。然后,对包进行排列以便将它们送到输出接口。一般只能限制网卡发送的数据包,不能限制网卡接收的数据包,所以可以通过改变发送次序靠控制传输速率。Linux流量控制主要是在输出接口排列时进行处理和实现,如下图所示: 目前大部分路由器以及树莓派都是使用这个方式。另有一些第三方设备厂商提供的设备,大多也是基于此种模式做的,只是在上层进行了更多的一些封装。此种方式可以做到定量的控制,而做不到定性的控制,因此优酷弱网平台从用户实际场景出发,分别支持量化的软件控制和定性的硬件弱网控制。 优酷弱网平台技术实现 平台网络拓扑 为了可以让每个用户很方便的使用弱网平台,经多次评估及讨论最终采用网络代理的方式,进行网络流量的拦截和控制,这样的好处是有较强的通用性,无论是Android 还是iOS以及windows系统均自带网络代理功能,因此用户侧直接在各端设置网络代理并免安装应用即可直接使用,具体的网络拓扑图如下: 平台分层功能架构图 优酷弱网平台开发采取分层实现模式,总体分三层: 底层物理层采用真机及屏蔽箱模式,可以直接对屏蔽箱的真机进行弱网信号控制; WIFI弱网控制层,通过TC服务器的方式进行控制; 用户前端页面提供设备及场景管理,状态展示等功能。 平台功能及业务应用 平台可支持弱网测试范围 从app的角度看,弱网测试的范围是非常广的,同时对于app的优化也非常重要,下图是对弱网常用的测试项的一些功能梳理,目前平台针对这些弱网的测试都是可以支持的。 弱网分级标准化定义 大多数开发者对于弱网定义仅限于差、好、坏等这样的方式来进行描述,这样的描述仅仅是一种定性方式,鉴于很多开发解决问题,也仅仅分析到此,一句网络问题,后面问题就不了了之,优酷弱网平台通过对于弱网参数的分级量化定义,很轻松的就能进行一些性能对比,让开发有针对性优化。 分级量化弱网如下图: 下图是不同分级的量化弱网数据的对比,很容易就能找到产品的差异点: 通过上图,可只低网速场景和高丢包场景,优酷app还有可以提供产品体验优化的地方。 优酷弱网体验持续优化 优酷业务主要是音视频播放,对网络稳定性的要求非常高,因此在弱网优化这一块,也积累的一些经验,主要从网络数据采集出发,针对用户实际的网络状况进行采集。在弱网策略层,对采集到的网络数据进行弱网状态的进入及退出进行策略判断,当用户进行弱网状态时,通过线下数据的策略匹配,对线上用户实际的场景进行匹配,最终达到网路优化的效果,具体可参考如下图: 一、用户弱网场景定义 优酷弱网场景:用户在看优酷视频时,在什么样的时间和地方遇到了导致用户播放出现加载时间过长或者无法起播的问题,该场景有规律性和确定性。 基于上述优酷弱网场景,我们进行弱网的一些特性测量,并基于测量数据,我们在实验室进行用户真实的场景模拟,下图是对用户场景的一部分实测模拟。 下图是对用户场景的波形回放及实际测试效果: 二、弱网持续优化过程 通过在弱网实验室进行重现用户是播放loading或者无法起播现象,比如同样检测到用户在地铁会播放会loading。可以根据用户的场景检测,进行地铁前提前大buffer缓存,或者提前提示用户缓存等各种方式,一旦用户有弱网场景会进行策略命中及优化,主要流程图如下: 通过用户在弱网具体场景的优化和策略匹配,用户在弱网场景播放上的体验有了持续提高。 真机弱网 4G信号和WIFI信号,不同的信号源有天然的区别,因此在4G网络情况下进行弱网测试,所需要的环境更为复杂,需要专门的屏蔽室,所需要的成本更高,优酷弱网平台采用屏蔽柜+真机平台+衰减器方式提供真实的弱网场景,用户在真机平台上可以一键用户真实的进行弱网模拟。 下图为:支持信号衰减的屏蔽柜 下图为:信号衰减场景 下图为:在不同信号衰减情况下,下载速率的一些关系图: 全国网络的单点接入能力 在我们实际业务中,由于运营商网络,CDN拥堵等各种原因,常常发生单点的网络问题,优酷弱网平台通过直接代理到全国各地市的方式,可以快速定位单点问题,并高效解决。 各弱网方案对比 总结及展望 优酷弱网仿真平台,通过代理的方式、平台化的服务,极大突破弱网测试所需的环境限制,目前已做到了弱网随时可测,然而5G网络、IPV6网络、IOT设备的大量部署,我们面临的网络环境更加复杂,同时网络拓扑也越来越复杂,如何能在实验室对这些网络的仿真依旧是一个难题。另外线上网络的问题,如何进行自动化的定位和恢复也是一个需要持续研究的内容,弱网平台以后将在这些方向进行发力。希望未来更多的对网络有兴趣的同学,一起成长为网络方面的专家。 关注【阿里巴巴移动技术】微信公众号,每周 3 篇移动技术实践&干货给你思考!

优秀的个人博客,低调大师

GraphQL前后端落地入门尝试总结

前言:首先要明白的是GraphQL是用来干嘛的也就是是解决什么问题的,其实就是解决传输数据的可定制化,减少后端api的开发量。举个例子:比如你获取一个用户列表,后端开发了一个叫getUserList接口,参数是parentId,返回的数据结构是这样的:[ { name, id , logo , address } ],后来又有个业务只要数据结构是这样的就可以了:[ { name} ],这个时候要么后端重新开发一个接口,要么就是直接用getUserList,但是造成了数据浪费和网络传输成本浪费,为了解决这个问题GraphQL就被Facebook创造了出来,即能复用getUserList也不造成各种浪费。 后端(使用的是nodejs,express) 1、安装依赖:npm install express-graphql -S ; npm install graphql -S ; 2、单独个目录做route接口,index.js统一导出,方便以后代码膨胀进行分块,如图 3、开始写具体的业务代码,拿我的base-graphql.js举例 // 也可以在不使用 GraphQL Schema Language 的情况下实现相同的 API: const { graphqlHTTP } = require('express-graphql'); const graphql = require('graphql'); const { createBaseDb, createUserDb } = require('../utils/db-util'); //创建db对象 const DBBase = createBaseDb(); // 定义 数据库对应的User类型 const UserType = new graphql.GraphQLObjectType({ name: 'User', fields: { id: { type: graphql.GraphQLInt }, version: { type: graphql.GraphQLInt }, create_date: { type: graphql.GraphQLString }, update_date: { type: graphql.GraphQLString }, update_user: { type: graphql.GraphQLInt }, name: { type: graphql.GraphQLString }, email: { type: graphql.GraphQLString }, server: { type: graphql.GraphQLString }, username: { type: graphql.GraphQLString }, password: { type: graphql.GraphQLString }, } }); const UsersType = new graphql.GraphQLList(UserType); // 定义查询对象类型,对应post查询传参: query:{user(id:"a"){id,name,age},hello(name:"charming")} const QueryType = new graphql.GraphQLObjectType({ name: 'Query', fields: { queryUser: { description: 'query user', //resolve返回的数据类型 type: UserType, // `args` 描述了 `user` 查询接受的参数 args: { id: { type: graphql.GraphQLString, } }, resolve(parentValue, args, request) { //查一个表的所有数据 let data = new Promise((resolve, reject) => { DBBase.all("select * from user", (err, res) => { if (err) { reject(err) } else { resolve(res[0]) } }) }); return data; } }, queryUsers: { description: 'query users', //resolve返回的数据类型 type: UsersType, // `args` 描述了 `user` 查询接受的参数 args: { id: { type: graphql.GraphQLString, } }, resolve(parentValue, args, request) { //查一个表的所有数据 let data = new Promise((resolve, reject) => { DBBase.all("select * from user", (err, res) => { if (err) { reject(err) } else { resolve(res) } }) }); return data; } }, //可以定义多个 hello: { description: 'a hello world demo', type: graphql.GraphQLString, args: { name: { // 这里定义参数,包括参数类型和默认值 type: graphql.GraphQLString, defaultValue: 'Brian' } }, resolve(parentValue, args, request) { // 这里演示如何获取参数,以及处理 return 'hello world ' + args.name + '!'; } } } }); // ====================================下面时修改数据================================= // 输入参数类型 const UserInputType = new graphql.GraphQLInputObjectType({ name: 'UserInput', fields: () => ({ name: { type: graphql.GraphQLString }, email: { type: graphql.GraphQLString }, username: { type: graphql.GraphQLString }, password: { type: graphql.GraphQLString }, }) }); const MutationType = new graphql.GraphQLObjectType({ name: 'Mutation', fields: { addUser: { //参数样式 mutation {addUser(one:{id:"s",name:"alice",age:12,male:false}){id,name,age}} type: graphql.GraphQLString, // `args` 描述了 `user` 查询接受的参数 args: { one: { type: UserInputType } }, resolve(parentValue, args, request) { let sqlStr = `insert into user (create_date,version,name,email,username,password) values ( '${new Date().toISOString()}', 0, '${args.one.name}', '${args.one.email}', '${args.one.username}', '${args.one.password}' )`; return new Promise((resolve, reject) => { DBBase.run('BEGIN TRANSACTION;'); DBBase.run(sqlStr, async (err, res) => { console.log("insert user ", err, res); if (err) { DBBase.run("ROLLBACK;"); reject(err) } else { //添加成功后,创建对应的用户数据库 try { await createUserDb(args.one.email); DBBase.run('COMMIT TRANSACTION;'); resolve(res) } catch (error) { console.log(error); DBBase.run("ROLLBACK;"); reject(err) } } }); }); } }, } }); const schema = new graphql.GraphQLSchema({ query: QueryType, mutation: MutationType }); module.exports = graphqlHTTP({ schema: schema, graphiql: true /* true代表需要调试 */ }) 上面注释写的也比较清楚,简单说下, 这里它提供了GraphQLObjectType来定义对象数据类型的描述,如果是数组必须使用GraphQLList再进行构建,然后你就可以用你构建的来声明你要返回的类型,但是参数类型不能使用这个,必须是GraphQLInputObjectType这种input相关的来构建。 还有resolve方法里是需要你直接return结果的,db的操作其实都是异步的,所以需要你用promise来解决 这个问题,当你的业务涉及事务等比较多db操作是async/await可能更方便,其他的用法就看官方文档吧,这里就不展开了。 例子中 我按功能来划分了模块,我综合思考了,还是觉得这样的普适性和开发难度是最好,对于一些复杂的大型项目肯定还是需要进行调整的。 好了到这里,你就可以直接用postman看看效果了 记得参数那里不要是form-data,一定选的是GraphQL(这个我猜想就是form-data等这种现有的形式来做这个可能有点别扭,所以干脆另外定了一个格式),查询参数类似这样:query {queryUsers(id:"a"){id,name,email}},修改参数类似这样:mutation {addUser(one:{name:"jack",email:"jack@qq.com",username:"jack",password:"123456"})};不用postman也可以用自带的,直接访问https://localhost:3001就可以了 。 写到这里你可能会想到现有的类似axios这种的框架不能用了,对的,必须要换成apollo-client这种支持的。所以如果是成熟项目要替换成GraphQL还是需要成本的。

优秀的个人博客,低调大师

三招为AIOps落地开个好头

面对激烈的市场竞争,企业意识到必须在业务与IT之间建立一条通畅的“纽带”。作为制定企业发展规划与战略路线的两大支柱,IT部门应当成为业务部门的重要合作伙伴与助力。 IT部门的诞生与早期的大型机同步,当时其基本作用仅限于“速度与馈送”。但在之后的发展过程中,开明的CIO们开始与业务负责人主动合作,着力思考运营指标对下游业务的实际影响。这种将生态系统可观察性及运营指标、同业务成果关联起来的能力,不仅代表着明确的竞争优势,同时也是企业实现转型与快速创新的必要条件。 但说起来简单,我们该如何一步步迈向这个终极目标? 目前衡量IT绩效的方法主要分两种:效率与效能。效率衡量的是IT性能,通常以速度、可用性与吞吐量为指标。另一方面,效能表达的则是IT部门对于业务产出的影响能力。很明显,业务部门更熟悉效能这类指标,具体涵盖可用性、客户满意度、客户转化率与财务指标等等。谁能达成这些目标,谁就能维持高于市场平均水平的增长率、为股东提供价值并为客户提供助力。 传奇大师Peter Drucker在畅销书《卓有成效的管理者》当中,解释了效率与效能之间的区别。虽然他的结论诞生于1966年,但仍然经受住了时间的考验。Drucker认为,二者可以分别理解为“把事做对”和“做对的事”。以CIO职能为例,把事做对最重要,而做对的事代表设定正确的目标以推动业务发展,属于达成目标的一种前提性思考。 事实证明,IT价值往往在预算与人员配备方面有所体现。在解释价值的过程中,CIO其实是在证明自己如何理解系统、服务/应用乃至客户群体对业务成果所产生的直接影响——例如客户转化、净推荐值(NPS)所量化的客户忠诚度,以及最终收入与盈利能力。他们可以在服务与客户的背景之下,证明IT支出的合理性。以此为前提,我们快速梳理一下哪些指标无法证明IT价值,而哪些能够准确体现IT的回报。 IT管理中经常会用到正常运行时间与服务水平协议(SLA)等指标,但这些显然与高管层无关。相反,更具意义的IT指标应该指向创新与扩展能力,例如新服务发布时间(TTNS)等指标。另一个重要指标,则是证明IT方案应对变更的能力。如今,敏捷企业已经将数字化服务纳入日常运营当中。过度频繁的变更与创新往往导致服务故障,并严重影响客户体验。一旦受到影响,客户很可能削减采购数额甚至考虑转向新的服务商。面对这类问题,IT需要在故障响应速度与创新发布速度之间取得平衡点。理想情况下,IT部门应该在客户受到实际影响之前检测并响应故障。虽然IT无法彻底消灭故障,但往往能够率先识别到问题的存在、并运用知识预防潜在的严重后果。 为了提升这种效能,现代CIO开始采用AIOps。AIOps是指将人工智能与IT运营整合起来,具体涵盖大数据分析、机器学习(ML)以及其他各类人工智能(AI)技术,借此自动识别并解决常见的IT问题。举例来说,IT人员可以使用AIOps衡量变更操作引发意外事件的频率,并将事件与特定客户群体关联起来。IT团队还可以进行假设性分析,甚至在客户遭遇实际故障前自动完成响应。通过这种前瞻性的识别与应对能力,AIOps即可防范后续发生类似故障、改善IT指标。这种主动管理能力不仅可以改善客户体验,同时也可通过NPS进行效果量化。最终,运营成本将由此降低、客户更乐于接受新服务,同时也保证技术措施更易被高层管理人员所理解及接纳。 效率与效能,可以说是CIO职能定位的核心。要想与业务部门开展良好合作,CIO必须立足特定时间段判断哪些内容对业务更为重要,而后据此注入资源以确保IT体系拥有必要的技术与人才。只有将IT与业务部门的优先级事务统一起来,双方才能真正建立合作关系、保证CIO“做对的事”。结合实践,我们发现以下三个步骤可以作为企业探索AIOps的理想起点: • 打好第一仗:清点您的系统与流程,找到其中重复、笨拙且效率低下的系统流程。消除及简化这类流程,可帮助您提高业务效率。 • 关注正确数据:很多数据与业务并没有什么关联。因此,请保证只记录最具价值的用例以及最值得解决的问题,而后判断解决过程需要哪些数据。这项实践的意义,在于引导我们将精力集中在正确的数据身上。 • 绘制生态系统图:明确整个企业生态系统中的各跨职能团队。通过这份系统图,我们可以明确谁需要参与协作,而后据此汇总数据以训练模型。 希望这三项提示,能帮助大家成功迈出AIOps探索之旅的第一步。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册