-
在容器化日益成为中大型企业上云主流选择的情况下,容器服务如何能帮助用户更简单快捷的上云、高效可信赖的运维?为了更好的解决这个问题,CCE用户体验团队在今年进行了大量的用户现场调研,聆听用户的声音。围绕行业普遍存在的配置复杂门槛高、运维信息分散效率低、升级难度大等问题打造全新CCE体验,提出“易用:一站式集群配置,开箱即用”、“场景化:聚焦用户场景,无跳出运维管理”和“透明化:所见即所得,将复杂的过程透明化”的设计理念,同时融合了华为云全新设计语言,为用户打造集群开箱即用、异常快速高效定位、任务透明可信赖的容器化上云体验。图1 容器化体验改进为了持续提供更好的产品体验,我们非常期待您对CCE产品的评价,如果您有任何的建议,欢迎通过页面底部的“意见反馈”向我们反馈,我们会认真听取您的宝贵建议。设计语言焕新升级CCE服务控制台应用了华为云全新的设计语言,这套设计语言的核心特点是更加贴近用户使用感知、着力提升用户使用友好性、降低使用难度,围绕用户关注点构建信息展现结构,构建更加友好、便捷的使用体验。直观、聚焦:关键信息抽取,同时减少页面复杂色,清晰直观,希望可以帮助用户更聚焦重点。图2 集群列表优化场景化:基于用户实际场景的有效信息汇聚,无需跨服务跳页面。图3 云原生观测优化易用:一站式集群配置,开箱即用不少用户反馈容器技术门槛相对较高,很多繁杂的配置用户自行摸索起来,效率低。日志等一些服务的开通和使用,需要到不同的服务里多次跳转等。针对这些复杂的配置问题,我们推出配置中心。在配置中心里,将配置项进行分类,方便用户统一管理同一类型配置。针对具体的配置项,我们提供配置解释、配置建议、给出配置风险,帮助用户“自己搞定”配置。图4 配置中心优化在运维管理上,我们推出云原生观测中心,实现运维管理的开箱即用。云原生观测中心将监控、日志服务集成进CCE服务,用户可以在CCE的页面内完成监控、日志的一键开通,并且在使用过程也不需要跳出CCE服务。图5 日志管理优化场景化:聚焦用户场景,无跳出运维管理在实地拜访中,我们发现工程师近80%的工作场景都在进行运维相关的工作。而之前CCE提供的是基础的监控能力,用户需要跳转去应用运维管理服务,查看详细监控和告警。围绕查看监控、告警的场景,我们希望用户能更聚焦对应的资源对象,我们提出“以应用为中心,构筑端到端的一站式运维体验”的设计理念。围绕集群、节点、负载和Pod,我们提供融合了资源健康度和监控的独立运维页面,方便用户聚焦关注的资源。用户在一个页面即可快速评估资源健康度和异常项,同时查看各层级完成监控。图6 监控中心优化围绕告警,CCE集成了应用运维管理的告警通知和告警规则、消息通知服务的联系人管理,用户无需跳转,即可在CCE快速查看处理告警和进行配置。图7 告警中心优化透明化:所见即所得、将复杂的过程透明化像集群升级等关键操作,具体变更点及影响相对模糊,容易引起用户顾虑。对于此类操作,我们通过信息预先告知、过程可视可回退等设计理念,让用户有充分的知情权和掌控感,降低用户顾虑。以集群升级为例,由于用户未清晰感知相关原理和可能存在的影响,升级过程不感知进度细节,不敢轻易升级。本次优化中,我们通过可视化等手段预先为用户呈现讲解原地升级的概念和原理,告知用户升级对插件等功能的影响,降低用户顾虑。图8 集群升级流程展示图9 集群升级插件影响同时对于升级过程,如升级检查,拓扑图形式呈现检查过程,用户可感知资源视角的进度和异常情况。图10 集群升级过程可视化对于升级过程,用户如果遇到异常,可以随时调出伴随式监控,辅助定位问题,无需跳转查看监控。图11 集群升级过程监控未来愿景华为云CCE致力于为用户提供配置更简单、管理更便捷、流程更透明的容器服务。未来我们将持续打磨CCE的使用体验,力争为用户带来更多价值。如果您有任何的建议或意见,可以通过页面下方的反馈意见告知我们,您的任何意见对我们来说都很重要。
-
华为云云容器引擎(Cloud Container Engine,简称CCE)服务Kubernetes版本支持策略将进行优化,从Kubernetes 1.27版本开始,CCE将对每个社区版本均提供商用支持。CCE集群1.27版本计划于2023年10月正式商用,CCE集群1.28版本计划于2023年12月支持。图1 版本支持策略升级CCE 提供高度可扩展的、高性能的企业级Kubernetes集群。借助云容器引擎,您可以在华为云上轻松部署、管理和扩展容器化应用程序。服务体验请访问:cid:link_0云容器引擎CCE
-
作者:华为云云原生团队随着业务的全球化发展和应用多元化部署的趋势,越来越多的客户选择通过混合云、多云模式来进行业务部署。选择多云进行部署可以提高部署业务的基础设施稳定性,在单个供应商基础设施出现故障或者访问流量激增时,可以通过配置跨云弹性来提高业务的高可用性,同时,多云还可以避免企业的技术架构被厂商锁定。尽管使用多云的优点很多,但管理多云集群和在多云的场景下发布应用却面临诸多问题和挑战。多云场景下集群管理和应用交付的挑战1、多集群基础设施的管理及一致性发布面临的挑战。例如,在多集群场景下的网络策略的配置,TLS证书的发布及更新管理。在现代应用程序的部署步骤中,SSL/TLS证书是很重要的一环。但在部署应用程序时,管理证书的续订通常是事后才想到的。证书的生命周期从90天到13个月不等,为了保持安全访问,这些证书需要在到期前更新/重新颁发。鉴于大多数 Ops 团队工作繁杂,证书更新有时会被遗漏,这会导致应用间不能正常访问和工作。在多集群场景下,运维团队会每个供应商集群重复上述过程进行证书更新;而通过 GitOps 结合 Cert-manager[1]、Nginx Ingress Controller 可以一致的、统一的管理证书的自动化更新[2],大大提升 Ops 团队的运维管理效率 。2、由业务场景侧需求和集群基础设施差异性带来的差异化配置挑战。根据应用程序的业务场景诉求不同,不同集群部署的业务版本,更新频率会存在不同。例如同一餐厅在不同地域的点餐系统可供给的菜单种类,菜单上新会有差异;或由于跨国公司在不同国家推广策略不同,新的业务软件仅需要部署至部分城市所在集群等。同时,由于业务部署的基础设施不同,应用程序部署到集群的底层架构、网络连接性、计算存储性能表现可能多种多样。例如同一份应用配置在被差异化渲染后可以被交付和托管在云上的CCE、EKS集群、客户本地数据中心中的集群(存在断连情况)、边缘端无人机的集群上(半连接集群)以及太空中卫星链所组成的集群(短时连接集群)。因此根据每个集群的性能指标(CPU、Memory)不同,部署业务应用的实例副本数可能会不同;根据每个集群的网络连接情况不同,设置部署业务的版本更新周期,高可用设置(访问某个服务的超时重试次数等)会产生差异;根据每个集群的使用目的不同(早期生命周期阶段的集群通常由开发人员管理,而实际的预发及生产集群的可能由客户的运维团队管理),部署业务的版本和数据库连接池等变量也会存在差异。因此当有M个应用需要交付至N个集群环境中时,差异化配置的复杂度会呈M×N维度爆炸增长。3、使用 UI 控制台方式交付应用与各厂商控制台风格各异、难以编排大规模微服务交付之间的挑战。随着微服务规模变大,依赖UI控制台进行应用交付的方式变得复杂臃肿,其交付的顺序编排依赖人工,无法做到自动化;且无法进行审计和版本控制。4、缺乏统一的应用观测视角的挑战。在多云集群场景下,当前缺乏统一的视图帮助客户查看应用在多集群的部署情况、应用的健康状态及异常状态定位。 使用UCS GitOps配置管理来交付您的多云应用 为了应对上述多云集群管理和多云应用交付的挑战,UCS 推出了基于 GitOps 理念的跨集群配置管理和应用分发的功能。通过它你可以屏蔽底层环境差异和多个管理入口,将多个集群环境的配置和治理集中于一处,以自动化的体验完成多集群基础设施的管理以及多云应用的发布及更新。GitOps 的概念最早由 Weaveworks 公司于2017年提出,指具备版本控制、拉取和合入请求能力、具备CI/CD流水线发布能力的基础设施即代码(Infrastructure as Code, IaC),是一种云原生的持续交付模型。如图1所示,它的核心是使用 Git 仓库来管理基础设施和应用的配置,并且以 Git 仓库作为更改基础设施和应用的单一事实来源,用户从其他地方(例如集群控制台或者命令行)修改的配置均会被修正。Git 仓库中的声明式配置描述了目标环境当前所需基础设施的期望状态,借助 GitOps 能力,当集群中的实际运行的配置或应用状态与 Git 仓库中定义的期望状态不匹配时,Kubernetes Reconcilers 会根据期望状态来调整当前的状态,最终使实际状态与期望状态保持一致[3]。图1:GitOps Operator 运行方式基于上述的思想和技术路线,CNCF 开源社区从17年开始至今,涌现出很多火热的持续交付项目,他们以Flux、ArgoCD等CNCF毕业项目为代表,可以将用户配置在代码仓库中的Kubernetes Manifast(Deployment、Service等Yaml文件)、Helm Chart、Kustomize、Ksonnet、Jsonnet 定义和组织的应用以自动化的方式部署、将配置变化更改到应用程序的运行时环境。UCS 的配置管理功能当前采用 Flux2 作为技术内核,并将其与 UCS 的容器舰队、集群模型进行适配。它通过简单易用的 UI 提供对华为云集群、多云集群、本地集群、附着集群和伙伴云集群进行跨命名空间、跨集群的应用分发与配置管理的能力,并在观测面板中对配置的实时状态的进行收集和展示。用户还可以将它对接到CI流水线后面,实现多云应用的 CI/CD 流水线的集成和发布。当前UCS提供如下关键能力,帮助用户实现便捷的多云交付。2.1 开箱即用的GitOps引擎,兼容主流的开源生态和体验图2:Flux2 主要组件的运行原理UCS 会为每个开启 GitOps 引擎的集群安装一个稳定开源版本的 Flux2 组件,且用户无须运维 GitOps 引擎。每个集群中的 GitOps 引擎会以Pull模式、定周期监听和拉取最新的仓库源配置信息并把最新的配置信息及时同步至集群中。如图2所示:Source-Controller 主要负责监视 Git 仓库源、Bucket 对象存储桶以及 Helm 仓库的存储配置变化,然后把最新 Commit 记录的制品包拉取至集群本地。而 Kustomize-Controller 和 Helm-Controller 则会负责监听集群本地拉取制品变化情况,其中以 Helm Chart/Helm Release 类型定义的制品会交由 Helm-Controller 进行渲染和同步至集群中;同理,按照 Kustomize 方式进行组织的制品交由 Kustomize-Controller 进行渲染和同步至集群中。2.2 丰富的多集群差异化配置能力随着部署应用的规模越来越大,部署集群的底层差异性越来越大,我们发现单一的一份配置对应一个集群的模式会变的越来繁琐和难以维护,因此面向多个集群的差异化配置策略随之出现。UCS 配置管理功能提供了两种多集群差异化配置的策略: Kustomize 和 Helm Release。Kustomize 是一个 Kubernetes 应用程序配置管理工具,它提供一种简单灵活的方式来生成 Kubernetes 资源,并可以使得这些资源在不同的环境中用不同的方式进行配置[4]。如图3所示,Kustomize 策略在 Base 目录下定义所有集群公共部署资源,然后在 Overlay 目录下描述每个集群产生差异化覆盖参数。然后在部署阶段,通过动态渲染参数将最终版本的制品交付至目标集群中。图3:Kustomize 制品组织目录示意图同理,HelmRelease 也是参考上述思路。将公共定义的资源放置在 templates 目录下,然后结合 valuesFrom/valuesFiles 等方式从 value.yaml 读取每个环境的差异化参数,满足客户差异化的配置诉求。其配置的重点在于做好定义公共部分抽象和少数变量的差异化配置,对应用本身参数属性和运维参数进行分离,减少重复编辑和维护的成本。2.3 基于Git的可审计、可持续的部署能力UCS 配置管理将 Git 仓库中最新合入的制品配置信息同步部署至纳管的多个集群中,同时对应用发布行为进行版本化管理和权限控制,提供发布回滚和版本迭代控制,并进行审计跟踪。 基于UCS GitOps+Pipeline流水线构建多云DevOps解决方案 随着 DevOps 价值观和文化的流行,越来越多的公司选择帮助开发团队分担应用程序交付的责任,他们将多云环境下的交付交给专门的运维团队来完成,让开发团队可以更加专注于应用程序的开发和构建本身[5,6]。基于 UCS GitOps+Pipeline 流水线可构建多云DevOps 的解决方案,实现多云环境下多云应用构建和发布。开发团队和运维团队可以基于 Git 工作流,将现有流程对接到华为云 CodeArts Pipeline 流水线或者企业自建的 CI/CD 流水线之上,从而拥有多云应用的业务开发、集成、测试再到多云应用的部署—全流程 DevOps 体验。具体来讲将分为以下两个阶段:1、定义和构建多云应用:开发团队进行业务的开发、测试、验证、打包软件和生成镜像。这里可以是采用华为云官方的 CodeArts Pipeline 流水线或者用户自建的 CI 流水线。然后定义每个集群交付资源的原始制品文件。2、交付多云应用:运维团队首先会根据开发团队提供的原始制品文件对部署在多个集群环境中的差异化内容进行配置。此环节需要做好定义公共部分抽象和少数变量的差异化配置,对应用本身参数属性和运维参数进行分离,减少重复编辑和维护参数的成本。然后使用 UCS GitOps 统一初始化集群所需的环境和资源,对发布步骤进行编排,通过更新配置仓库来一致的对多个集群进行自动化应用发布;同时运维团队还对应用发布行为进行版本化管理、权限控制和审计,提供发布回滚和版本迭代控制,保证业务应用的成功部署。图4:结合UCS GitOps的多云DevOps流水线下面将以一个详细的例子来解释:华为云某亚太跨国公司客户需要统一管理横跨多国的 Kubernetes 集群和进行业务发布,他们的线上商城业务应用同时运行在Hong Kong 的华为云 CCE 集群中,新加坡的亚马逊云 EKS 集群中;并且他们在马来西亚还拥有一部分自建数据中心集群供开发团队进行业务开发和测试验证。由于每个国家消费者的商品喜好差异以及当地的供应链供给不同,商城中发布的商品类别会存在差异。在原有的交付流程中,运维团队会根据每个地域的供应商集群控制面板风格、部署业务版本,业务更新频率等因素,为每个环境单独构建一条流水线独立交付;并在每次发布版本前,运维团队会与开发团队就新版本特点和每条流水线的部署细节进行详细磋商。而使用 UCS GitOps 可以大大降低交付上述流程的复杂度,如图4的解决方案中所示,客户采用多套环境共享一套 CI 流水线,并将构建的产物统一推送至华为云Hong Kong 的SWR 镜像仓库。然后通过差异化配置不同环境的部署参数,将多个环境的发布对接到华为云 CodeArts 配置仓库,实现了从本地集群测试和验证到多个生产集群的发布的无缝切换,也极大的提升了他们多云交付的效率。总结综上所述,UCS GitOps 是以 Flux2 为技术内核,将其与 UCS 的容器舰队/集群模型进行适配的多云交付平台。它通过简单易用的 UI 提供对华为云集群、多云集群、本地集群、附着集群和伙伴云集群进行跨命名空间、跨集群的应用分发与配置管理的能力,并在观测面板中对配置的实时状态进行收集和展示。它可以帮助您将多个集群环境的配置和治理集中于一处,以自动化的体验完成多集群基础设施的管理以及多云应用的发布及更新。同时 UCS 会持续关注开源社区侧多集群 GitOps 的发展趋势,并将优质特性采纳为产品的内核。在后续的版本迭代中,下列特性将会逐步支持:1、容器舰队级别的配置分发:通过对舰队内部集群进行标签化管理,完成舰队视角下应用的一键分发和统一管理。2、全面对接华为云 CodeArts Pipeline:提供全流程、更好融合体验的多云 DevOps 流水线。3、在界面中提供对接三方消息系统的应用发布状态感知能力:一方面处理来自外部系统(GitHub、Bitbucket、Harbor、Jenkins)的事件,然后通知 GitOps Toolkit 控制器有关源更改的信息;另一方面处理由 GitOps Toolkit 控制器发出的事件,然后根据事件的严重性和涉及的对象将它们转发至外部系统(Slack、Microsoft Teams、Discord、Rocker)。参考资料在 Kubernetes 环境中自动化证书管理 https://www.nginx.com/blog/automating-certificate-management-in-a-kubernetes-environment 使用 Flux 管理多集群基础设施 cid:link_0Codefresh Continuous Delivery for Kubernetes使用 Kustomize 对 Kubernetes 对象进行声明式管理 https://kubernetes.io/zh-cn/docs/tasks/manage-kubernetes-objects/kustomization/Enterprise CI CD Best PracticesGitOps-2.0 The Future of DevOps Ebook v4
-
由 Istio 社区指导委员会成员和华为云云原生团队联合编著的云原生服务网格书籍《 Istio 权威指南》重磅上市!《 Istio 权威指南》包含云原生服务网格原理、实践、架构、源码四大技术篇章,内容权威、系统、详实, 凝聚华为云云原生团队在 Istio 社区及产品领域耕耘多年的长期实践和宝贵经验。华为云 CTO、CNCF CTO 联合作序,Istio 社区技术委员会( TOC )资深成员强力推荐。Istio服务网格是 CNCF( Cloud-Native Computing Foundation,云原生计算基金会)定义的云原生技术的典型代表之一,向下与提供资源、运行环境结合,构建了一个懂应用、对应用更友好的基础设施,帮助下层基础设施感知上层应用,更有效地发挥资源的效能;向上以非侵入的方式提供面向应用的韧性、安全、动态路由、调用链、拓扑等应用管理和运维能力。作为服务网格技术中最具影响力的项目,Istio 从诞生之初就获得了技术圈和产业界的极大关注。CNCF 这几年的调查报告显示,Istio 一直是生产环境下最受欢迎和使用最多的服务网格。2022 年 9 月,CNCF正式接受 Istio 成为孵化项目,推动 Istio 与 Envoy 项目的紧密协作,一起构建云原生应用流量管理的技术栈,也将进一步促进 Istio 成为应用流量治理领域的事实标准。根据 Istio 官方的统计,Istio 项目已有 8800 名个人贡献者,超过 260 个版本,并有来自 15 家公司的 85 名维护者,可见Istio在技术圈和产业圈都获得了极大的关注和认可。两次年度 IstioCon活动每次都吸引了超过 4000 人参加。华为云云原生团队成员入选了每届Istio社区指导委员会,当前有 2 名指导委员会成员(全球仅 8 家公司 13 人),参与Istio社区的重大技术决策,持续引领了Istio项目和服务网格技术的发展。另外Maintainer 2 名,Member 10+ 名,Pull Request 位于全球TOP 3,中国第一,Contributions TOP 3(2.3w+)。《 Istio 权威指南》简介《 Istio 权威指南》由华为云云原生团队出品,旨在打造业界最系统权威的 Istio 图书。书籍分为上、下两册,上册包括原理篇、实践篇;下册包括架构篇和源码篇,总计 26 章。▍原理篇 1~7 章介绍 Istio 的相关概念、原理,并详解 Istio 丰富的流量治理、可观测性、安全等方面的原理、机制和用法细节。▍实践篇 8~14 章基于一个统一用例实践 Istio 的流量治理、灰度、韧性、安全、可观测性、多基础设施、网关等典型应用。▍架构篇 15~20 章从架构的视角详解 Istio 各控制面组件和数据面组件的设计思想、数据模型和核心工作流程。▍源码篇 21~26 章从代码的视角详解 Istio 各控制组件面和数据面组件的代码结构、代码流程和关键代码片段。书籍特色1. 权威详实内容获 Istio 社区和 Istio TOC Lin Sun 和 John Howard 代表 Istio 社区强力推荐《 Istio 权威指南》基于 Istio 最新版本和架构,通过 4 篇、26 章、近 1000 页的篇幅,全面、系统、详细、深入地解析 Istio 原理、用法、实践、架构和源码。能帮助读者从多个维度理解云原生、服务网格、Istio 等相关技术,掌握基于 Istio 实现应用流量管理、零信任安全、应用可观测性等能力的相关原理与实践。Istio 社区最资深权威的两位 TOC 委员 Lin Sun 和 John Howard 代表Istio 社区推荐书籍的权威、系统的内容,建议初学者、云原生技术专家或 Istio 社区的贡献者均可阅读、参考。2.450+ 详实原创图表解析关键原理、架构、模型和代码流程,归纳易错技术点全书运用 450+ 原创图表多维度洞察、归纳、总结Istio原理、架构、流程和易错技术要点。践行了作者著书的理念不是搬运知识,而是将自己的实际的经验总结和提炼出来,由浅入深地帮助广大从业者学习服务网格的机制,掌握Istio的用法,特别是帮助从业者理解其中容易出错,最难理解的技术细节。如图书第4章可观测性中详细介绍了Istio访问日志的内容,特别剖析了 6 个重要的可以帮助运维人员识别一个请求通过服务网格数据面的每个阶段的耗时细节、定位耗时的瓶颈时间段。考虑到大多数从业者很容易混淆这几个个时间段的细微的差别,特提供了图4-26展示了代理观测记录每个时间段的起始时间点和终止时间点。并通过表4-4对每个时间字段进行了解析。这种通过原创的细致入微的图、表和文字结合的立体表达详解易错核心技术点的方式,获得了Istio TOC成员, Director of Open Source at Solo.io Lin Sun的赞誉和强烈推荐。▲ 图4-26 访问日志中的重要时间字段解析▼ 表4-4 访问日志中的重要时间字段解析3.国内首本系统详细解析 Istio 和 Envoy 架构和源码的技术书籍,Istio 和Envoy 社区核心维护者周礼赞强力推荐此外当前服务网格的使用越来越普及,国内甚至业界介绍服务网格控制面的资料书籍已经慢慢丰富起来,但是详细介绍架构和源码实现的书籍,特别是网格数据面的资料一直较少。很多从业朋友反映业务进入深水区后网格数据面知识的欠缺阻碍了其日常的工作的开展和生产中问题定位定界。《 Istio 权威指南》下册着重介绍 Istio 的架构与源码,特别规划了4章系统详细地解析 Istio-proxy 和 Envoy 架构和源码。书籍的详实内容获得 Istio 和 Envoy 社区核心维护者周礼赞强力推荐。4. 大量原创实践内容覆盖典型应用和常见疑难问题,指导客户解决生产问题《 Istio 权威指南》内容源于华为云云原生团队在 Istio 社区及产品领域耕耘多年的长期工程实践、客户实际案例的宝贵经验积累。在全面系统、深入介绍 Istio 原理、架构的同时,更注重内容对读者具体工作的实用价值。本书规划了独立的实践篇涵盖 Istio 的典型的流量、安全和可观测性实践案例。另外,近些年用户深入使用 Istio 的过程中,访问日志的应答标记的含义对大部分资深使用者造成困扰,但是国内外的资料包括社区官方都很简单,只是一般性的简单描述。上册附录规划了原创的访问日志实践,涵盖了大部分 Istio 访问日志中典型应答标记的实际案例,帮助读者理解其用法。此外下册附录规划了多个华为云云原生团队生产中积累的有借鉴意义的疑难案例,帮助读者参照解决实际工作中碰到的类似问题。5. 华为云 CTO、CNCF CTO、信通院、IEEE/CCF Fellow 等顶级领域专家推荐《 Istio 权威指南》目标成为 Istio 技术的权威、系统的技术书籍,持续帮助读者朋友学习了解 Istio ,解答大家使用 Istio 中的具体问题,推动云原生技术的发展。该目标和成果得到了华为云 CTO 张宇昕、CNCF CTO Chris Aniszczyk 的大力支持,二位 CTO 为《 Istio 权威指南》联合作序,倾力推荐。中国信通院云计算与大数据研究所何宝宏所长、上海交通大学致远讲席教授IEEE/CCF Fellow 过敏意老师、CNCF 中国区总监 Keith Chan、华为云首席产品官方国伟分别结合研究所、学术界、CNCF和产业界的背景和技术趋势表达了对Istio和其所属的服务网格技术的观点,也给出了读者使用本书的建议 。6. Istio 社区和华为云产品专家联合出品《 Istio 权威指南》由 Istio 社区亚洲唯一的从首届至今的指导委员会成员、国内最早的 Istio 商用网格服务开发团队成员联合出品,内容涵盖 Istio 的原理、实践、架构与源码。内容来源于作者在 Istio 社区设计开发大颗粒功能的经验总结,结合华为云云原生团队在云服务开发、客户解决方案构建、生产环境运维等日常工作中的实践、思考和总结,打造国内最权威、系统、详实、实用的Istio书籍。图书是《云原生服务网格 Istio 原理、实践、架构与源码解析》核心作者张超盟、徐中虎又一力作 。作者简介张超盟华为云应用服务网格架构师,先后负责过华为云容器应用运维、微服务平台、云服务目录、云服务可靠性、服务网格等云原生产品的架构设计与开发工作,主导过多个重大项目的云原生和微服务化生产落地。在服务网格、Kubernetes容器服务、微服务架构、应用性能管理、大数据、DevOps工具等方面有深入的研究与实践。Istio社区成员,KubeCon、IstioCon及ServiceMeshCon等会议的演讲者,技术图书作者。早期曾在中铁一局从事路桥建设工作。徐中虎华为云云原生团队核心成员,开源技术专家,服务网格Istio核心维护者,Istio社区指导委员会成员,Kubernetes项目核心贡献者,批量计算项目Volcano的核心维护者,拥有丰富的开源工作经验。主要研究方向有微服务架构、服务网格、容器编排平台Kubernetes和未来的分布式云原生架构等。在分布式系统的性能优化、高可靠和可扩展方面研究深入、经验丰富。张伟华为云服务网格数据面资深专家,拥有18年架构设计与开发经验,先后就职于亿阳信通、加拿大北电网络(中国)、甲骨文、Polycom、阿里巴巴及华为等公司。作为核心开发人员开发过传输网管系统、Tuxedo交易中间件、ts-server多媒体转码服务、GTS高性能事务云服务、sc高性能注册中心、ASM数据面等多个产品,现主要负责华为云ASM服务网格数据面代理产品的设计与开发工作。冷雪西安电子科技大学杭州研究院菁英副教授,浙江大学工学博士。主要研究方向有云原生安全、性能优化和智能运维等,致力于解决云网环境下的关键问题。曾参与并主持多项科研项目,在国际顶级会议和期刊上发表多篇论文并获得多项授权专利。我们衷心地希望书中的内容能对您和您日常工作带来帮助,也很期待有机会就其中的内容和您进行技术交流。假如你需要更深入地学习服务网格及云原生相关技术,欢迎关注我们的容器魔方公众号(参见本书封面),一起学习并讨论服务网格及云原生领域最新的技术进展。行业权威著作,云原生服务网格从业白皮书华为云、CNCF CTO联合作序——华为云CTO 张宇昕《 Istio 权威指南》来源于华为云云原生团队在云服务开发、客户解决方案构建、Istio社区特性开发、生产环境运维等日常工作中的实践、思考和总结,旨在帮助技术圈的更多朋友由浅入深且系统地理解 Istio 的原理、实践、架构与源码。书中内容在描述 Istio 的功能和机制的同时,运用了大量的图表总结,并深入解析其中的概念和技术点,可以帮助读者从多个维度理解云原生、服务网格等相关技术,掌握基于 Istio 实现应用流量管理、零信任安全、应用可观测性等能力的相关实践。无论是初学者,还是对服务网格有一定了解的用户,都可以通过本书获取自己需要的信息。——CNCF CTO Chris Aniszczyk本书提供了全面且实用的 Istio 指南,涵盖了 Istio 的核心概念、特性和对 xDS 协议等主题的深入探讨,还包括对 Envoy 和 Istio 项目源码的深入解析,这对潜在贡献者非常有用。无论您是软件工程师、SRE 还是云原生开发人员,本书都将为您提供利用 Envoy 和 Istio 构建可扩展和安全的云原生应用所需的知识和技能。行业大咖倾力推荐——中国信通院云计算与大数据研究所所长 何宝宏服务网格作为一种管理服务间通信的核心技术,为服务间的调用带来了便捷且可靠的流量、安全和可观测性等能力。中国信通院作为ICT领域的国家智库,率先牵头制定了服务网格相关标准。华为作为云原生领域的中坚力量,在该标准的编写过程中发挥了重要作用。《Istio权威指南》作为关于服务网格的专业技术书籍,对国内云原生技术的普及和发展将起到极大的促进作用。——上海交通大学致远讲席教授、国家杰青、IEEE/CCF Fellow 过敏意云原生技术已经成为产业界和学术界共同关注的热点之一。Istio作为一种集成了流量、安全和可观测性等能力的透明服务治理平台,有效推动了服务网格在云生产环境下的应用和普及。《Istio权威指南》作为服务网格领域的权威书籍,凝聚了华为云云原生团队长期积累的丰富经验,深入浅出地对Istio相关技术进行了详尽解读,值得相关从业者、技术爱好者和学术研究者阅读、参考。——CNCF中国区总监、Linux Foundation亚太区战略总监Keith ChanIstio一直是云原生领域非常流行的开源项目,是CNCF组织的各类会议上的热门话题。华为一直是云原生开源活动的积极参与者,在Kubernetes和Istio等项目中都有着突出的贡献。《Istio权威指南》由华为云云原生团队倾力打造而成,其理论结合实践,深度剖析了Istio的原理、实践、架构与源码,对于企业面向云原生架构转型及践行服务网格落地都有很大的参考意义。——华为云首席产品官 方国伟云原生极大地提高了企业应用生产力,缩短了应用的上市时间,降低了应用上云的门槛。服务网格作为云原生技术栈中的关键技术之一,可以帮助用户打造“以应用为中心”的云原生基础设施。《Istio权威指南》作为系统介绍服务网格技术Istio的权威书籍,来源于在Istio社区及产品领域耕耘多年的华为云云原生团队的长期工程实践和宝贵经验积累,值得广大云原生技术爱好者阅读、参考。——Istio TOC Member、Director of Open Source at Solo.io Lin SunIstio是当今生产环境下非常流行、部署非常广泛的服务网格技术。如果您已经了解Istio并想从基本概念、API、架构、各组件的源码等方面深入研究Istio,那么《Istio权威指南》适合您阅读。本书是非常实用且有深度的Istio书籍,其涵盖的Istio组件工作流和图表的深度给我留下了特别深刻的印象。希望您喜欢本书,我代表Istio社区祝您学习Istio愉快!——Istio TOC Member、Istio SC Member、Google Staff Engineer John Howard加入CNCF,标志着Istio向服务网格的事实标准迈出了关键的一步。《Istio权威指南》由来自Istio指导委员会、Istio社区等的Istio资深开发人员编写而成,是非常全面、深入地讲解Istio技术的权威书籍,内容涵盖Istio的原理、实践、架构与源码。无论您是初学者、云原生技术专家,还是Istio社区的贡献者,都可以从中获益。——Envoy与Istio核心维护者、Tetrate.io前创始工程师 周礼赞《Istio权威指南(上)》讲解了Istio的原理、各种使用场景和优秀实践,《Istio权威指南(下)》讲解了Istio控制面和数据面Envoy的内部架构及源码实现。这两本书深入剖析了Istio的内部架构,可以帮助您更充分地理解Istio的工作原理和实现,从而更好地应用Istio并进行Istio调优。凝聚深厚实践 行业问鼎力作华为云应用服务网格华为云在2018年率先发布全球首个Istio商用服务:应用服务网格 ASM (Application Service Mesh,)。ASM 是一个拥有高性能、高可靠性和易用性的全托管服务网格。作为分布式云场景中面向应用的网络基础,ASM 对多云、混合云环境下的容器、虚拟机、Serverless、传统微服务、Proxyless 服务提供了应用健康、韧性、弹性、安全性等的全方位管理。华为云应用服务网格(ASM)也已服务于互联网、汽车、制造、物流、政府等多个行业的近千家客户,满足不同行业客户的业务诉求。华为云将在此过程中积累的丰富经验,转化为代码贡献给Istio社区,极大地推动了 Istio 技术的成熟和社区的快速发展。华为云 Istio 社区贡献作为最早一批投身云原生技术的厂商,华为云是 CNCF 在亚洲唯一的初创成员。华为云云原生团队从 2018 年开始积极参与 Istio 社区的活动,参与 Istio 社区的版本特性设计与开发,基于用户的共性需求开发了大量大颗粒特性。团队成员入选了每届 Istio 社区指导委员会,当前有2名指导委员会成员(全球仅 8 家公司 13 人),参与 Istio 社区的重大技术决策,持续引领了 Istio 项目和服务网格技术的发展。另外 Maintainer 2 名,Member 10+名,Pull Request 位于全球TOP 3,中国第一,Contributions TOP 3(2.3w+)。华为云云原生团队华为云云原生团队创建于2013年,是国内较早从事云原生研究的团队之一,也是CNCF的初创成员和白金会员。华为云在容器、服务网格、微服务等云原生技术领域都有着深厚的沉淀,拥有10多名CNCF项目维护者,对 Kubernetes、Istio 等核心项目的贡献一直位居全球前列,并向CNCF捐献了 KubeEdge、Volcano、Karmada 等知名项目。基于 CNCF 的开源生态,华为云还打造了云容器引擎、云容器实例、应用服务网格等一系列优质的商业化云原生服务。为进一步推广云原生技术,加速云原生在行业中落地,华为云联合CNCF、中国信通院及业界云原生技术精英们成立了全球云原生交流平台——创原会。创原会创原会是 CNCF、中国信通院、华为云及业界云原生技术精英们联合成立的全球云原生交流平台,旨在通过研究前沿云原生技术及共享产业落地实践,探索云原生与业务融合的无限可能。自 2020 年成立至今,创原会已在中国、东南亚、拉美、欧洲陆续成立分会并举办活动 50 余场,为全球技术精英们提供了一个优质、高端、开放的交流平台,并吸纳近 300 位 CTO、技术总监成为会员,极大地促进了云原生在全球各行业中的普及和落地。对本书感兴趣,可链接直达− 《Istio权威指南(上):云原生服务网格Istio原理与实践》(张超盟,徐中虎,张伟,冷雪) https://item.jd.com/13938046.html− 《Istio权威指南(上):云原生服务网格Istio架构与源码》(张超盟,徐中虎,张伟,冷雪)https://item.jd.com/13938046.html添加小助手k8s2222进入华为云云原生团队Istio技术交流群
-
在openEuler 22.03-lts aarch64版本的容器中安装rsyslogd,根据centos的类似方法,将以下注释 #### MODULES #### #module(load="imuxsock" # provides support for local system logging (e.g. via logger command) # SysSock.Use="off") # Turn off message reception via local log socket; # local messages are retrieved through imjournal now. #module(load="imjournal" # provides access to the systemd journal # StateFile="/run/log/imjournal.state") # File to store the position in the journal #module(load="imklog") # reads kernel messages (the same are read from journald) #module(load="immark") # provides --MARK-- message capability #$imjournalRatelimitInterval 0 启动rsyslog报错 [root@fb4bbc75f4e5 ~]# rsyslogd rsyslog startup failure, child did not respond within startup timeout (60 seconds) 求助解决
-
一、容器化改造方案租户对应一个企业。租户中内置多级VDC对企业不同部门。每个部门可以设置配额,对应部门对资源的预算。支持VDC多级管理,最大5级。 部门内的项目,对应project,一个用户可以在不同项目内。一个项目也可以有不同用户。用户可以跨部门关联项目 部门的资源归属到项目中 VDC内用户有不同角色,分别为VDC管理员,负责本级及下级的产品、角色、用户、Project管理、资源管理; VDC业务员:负责资源使用二、高可用规划结合华为云,给出高可用规划的简单说明:1 、分别在2个AZ中部署两套CCE集群,K8S Master采用本地3节点高可用部署;2、应用AZ内高可用部署,通过ClusterIP服务调用不跨AZ。3、应用发布LoadBalancer类型的Service对接到集群所在AZ的融合ELB服务实例;4、应用通过VIP访问数据库,数据库自动切换应用不感知。5、支持多AZ动态容器存储,根据pod所在AZ创建数据卷。三、 网络规划1、集群内部应用默认可通过ClusterIP类型服务相互通信。k8s集群内置DNS服务,服务间访问可以通过IP或域名访问,请画出K8S集群内部应用网络互通示意图:2、Step1:kube-proxy、core-dns从Master中kube-apiserver订阅service,POD2的Service创建时,kube-proxy刷新本节点iptables,core-DNS更新路由数据。3、Step2:Pod2通过域名访问Pod4的service4,发起到core-dns查询请求,并获取对应的ClusterIP(如果使用ClusterIP直接访问则忽略这一步骤)4、Step3:Pod2发送业务报文,目的地址为获取到的ClusterIP。容器网络根据目的地址匹配策略后进行VxLAN封装,封装源地址为容器所在的VM IP地址,目的地址为目的容器所在VM IP,并将报文发给I层vSwitch,然后转发至目的容器所在VM,容器网络解VxLAN封装后,根据ClusterIP将业务报文发送目的service及POD。四、 云原生概念五、 微服务微服务目的是有效的拆分应用,实现敏捷开发和部署 。1、按照业务来划分服务,单个服务代码量小,业务单一,易于维护2、每个微服务都有自己独立的基础组件,例如数据库、缓存等,且运行在独立的进程中3、微服务之间的通信是通过HTTP 协议或者消息组件,且具有容错能力4、微服务有一套服务治理的解决方案,服务之间不相合,可以随时加入和剔除服务5、单个微服务能够集群化部署,并且有负载均衡的能力6、整个微服务系统应该有一个完整的安全机制,包括用户验证、权限验证、资源保护等7、整个微服务系统有链路追踪的能力8、有一套完整的实时日志系统微服务具备功能:1、服务的注册和发现2、服务的负载均衡3、服务的容错4、服务网关5、服务配置的统一管理6、链路追踪7、实时日志六、 CI/CDCICD实现了从代码开发、代码编译、部署、测试、发布上线自动化的一套自动化构建的流程;CI即持续集成(Continuous Integration),它实现代码合并、构建、部署、测试都在一起,不断地执行这个过程,并对结果进行反馈。CD包含两个含义:持续交付(Continuous Delivery),它实现部署到生产环境,给用户进行使用;持续部署(Continuous Deployment),它实现部署到生产环境七、 DevopsDevOps就是让开发人员和运维人员更好地沟通合作,通过自动化流程来使得软件整体过程更加快捷和可靠八、 容器化容器是通过一种虚拟化技术来隔离运行在主机上不同进程,从而达到进程之间、进程和宿主操作系统相互隔离、互不影响的技术。这种相互孤立进程就叫容器,它有自己的一套文件系统资源和从属进程。九、 使用容器引擎客户端上传镜像顺序开始——安装容器引擎——构建镜像——创建组织——连接容器镜像服务——上传镜像——结束十、 CCE引擎优势
-
一.存储容器化存储作为基础组件,直接和本地盘打交道,所以我们一个要解决的事情就是如果Kubernetes 管理本地盘。kubernetes管理本地盘通过官方提供的local-static-provisioner自动生成LocalPersistentVolume管理磁盘。LocalPersistentVolume是Kubernetes提供的一种管理本地盘的资源。5.1 使用Statefulset管理存储容器通过statefulset 管理有状态的存储服务, 为每个pod分配一个单独的磁盘可以使用volumeClaimTemplates给每个pod生成唯一的pvc,具体规则{podName},事先准备好PVC 和 PV,通过Statefulset 我们就可以把我们的存储托管到云上了。另外借助daemonset,可以把我们gateway模块部署到每一个node上面。处理云存储的请求。5.2 存储容器化的收益1)降低运维成本基于Kubernetes和statfulset获得了滚动更新,灰度更新,健康检查,快速扩容等功能,只需要一组yaml文件就可以快速搭建一个集群,相比于传统写ansible脚本部署的方式复杂度大大降低。2)降低开发运维成本由于Kubernetes把存储抽象成StorageClass PersistentVolume PersistentVolumeClaim。我们可以通过他们管理我们的存储资源,基于Kubernetes lable的过滤功能,可以实现简单的关系查询,通过PVC与PV管理存储资源,减少管理端的开发。定位问题也能通过POD信息快速定位到问题机器和问题云盘。而且接入Kubernetes生态上的prometheus后,监控告警也能快速开发。3)隔离性增强docker限制cpu memory使用,减少进程之间资源互相干扰,进一步提升资源利用率。在做流媒体容器化过程中,各个系统 Portal 平台、中间件、ops 基础设施、监控等都做了相应的适配改造,改造后的架构矩阵如下图所示。Portal:流媒体 的 PaaS 平台入口,提供 CI/CD 能力、资源管理、自助运维、应用画像、应用授权(db 授权、支付授权、应用间授权)等功能。2.运维工具:提供应用的可观测性工具, 包括 watcher(监控和报警)、bistoury (Java 应用在线 Debug)、qtrace(tracing 系统)、loki/elk(提供实时日志/离线日志查看)。中间件:应用用到的所有中间件,mq、配置中心、分布式调度系统 qschedule、dubbo 、mysql sdk 等。3.虚拟化集群:底层的 K8s 和 OpenStack 集群。4.Noah:测试环境管理平台,支持应用 KVM/容器混合部署。一.CI/CD 流程改造主要改造点:应用画像: 把应用相关的运行时配置、白名单配置、发布参数等收敛到一起,为容器发布提供统一的声明式配置。授权系统: 应用所有的授权操作都通过一个入口进行,并实现自动化的授权。K8s 多集群方案: 通过调研对比,KubeSphere 对运维优化、压测评估后也满足我们对性能的要求,最终我们选取了 KubeSphere 作为多集群方案。二.中间件适配改造改造关注点:由于容器化后,IP 经常变化是常态,所以各个公共组件和中间件要适配和接受这种变化。Qmq组件改造点:Broker端加快过期数据的处理速度。原因:由于IP变化频繁,对于一个主题有几百个甚至上千个的IP订阅,会产生很多文件Qconfig/Qschedule组件改造点:按实例级别的推送、任务执行在容器场景下不建议使用 。原因:因为IP经常变化,在容器化场景下发布、pod驱逐等都会导致IP变化,按实例维度推送没有意义Dubbo组件改造点:更改上线下线逻辑,下线记录由永久节点改为临时节点。 原因:上下线机制加上频繁的IP变更会导致zookeeper上产生大量的过期数据Openresty改造点:监听多K8s集群的endpoint变更,并更新到upstream; KVM、容器server地址共存,支持KVM和容器混合部署;三、应用平滑迁移方案设计为了帮助业务快速平滑地迁移到容器,制定了一些规范和自动化测试验证等操作来实现这个目标。1.容器化的前置条件: 应用无状态、不存在 post_offline hook(服务下线后执行的脚本)、check_url 中不存在预热操作。2.测试环境验证: 自动升级 SDK、自动迁移。我们会在编译阶段帮助业务自动升级和更改 pom 文件来完成 SDK 的升级,并在测试环境部署和验证,如果升级失败会通知用户并提示。3.线上验证: 第一步线上发布,但不接线上流量,然后通过自动化测试验证,验证通过后接入线上流量。4.线上 KVM 与容器混部署:保险起见,线上的容器和 KVM 会同时在线一段时间,等验证期过后再逐步下线 KVM。5.线上全量发布: 确认服务没问题后,下线 KVM。6.观察: 观察一段时间,如果没有问题则回收 KVM。
-
一、容器和虚拟化的联系容器和虚拟化相比容器比虚拟机小很多,通常是MB级,所需的硬件资源也少很多,虚拟机是GB级,意味着一台物理机器可以承载的容器比虚拟机要多的多。容器可以在几秒甚至几毫秒内启动,相比之下,虚拟机启动时间比较长。容器是共享主机的操作系统,因为所有应用必须在统一操作系统上运行。相比,虚拟机可以运行不同的操作系统。使用容器只需对容器主机的操作系统进行补丁和更新,而虚拟机需对每个操作系统进行补丁和更新。如果一个容器导致容器主机操作系统崩溃,则在该主机上运行的所有容器都将失败。容器主机的操作系统内核中的安全漏洞将影响其所托管的所有容器。使用场景虚拟机非常适合传统的资源密集型单片应用程序,尤其是准备将这些应用程序移至云中时。容器更适合承载web服务中使用的微服务。不仅如此,容器和虚拟机也可以共存,容器可以在虚拟机中运行,企业可以利用现有的虚拟化基础设施来管理其容器。
-
↵AR502H系列网关的容器是开放的,用户可以根据自身要求来定制,本文介绍如何制作出一个带有Python3运行环境的lxc容器。一,容器制作环境搭建环境制作方法在此不再赘述,请参考《软件二次开发指南》相关章节进行搭建《软件二次开发指南》:cid:link_0二、修改制作容器脚本1、修改编译环境中的/usr/local/bin/create-rootfs的脚本,以完成安装python如上图,在脚本178行左右末尾添加python3 python3-pip2、添加py运行库如上图在脚本185行左右添加如红框内容,该部分可按需添加这里的pip3 install 后建议指定为国内源以保证网络质量三、制作容器按照正常步骤制作容器,制作出的容器就带有python3环境了后记:也可使用相同方法,在容器中安装如gdb等调试工具
-
摘要:KubeEdge 1.11版本提供了“边缘节点分组管理”新特性,抽象出了跨地域的应用部署模型。本文分享自华为云社区《基于KubeEdge的边缘节点分组管理设计与实现》,作者:云容器大未来 。KubeEdge 1.11版本提供了“边缘节点分组管理”新特性,抽象出了跨地域的应用部署模型。该模型将边缘节点按地区划分为节点组,并将应用所需资源打包成一个整体在节点组上进行部署,降低了边缘应用生命周期管理的复杂度,有效减少运维成本。1. 边缘应用跨地域部署面临的挑战图1 边缘应用跨地域部署示意图在边缘计算场景中,边缘节点通常分布在不同的地理区域,这些区域中的节点有着计算资源、网络结构和硬件平台等属性上的差异。如图1所示,边缘节点部署在杭州、北京和上海等地域,各地域边缘节点的规模不同,不同地域网络不互通,以及不同区域镜像仓库也是不同的,如北京的节点无法通过IP直接访问其他区域的节点。因此在部署边缘应用的时候,通常需要为每个这样的地理区域维护一个Deployment,对于资源少的区域减少副本数量,对于局域网中的节点需要把镜像地址改为本地镜像仓库的地址,同样也需要为每个地区管理单独的Service资源,来解决跨地域节点之间的访问问题。然而随着地理区域和应用数量的增长,对应用的管理会变得越来越复杂,运维成本也随之增加。基于以上背景,KubeEdge提供了边缘节点分组管理能力,来解决在跨地域应用部署中运维复杂度的问题。2. 边缘节点分组管理设计与实现图2 边缘节点分组整体概览如图2所示,边缘节点分组特性的整体设计图,主要由节点分组、边缘应用和流量闭环三个部分的内容组成,下面会就以上各个部分详细展开。2.1 节点分组(NodeGroup)图3 节点分组示例根据边缘节点的地理分布特点,可以把同一区域的边缘节点分为一组,将边缘节点以节点组的形式组织起来,同一节点同时只能属于一个节点组。节点分组可以通过matchLabels字段,指定节点名或者节点的Label两种方式对节点进行选择。节点被包含到某一分组后,会被添加上apps.kubeedge.io/belonging-to:nodegroup的Label。2.2 边缘应用(EdgeApplication)图4 边缘应用EdgeApplication的组成边缘应用用于将应用资源打包,按照节点组进行部署,并满足不同节点组之间的差异化部署需求。该部分引入了一个新的CRD: EdgeApplication,主要包括两个部分:(1) Workload Templates。主要包括边缘应用所需要的资源模板,例如Deployment Template、Service Template和ConfigMap Template等;(2) WorkloadScopes。主要针对不同节点组的需求,用于资源模板的差异化配置,包括副本数量差异化配置(Replicas Overrider)和镜像差异化配置(Image Overrider),其中Image Overrider包括镜像仓库地址、仓库名称和标签。对于应用主体,即Deployment,会根据Deployment Template以及差异化配置Overrider生成每组所需的Deployment版本,通过调整nodeSelector将其分别部署到指定分组中。对于应用依赖的其他资源,如ConfigMap和Service,则只会在集群中通过模板创建一个相应的资源。边缘应用会对创建的资源进行生命周期管理,当删除边缘应用时,所有创建的资源都会被删除。2.3 流量闭环图5 流量闭环示意图通过流量闭环的能力,将服务流量限制在同一节点组内,在一个节点组中访问Service时,后端总是在同一个节点组中。当使用EdgeApplication中的Service Template创建Service时,会为Service添上service-topology:range-nodegroup的annotation,KubeEdge云上组件CloudCore会根据该annotation对Endpoint和Endpointslice进行过滤,滤除不在同一节点组内的后端,之后再下发到边缘节点。此外,在下发集群中默认的Master Service “Kubernetes”所关联的Endpoint和Endpointslice时,会将其维护的IP地址修改为边缘节点MetaServer地址,用户在边缘应用中list/watch集群资源时,可以兼容K8s流量访问方式,实现无缝迁移和对接。3. 实现原理与设计理念在这个部分,我们会分享一下边缘节点分组管理特性的设计理念,并结合KubeEdge整体架构,详细介绍一下我们的实现原理。图6 设计理念我们希望给用户提供一个统一的运维入口,原本我们需要维护各个地区的Deployment,如果需要进行增删改查操作,我们需要对每个地区的Deployment都执行一遍相同的操作,不仅增加了运维成本,还容易引入人为操作的错误。边缘节点分组管理特性通过引入EdgeApplication CRD,统一了Deployment等资源的运维入口。另外我们需要提供更大的扩展可能性,在内部实现中,我们统一使用了Unstructured结构,降低与特定资源的耦合度,方便后续添加其他资源。另外为了不干涉原生资源和流程,我们降低与Kubernetes Reconciliation的耦合度,可以保证Deployment等资源操作过程的原生性。图7 节点组和边缘应用实现在边缘节点分组管理特性中,我们引入了两个CRD,分别是节点组NodeGroup和边缘应用EdgeApplication。在NodeGroup Reconciliation中,NodeGroup Controller用于监听NodeGroup CRD的变化,并对节点的apps.kubeedge.io/belonging-to:nodegroup Label进行增删改等操作,同时,加入节点组的节点,会上报状态到NodeGroup CRD中,我们就可以通过查询NodeGroup直接查看节点组内所有节点的状态。EdgeApplication Reconciliation与NodeGroup Reconciliation类似,由EdgeApplication Controller来监听EdgeApplication CRD的变化,对相应资源进行增删改等操作,同时对应资源会上报状态到EdgeApplication CRD中。图8 整体架构如图8所示,是最终的整体架构图。在边缘节点分组管理特性中,我们引入了新的组件ControllerManager,其中包括了刚才我们介绍的NodeGroup Controller和EdgeApplication Controller,在CloudCore中引入了新的模块EndpointSlice Filter,用于实现流量闭环的能力。图中蓝色区域是前面已经介绍了的节点分组和边缘应用的内容,在这里再重点介绍一下Service Template实现流量闭环能力的过程。首先在EdgeApplication CRD中加入Service的模板,在创建边缘应用时,Service range-nodegroup资源也会随之生成,同时控制面会自动为其创建EndpointSlice。EndpointSlice会通过KubeEdge的云边通道下发到边缘节点,CloudCore中的EndpointSlice Filter会进行过滤,保证下发到同一节点组内的边缘节点,由此可以保证边缘上的客户端访问始终在一个节点组内。对于用户来说,图8中紫色的线表达了用户需要维护的资源。首先用户需要维护NodeGroup,来管理节点组中的节点;其次,用户需要维护EdgeApplication资源,通过EdgeApplication来实现对各个地域边缘应用的生命周期管理。4. 发展规划目前我们已经实现了Deployment、Service和ConfigMap等资源的打包以及流量闭环的能力,并且支持资源的部分状态收集。未来我们将继续拓展边缘节点分组的能力,实现边缘网关,支持StatefulSet等更多资源,逐步完善应用状态收集,并在Kubectl中支持更友好的资源展现形式。欢迎大家能够加入KubeEdge社区,一起完善与增强KubeEdge边缘节点分组等方面的能力。了解KubeEdge社区KubeEdge是业界首个云原生边缘计算框架、云原生计算基金会内部唯一孵化级边缘计算开源项目,社区已完成业界最大规模云原生边云协同高速公路项目(统一管理10万边缘节点/50万边缘应用)、业界首个云原生星地协同卫星、业界首个云原生车云协同汽车、业界首个云原生油田项目,开源业界首个分布式协同AI框架Sedna及业界首个边云协同终身学习范式,并在持续开拓创新中。KubeEdge网站 : https://kubeedge.ioGitHub地址 : https://github.com/kubeedge/kubeedgeSlack地址 : https://kubeedge.slack.com邮件列表 : https://groups.google.com/forum/#!forum/kubeedge每周社区例会 : https://zoom.us/j/4167237304Twitter : https://twitter.com/KubeEdge文档地址 : https://docs.kubeedge.io/en/latest/本文作者由KubeEdge社区Member——华为云 鲍玥、浙江大学SEL实验室 张逸飞原创。
-
摘要:KubeEdge设备管理架构的设计实现,有效帮助用户处理设备数字孪生进程中遇到的场景。本文分享自华为云社区《KubeEdge:下一代云原生边缘设备管理标准DMI的设计与实现》。随着5G、AI、分布式云等技术的成熟发展,万物互联、数字孪生、算力泛在等理念不断推进,带来了很多行业业务的创新,越来越多的设备、应用运行在端侧,并产生大量的数据。如何更好地解耦业务应用开发和设备数据访问,为设备提供完整的生命周期数据管理,释放设备数据的价值?如何在保证集群可用性的同时,高效管理和传输设备数据,获得更为方便、灵活的数据访问方式?云原生边缘计算的方案选择可以帮助用户更好地应对这类问题。一、KubeEdge设备管理框架KubeEdge设备管理架构的设计实现,有效帮助用户处理设备数字孪生进程中遇到的场景。用户可以通过KubeEdge,将物理设备抽象成数字孪生,用云原生的方式对设备和数据进行管理。一、KubeEdge设备管理框架 图 1 KubeEdge设备管理架构设计KubeEdge设备管理架构设计如图1所示,具体流程如下:1. 用户调用Kubernetes API接口,创建Device CRD实例到KubeEdge2. KubeEdge云上组件CloudCore watch到Kubernetes中Device CRD实例创建消息3. 此时CloudCore会做两件事情,一方面CloudCore通过云边websocket通道下发Device Twin信息到EdgeCore,另一方面CloudCore会生成一份包含Device Profile信息的Configmap,该Configmap是以Node名称为索引,挂载到对应Mapper的Pod中的4. Mapper通过读取挂载的Configmap中的Device Profile信息,更新本地维护的Device list列表5. EdgeCore把接收到的Device Twin信息发送到指定的mqtt topic6. 该节点上的所有Mapper都会收到该Device Twin消息,并根据Device名称来匹配是否是自己维护的list中的Device7. Mapper根据Device Profile信息,通过对应的协议与设备建立连接8. Mapper通过mqtt topic上报设备状态和采集的数据Device Twin到EdgeCore9. EdgeCore通过云边websocket通道上报Device Twin数据到CloudCore10. CloudCore更新设备Device Twin数据到Kubernetes二、DMI框架设计 在此基础上,KubeEdge团队也对框架不断更新迭代。为帮助用户应对未来更大规模设备场景、更高的可用性需求、更灵活的功能支持以及更优的用户体验,KubeEdge 设计了更优化的设备管理框架——DMI。DMI整合设备管理接口,优化边缘计算场景下的设备管理能力,打造基于云原生技术的,覆盖设备管理、设备数据的设备数字孪生管理平台;同时定义了EdgeCore与Mapper之间统一的连接入口,并分别由EdgeCore和Mapper实现上行数据流和下行数据流的服务端和客户端,承载DMI具体功能。DMI框架设计中解耦了设备管理面与设备业务面数据,让Device CRD只承载设备本身的生命周期管理,而设备业务面数据则直接通过微服务的方式为数据消费者应用提供出来。在这样的架构下,设备就不再是单纯的数据源,而是一种云原生的设备微服务,设备数据消费应用的开发者就可以不再关心如何获取设备数据,而是以更云原生的方式来聚焦应用本身的业务逻辑开发。DMI框架还提供多种数据推送方式,让数据消费者可以更灵活地获取设备数据,用户体验更优。由于DMI的设备管理面与业务面数据分离的特点,业务面数据可以通过业务面通道更灵活地在云端或边端被处理,而管理面的云边通道中只会传输少量管理面信息,大大降低了云边通道拥塞的可能,提高了KubeEdge系统的可用性。另外,DMI提供了统一的设备管理相关接口,无论是设备应用开发者还是设备应用的使用者,都可以以更统一、更灵活、更标准化的方式来开展设备相关工作,不拘泥于具体形式,只要能够实现DMI接口,就能够享受KubeEdge边缘计算平台带来的云原生设备管理体验。▍2.1 DMI框架定位图 2 DMI 在 KubeEdge 架构中的定位DMI在KubeEdge架构中的定位如图2所示。DMI类似Kubernetes的CNI、CSI、CRI等接口,定义了一组EdgeCore与Mapper之间的内部API接口以及外部应用访问Mapper的统一的API接口。其中内部接口底层由gRPC结合UDS的方式来实现,外部API接口支持mqtt和REST两种接入方式。Mapper不论是何种承载、实现方式,只要实现了DMI中所定义的上行、下行数据接口,即可接入KubeEdge云原生边缘计算平台,使用云原生的方式对设备进行管理。▍2.2 DMI设备管理与数据管理DMI框架架构设计如图3所示,其中黄色线条为设备管理面数据流管理,蓝色部分为业务面数据流管理。在DMI的架构设计中,将设备的管理面数据与业务面数据进行分离。其中管理面数据主要包括设备的元数据、设备属性、配置、状态、生命周期等,其特点是相对比较稳定,创建后除状态上报外的信息更新较少,更贴近Pod类型资源所产生的数据,在保证用户可以通过云端Kubernetes API像访问Pod一样维护Device的生命周期的同时,尽量减少设备管理产生的额外数据传输开销。图 3 DMI设备管理与数据管理架构在DMI框架设计下,设备不再是单纯的数据源,而是被抽象为微服务,以云原生的方式为设备数据消费者提供数据服务。DMI框架下的设备数据访问支持多种场景,更加灵活。图3中列出了几种主要的数据访问方式,包括推数据和拉数据等,具体情况如下:1. 边缘侧应用通过REST Service访问设备数据2. 云侧应用通过REST Service访问设备数据3. Mapper通过配置REST目的地址,将数据推送到边缘侧应用4. Mapper通过配置REST目的地址,将数据推送到云侧应用5. Mapper通过配置目的地址,将数据推送到边缘侧数据库6. Mapper通过配置目的地址,将数据推送到mqtt broker7. 边缘侧应用通过mqtt broker topic订阅设备数据8. 云侧应用通过mqtt broker topic 订阅设备数据9. 边缘侧应用处理数据后将处理结果传上云▍2.3 DMI工作流程图 4 DMI设备管理工作流程示例在DMI框架下,设备管理工作的流程有一定的变化。如图4所示,在安装KubeEdge的时候,云端CloudCore会注册DeviceController组件用于监听Device和DeviceModel的CRD资源。DeviceController中存在两个模块,Downstream Controller和Upstream Controller,其中Downstream Controller用于监听云端的Device、DeviceModel事件,并通过Cloudhub下发至边缘,Upstream Controller用于接收从Cloudhub转发来的EdgeHub上报的Device状态和消息,并更新Kubernetes中的Device状态。在边缘侧,Mapper初始化的时候,需要调用DMI中的Mapper注册接口,将Mapper的相关信息注册至Device Manager,并接收接口返回的已下发至该节点的且协议匹配的设备信息。EdgeHub在接收到云端下发的设备消息时,会将其转发到DeviceManager组件,DeviceManager会根据该设备的协议选择对应的Mapper驱动程序,发送创建设备的请求,并且本地数据库也会存储该设备的信息,后续Mapper会将设备孪生消息转化为设备协议格式,跟实际的物理设备进行通信。三、DMI接口定义▍3.1 DMI 接口分类DMI接口实现了EdgeCore与Mapper之间的通信,支持REST和mqtt的通信方式,并以标准化的形式呈现,降低了Mapper开发、适配难度。在数据访问方面,DMI可以实现边缘侧和云侧的应用都可以通过REST Service的方式访问设备数据。图 5 DMI接口定义如图5所示,DMI有六类接口,Mapper管理是针对边缘侧各类设备协议驱动程序,Device管理和Device数据管理对管理面和业务面进行了数据拆分,Device升级管理和Device命令管理为具有升级和命令执行功能的设备提供相关的接口,Device事件管理可以监控Mapper及其纳管的各个设备的运行状态。▍3.2 DMI 接口定义示例图 6 DMI设备管理部分接口定义示例如图6所示,为DMI设备管理部分接口定义,v1版本以gRPC proto的方式定义,可使用make dmi命令创建对应的gRPC-go代码。 ▍3.3 DMI 设备相关 CRD 定义如图7所示,是DMI设备相关CRD定义,主要分为Device和DeviceModel。其中DeviceModel与设备型号是一一对应的关系,代表同一类设备型号的共有属性,主要包含设备产生数据属性Properties和设备支持命令属性Commands。Device为设备实例,与真实的物理设备为一对一的关系,每个DeviceModel可以对应统一型号的多个Device实例。Device类型资源主要包含设备型号对应关系信息、设备协议配置信息、设备部署节点信息、设备状态信息以及设备数据Property采集配置信息。图 7 DMI 设备相关 CRD 定义 四、发布计划 四、发布计划DMI发布计划分为三个版本,Alpha版本提供设备管理相关功能实现,以及提供一个支持DMI接口的Mapper Demo。Beta版本支持设备命令管理、设备升级管理以及设备数据管理的能力,此外还会对接第三方平台,并提供相关对接Demo。GA版本会对多平台、多协议进行对接支持,另外会把设备安全以及事件管理的功能补全。图 8 DMI发布计划目前 KubeEdge Device IoT SIG 专注于第一阶段的设备管理和 Mapper Demo 的开发工作。欢迎大家通过下方联系方式联系我们,一起参与到方案设计和特性开发的工作当中本文作者:华为云 赵然 ;DaoCloud 道客 王梓龙附:KubeEdge社区贡献和技术交流地址网站: https://kubeedge.ioGithub地址: cid:link_1地址: https://kubeedge.slack.com邮件列表: https://groups.google.com/forum/#!forum/kubeedge每周社区例会: https://zoom.us/j/4167237304Twitter: https://twitter.com/KubeEdge文档地址: https://docs.kubeedge.io/en/latest/
-
一、常见数据结构非线程安全的数据结构:ArrayList,LinkedList,ArrayQueue,HashMap,HashSet线程安全的数据结构:Vector,Stack,Hashtable,CopyOnWriteArrayList,ConcurrentHashMap二、ArrayList2-1 线程不安全的原因看源码public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! // 该方法是容量保障,当容纳不下新增的元素时会进行扩容 elementData[size++] = e; return true;}分析:当数组长度为10,而size = 9时,此时A线程判断可以容纳,B线程也来判断发现可以容纳(这是因为add非原子操作)。当A添加完之后,B线程再添加的话,就会报错(数组越界异常)而且这一步elementData[size++] = e也非原子性的.可以拆分为elementData[size] = e 和 size ++;在多线程的情况下很容易出现elementData[size] = e1; elementData[size] = e2; size++; size++; 的情况2-2 Vector实现安全Vector的add()源码: public synchronized void addElement(E obj) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = obj; }分析: Vector的add方法加了synchronized ,而ArrayList没有,所以ArrayList线程不安全,但是,由于Vector加了synchronized ,变成了串行,所以效率低。回到目录…三、CopyOnWriteArrayListCopyOnWrite容器即写时复制的容器。// java.util.concurrent包下List<String> list = new CopyOnWriteArrayList<String>();123-1 如何实现线程安全? 通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。 这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。3-2 特征CopyOnWriteArrayList(写数组的拷贝)是ArrayList的一个线程安全的变体,CopyOnWriteArrayList和CopyOnWriteSet都是线程安全的集合,其中所有可变操作(add、set等等)都是通过对底层数组进行一次新的复制来实现的。它绝对不会抛出ConcurrentModificationException的异常。因为该列表(CopyOnWriteArrayList)在遍历时将不会被做任何的修改。CopyOnWriteArrayList适合用在“读多,写少”的并发场景中,比如缓存、白名单、黑名单。它不存在“扩容”的概念,每次写操作(add or remove)都要copy一个副本,在副本的基础上修改后改变array引用,所以称为“CopyOnWrite”,因此在写操作要加锁,并且对整个list的copy操作时相当耗时的,过多的写操作不推荐使用该存储结构。读的时候不需要加锁,如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为开始读的那一刻已经确定了读的对象是旧对象。3-3 缺点在写操作时,因为复制机制,会导致内存占用过大。不能保证实时性的数据一致,“脏读”。回到目录…四、HashMap4-1 底层原理不清楚的小白看看之前两篇文章,就可以很容易搞懂HashMap的底层实现原理了。 Java数据结构之哈希表 JDK中的Set和Map解析4-2 线程不安全的原因单看 HashMap 中的 put 操作:JDK1.7头插法 –> 将链表变成环 –> 死循环JDK1.8尾插法 –> 数据覆盖回到目录…五、ConcurrentHashMap// java.util.concurrent包下Map<Integer, String> map = new ConcurrentHashMap<>();125-1 实现原理JDK1.7时,采用分段锁JDK1.8时,只针对同一链表内互斥,不是同一链表内的操作就不需要互斥。但是一旦遇到需要扩容的时候,涉及到所有链表,此时就不是简单的互斥了。扩容的过程:当A线程put 操作时发现需要扩容,则它自己创建一个扩容后的新数组。A线程只把当前桶中的节点重新计算哈希值放入新数组中,并且标记该桶元素已经迁移完成。由于其它桶中的元素还没有迁移,所以暂时还不删除旧数组。等其它线程抢到锁并在桶内做完操作时,需要义务的将该桶节点全部搬移并标记桶。直到最后一个线程将最后一桶节点搬移完毕,则它需要把旧数组删除。5-2 与Hashtable的区别HashTable和HashMap的实现原理几乎一样,差别在于:HashTable不允许key和value为null;HashTable是线程安全的。 但是HashTable线程安全的策略实现代价却比较大,get/put所有相关操作都是synchronized的,这相当于给整个哈希表加了一把全表锁。当一个线程访问或操作该对象,那其他线程只能阻塞。 所以说,Hashtable 的效率低的离谱,几近废弃。————————————————版权声明:本文为CSDN博主「一只咸鱼。。」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq15035899256/article/details/125961682
-
前言Map 这样的 Key Value 在软件开发中是非常经典的结构,常用于在内存中存放数据。本篇主要想讨论 ConcurrentHashMap 这样一个并发容器,在正式开始之前我觉得有必要谈谈 HashMap,没有它就不会有后面的 ConcurrentHashMap。HashMap众所周知 HashMap 底层是基于 数组 + 链表 组成的,不过在 jdk1.7 和 1.8 中具体实现稍有不同。Base 1.71.7 中的数据结构图:先来看看 1.7 中的实现。这是 HashMap 中比较核心的几个成员变量;看看分别是什么意思?初始化桶大小,因为底层是数组,所以这是数组默认的大小。桶最大值。默认的负载因子(0.75)table 真正存放数据的数组。Map 存放数量的大小。桶大小,可在初始化时显式指定。负载因子,可在初始化时显式指定。重点解释下负载因子:由于给定的 HashMap 的容量大小是固定的,比如默认初始化: 1 public HashMap() { 2 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); 3 } 4 5 public HashMap(int initialCapacity, float loadFactor) { 6 if (initialCapacity < 0) 7 throw new IllegalArgumentException("Illegal initial capacity: " + 8 initialCapacity); 9 if (initialCapacity > MAXIMUM_CAPACITY)10 initialCapacity = MAXIMUM_CAPACITY;11 if (loadFactor <= 0 || Float.isNaN(loadFactor))12 throw new IllegalArgumentException("Illegal load factor: " +13 loadFactor);1415 this.loadFactor = loadFactor;16 threshold = initialCapacity;17 init();18 }给定的默认容量为 16,负载因子为 0.75。Map 在使用过程中不断的往里面存放数据,当数量达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容,而扩容这个过程涉及到 rehash、复制数据等操作,所以非常消耗性能。因此通常建议能提前预估 HashMap 的大小最好,尽量的减少扩容带来的性能损耗。根据代码可以看到其实真正存放数据的是transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;这个数组,那么它又是如何定义的呢?Entry 是 HashMap 中的一个内部类,从他的成员变量很容易看出:key 就是写入时的键。value 自然就是值。开始的时候就提到 HashMap 是由数组和链表组成,所以这个 next 就是用于实现链表结构。hash 存放的是当前 key 的 hashcode。知晓了基本结构,那来看看其中重要的写入、获取函数:put 方法 1 public V put(K key, V value) { 2 if (table == EMPTY_TABLE) { 3 inflateTable(threshold); 4 } 5 if (key == null) 6 return putForNullKey(value); 7 int hash = hash(key); 8 int i = indexFor(hash, table.length); 9 for (Entry<K,V> e = table[i]; e != null; e = e.next) {10 Object k;11 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {12 V oldValue = e.value;13 e.value = value;14 e.recordAccess(this);15 return oldValue;16 }17 }1819 modCount++;20 addEntry(hash, key, value, i);21 return null;22 }判断当前数组是否需要初始化。如果 key 为空,则 put 一个空值进去。根据 key 计算出 hashcode。根据计算出的 hashcode 定位出所在桶。如果桶是一个链表则需要遍历判断里面的 hashcode、key 是否和传入 key 相等,如果相等则进行覆盖,并返回原来的值。如果桶是空的,说明当前位置没有数据存入;新增一个 Entry 对象写入当前位置。 1 void addEntry(int hash, K key, V value, int bucketIndex) { 2 if ((size >= threshold) && (null != table[bucketIndex])) { 3 resize(2 * table.length); 4 hash = (null != key) ? hash(key) : 0; 5 bucketIndex = indexFor(hash, table.length); 6 } 7 8 createEntry(hash, key, value, bucketIndex); 9 }1011 void createEntry(int hash, K key, V value, int bucketIndex) {12 Entry<K,V> e = table[bucketIndex];13 table[bucketIndex] = new Entry<>(hash, key, value, e);14 size++;15 }当调用 addEntry 写入 Entry 时需要判断是否需要扩容。如果需要就进行两倍扩充,并将当前的 key 重新 hash 并定位。而在 createEntry 中会将当前位置的桶传入到新建的桶中,如果当前桶有值就会在位置形成链表。get 方法再来看看 get 函数: 1 public V get(Object key) { 2 if (key == null) 3 return getForNullKey(); 4 Entry<K,V> entry = getEntry(key); 5 6 return null == entry ? null : entry.getValue(); 7 } 8 9 final Entry<K,V> getEntry(Object key) {10 if (size == 0) {11 return null;12 }1314 int hash = (key == null) ? 0 : hash(key);15 for (Entry<K,V> e = table[indexFor(hash, table.length)];16 e != null;17 e = e.next) {18 Object k;19 if (e.hash == hash &&20 ((k = e.key) == key || (key != null && key.equals(k))))21 return e;22 }23 return null;24 }首先也是根据 key 计算出 hashcode,然后定位到具体的桶中。判断该位置是否为链表。不是链表就根据 key、key 的 hashcode 是否相等来返回值。为链表则需要遍历直到 key 及 hashcode 相等时候就返回值。啥都没取到就直接返回 null 。Base 1.8不知道 1.7 的实现大家看出需要优化的点没有?其实一个很明显的地方就是:当 Hash 冲突严重时,在桶上形成的链表会变的越来越长,这样在查询时的效率就会越来越低;时间复杂度为 O(N)。因此 1.8 中重点优化了这个查询效率。1.8 HashMap 结构图:先来看看几个核心的成员变量: 1 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 2 3 /** 4 * The maximum capacity, used if a higher value is implicitly specified 5 * by either of the constructors with arguments. 6 * MUST be a power of two <= 1<<30. 7 */ 8 static final int MAXIMUM_CAPACITY = 1 << 30; 910 /**11 * The load factor used when none specified in constructor.12 */13 static final float DEFAULT_LOAD_FACTOR = 0.75f;1415 static final int TREEIFY_THRESHOLD = 8;1617 transient Node<K,V>[] table;1819 /**20 * Holds cached entrySet(). Note that AbstractMap fields are used21 * for keySet() and values().22 */23 transient Set<Map.Entry<K,V>> entrySet;2425 /**26 * The number of key-value mappings contained in this map.27 */28 transient int size;和 1.7 大体上都差不多,还是有几个重要的区别:TREEIFY_THRESHOLD 用于判断是否需要将链表转换为红黑树的阈值。HashEntry 修改为 Node。Node 的核心组成其实也是和 1.7 中的 HashEntry 一样,存放的都是 key value hashcode next 等数据。再来看看核心方法。put 方法看似要比 1.7 的复杂,我们一步步拆解:判断当前桶是否为空,空的就需要初始化(resize 中会判断是否进行初始化)。根据当前 key 的 hashcode 定位到具体的桶中并判断是否为空,为空表明没有 Hash 冲突就直接在当前位置创建一个新桶即可。如果当前桶有值( Hash 冲突),那么就要比较当前桶中的 key、key 的 hashcode 与写入的 key 是否相等,相等就赋值给 e,在第 8 步的时候会统一进行赋值及返回。如果当前桶为红黑树,那就要按照红黑树的方式写入数据。如果是个链表,就需要将当前的 key、value 封装成一个新节点写入到当前桶的后面(形成链表)。接着判断当前链表的大小是否大于预设的阈值,大于时就要转换为红黑树。如果在遍历过程中找到 key 相同时直接退出遍历。如果 e != null 就相当于存在相同的 key,那就需要将值覆盖。最后判断是否需要进行扩容。get 方法 1 public V get(Object key) { 2 Node<K,V> e; 3 return (e = getNode(hash(key), key)) == null ? null : e.value; 4 } 5 6 final Node<K,V> getNode(int hash, Object key) { 7 Node<K,V>[] tab; Node<K,V> first, e; int n; K k; 8 if ((tab = table) != null && (n = tab.length) > 0 && 9 (first = tab[(n - 1) & hash]) != null) {10 if (first.hash == hash && // always check first node11 ((k = first.key) == key || (key != null && key.equals(k))))12 return first;13 if ((e = first.next) != null) {14 if (first instanceof TreeNode)15 return ((TreeNode<K,V>)first).getTreeNode(hash, key);16 do {17 if (e.hash == hash &&18 ((k = e.key) == key || (key != null && key.equals(k))))19 return e;20 } while ((e = e.next) != null);21 }22 }23 return null;24 }get 方法看起来就要简单许多了。首先将 key hash 之后取得所定位的桶。如果桶为空则直接返回 null 。否则判断桶的第一个位置(有可能是链表、红黑树)的 key 是否为查询的 key,是就直接返回 value。如果第一个不匹配,则判断它的下一个是红黑树还是链表。红黑树就按照树的查找方式返回值。不然就按照链表的方式遍历匹配返回值。从这两个核心方法(get/put)可以看出 1.8 中对大链表做了优化,修改为红黑树之后查询效率直接提高到了 O(logn)。但是 HashMap 原有的问题也都存在,比如在并发场景下使用时容易出现死循环。1final HashMap<String, String> map = new HashMap<String, String>();2for (int i = 0; i < 1000; i++) {3 new Thread(new Runnable() {4 @Override5 public void run() {6 map.put(UUID.randomUUID().toString(), "");7 }8 }).start();9}但是为什么呢?简单分析下。看过上文的还记得在 HashMap 扩容的时候会调用 resize() 方法,就是这里的并发操作容易在一个桶上形成环形链表;这样当获取一个不存在的 key 时,计算出的 index 正好是环形链表的下标就会出现死循环。遍历方式还有一个值得注意的是 HashMap 的遍历方式,通常有以下几种: 1Iterator<Map.Entry<String, Integer>> entryIterator = map.entrySet().iterator(); 2 while (entryIterator.hasNext()) { 3 Map.Entry<String, Integer> next = entryIterator.next(); 4 System.out.println("key=" + next.getKey() + " value=" + next.getValue()); 5 } 6 7Iterator<String> iterator = map.keySet().iterator(); 8 while (iterator.hasNext()){ 9 String key = iterator.next();10 System.out.println("key=" + key + " value=" + map.get(key));1112 }强烈建议使用第一种 EntrySet 进行遍历。第一种可以把 key value 同时取出,第二种还得需要通过 key 取一次 value,效率较低。简单总结下 HashMap:无论是 1.7 还是 1.8 其实都能看出 JDK 没有对它做任何的同步操作,所以并发会出问题,甚至出现死循环导致系统不可用。因此 JDK 推出了专项专用的 ConcurrentHashMap ,该类位于 java.util.concurrent 包下,专门用于解决并发问题。坚持看到这里的朋友算是已经把 ConcurrentHashMap 的基础已经打牢了,下面正式开始分析。ConcurrentHashMapConcurrentHashMap 同样也分为 1.7 、1.8 版,两者在实现上略有不同。Base 1.7如图所示,是由 Segment 数组、HashEntry 组成,和 HashMap 一样,仍然是数组加链表。它的核心成员变量:1 /**2 * Segment 数组,存放数据时首先需要定位到具体的 Segment 中。3 */4 final Segment<K,V>[] segments;56 transient Set<K> keySet;7 transient Set<Map.Entry<K,V>> entrySet;Segment 是 ConcurrentHashMap 的一个内部类,主要的组成如下: 1 static final class Segment<K,V> extends ReentrantLock implements Serializable { 2 3 private static final long serialVersionUID = 2249069246763182397L; 4 5 // 和 HashMap 中的 HashEntry 作用一样,真正存放数据的桶 6 transient volatile HashEntry<K,V>[] table; 7 8 transient int count; 910 transient int modCount;1112 transient int threshold;1314 final float loadFactor;1516 }和 HashMap 非常类似,唯一的区别就是其中的核心数据如 value ,以及链表都是 volatile 修饰的,保证了获取时的可见性。原理上来说:ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。下面也来看看核心的 put get 方法。put 方法 1 public V put(K key, V value) { 2 Segment<K,V> s; 3 if (value == null) 4 throw new NullPointerException(); 5 int hash = hash(key); 6 int j = (hash >>> segmentShift) & segmentMask; 7 if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck 8 (segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment 9 s = ensureSegment(j);10 return s.put(key, hash, value, false);11 }首先是通过 key 定位到 Segment,之后在对应的 Segment 中进行具体的 put。 1 final V put(K key, int hash, V value, boolean onlyIfAbsent) { 2 HashEntry<K,V> node = tryLock() ? null : 3 scanAndLockForPut(key, hash, value); 4 V oldValue; 5 try { 6 HashEntry<K,V>[] tab = table; 7 int index = (tab.length - 1) & hash; 8 HashEntry<K,V> first = entryAt(tab, index); 9 for (HashEntry<K,V> e = first;;) {10 if (e != null) {11 K k;12 if ((k = e.key) == key ||13 (e.hash == hash && key.equals(k))) {14 oldValue = e.value;15 if (!onlyIfAbsent) {16 e.value = value;17 ++modCount;18 }19 break;20 }21 e = e.next;22 }23 else {24 if (node != null)25 node.setNext(first);26 else27 node = new HashEntry<K,V>(hash, key, value, first);28 int c = count + 1;29 if (c > threshold && tab.length < MAXIMUM_CAPACITY)30 rehash(node);31 else32 setEntryAt(tab, index, node);33 ++modCount;34 count = c;35 oldValue = null;36 break;37 }38 }39 } finally {40 unlock();41 }42 return oldValue;43 }虽然 HashEntry 中的 value 是用 volatile 关键词修饰的,但是并不能保证并发的原子性,所以 put 操作时仍然需要加锁处理。首先第一步的时候会尝试获取锁,如果获取失败肯定就有其他线程存在竞争,则利用 scanAndLockForPut() 自旋获取锁。尝试自旋获取锁。如果重试的次数达到了 MAX_SCAN_RETRIES 则改为阻塞锁获取,保证能获取成功。再结合图看看 put 的流程。将当前 Segment 中的 table 通过 key 的 hashcode 定位到 HashEntry。遍历该 HashEntry,如果不为空则判断传入的 key 和当前遍历的 key 是否相等,相等则覆盖旧的 value。不为空则需要新建一个 HashEntry 并加入到 Segment 中,同时会先判断是否需要扩容。最后会解除在 1 中所获取当前 Segment 的锁。get 方法 1 public V get(Object key) { 2 Segment<K,V> s; // manually integrate access methods to reduce overhead 3 HashEntry<K,V>[] tab; 4 int h = hash(key); 5 long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE; 6 if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null && 7 (tab = s.table) != null) { 8 for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile 9 (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);10 e != null; e = e.next) {11 K k;12 if ((k = e.key) == key || (e.hash == h && key.equals(k)))13 return e.value;14 }15 }16 return null;17 }get 逻辑比较简单:只需要将 Key 通过 Hash 之后定位到具体的 Segment ,再通过一次 Hash 定位到具体的元素上。由于 HashEntry 中的 value 属性是用 volatile 关键词修饰的,保证了内存可见性,所以每次获取时都是最新值。ConcurrentHashMap 的 get 方法是非常高效的,因为整个过程都不需要加锁。Base 1.81.7 已经解决了并发问题,并且能支持 N 个 Segment 这么多次数的并发,但依然存在 HashMap 在 1.7 版本中的问题。那就是查询遍历链表效率太低。因此 1.8 做了一些数据结构上的调整。看起来是不是和 1.8 HashMap 结构类似?其中抛弃了原有的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。也将 1.7 中存放数据的 HashEntry 改为 Node,但作用都是相同的。其中的 val next 都用了 volatile 修饰,保证了可见性。put 方法重点来看看 put 函数:根据 key 计算出 hashcode 。判断是否需要进行初始化。f 即为当前 key 定位出的 Node,如果为空表示当前位置可以写入数据,利用 CAS 尝试写入,失败则自旋保证成功。如果当前位置的 hashcode == MOVED == -1,则需要进行扩容。如果都不满足,则利用 synchronized 锁写入数据。如果数量大于 TREEIFY_THRESHOLD 则要转换为红黑树。get 方法根据计算出来的 hashcode 寻址,如果就在桶上那么直接返回值。如果是红黑树那就按照树的方式获取值。就不满足那就按照链表的方式遍历获取值。1.8 在 1.7 的数据结构上做了大的改动,采用红黑树之后可以保证查询效率(O(logn)),甚至取消了 ReentrantLock 改为了 synchronized,这样可以看出在新版的 JDK 中对 synchronized 优化是很到位的。总结看完了整个 HashMap 和 ConcurrentHashMap 在 1.7 和 1.8 中不同的实现方式相信大家对他们的理解应该会更加到位。其实这块也是面试的重点内容,通常的套路是:谈谈你理解的 HashMap,讲讲其中的 get put 过程。1.8 做了什么优化?是线程安全的嘛?不安全会导致哪些问题?如何解决?有没有线程安全的并发容器?ConcurrentHashMap 是如何实现的? 1.7、1.8 实现有何不同?为什么这么做?原文链接:https://blog.csdn.net/weixin_44460333/article/details/86770169
-
【摘要】 Sermant Agent是一种基于JavaAgent的无代理服务网格技术。它利用JavaAgent来检测主机应用程序,并具有增强的服务治理功能,以解决海量微服务架构中的服务治理问题。本文介绍了Sermant Agent的接入原理和如何使用Sermant Agent无修改接入CSE。本文分享自华为云社区《Spring Cloud应用零代码修改接入华为云微服务引擎CSE》,作者: 微服务小助手 。一、 Sermant Agent介绍Sermant Agent是一种基于JavaAgent的无代理服务网格技术。它利用JavaAgent来检测主机应用程序,并具有增强的服务治理功能,以解决海量微服务架构中的服务治理问题。Sermant Agent处于快速发展阶段,当前已支持多种服务治理能力,包含流量治理、注册、优雅上下线及动态配置能力。 二、 为何使用Sermant Agent接入代码零侵入,配置很简单相较于SDK方式接入,基于Sermant Agent的接入会更加快捷高效,配置简单,且应用无需做任何代码改造,仅需在服务启动时附带Sermant Agent即可动态接入到CSE。支持多种治理能力Sermant Agent默认集成流量治理能力,当前支持熔断、限流、隔离仓以及重试治理能力,该能力可基于CSE配置中心进行配置与发布。支持多种注册中心Sermant Agent目前支持业内主流的注册中心,已经支持了ServiceComb ServiceCenter、Naocs,Eureka、Zookeeper等正在开发中。支持应用不停机迁移Sermant Agent支持服务的双注册,可根据配置中心下发的服务订阅策略,动态修改当前服务的订阅策略,并基于该能力帮助线上应用在业务不中断的前提下完成服务迁移。不仅如此,Sermant Agent提供优雅上下线能力,在服务重启、上下线时提供保障,在保护服务的同时,规避服务下线时可能存在的流量丢失问题。三、 接入原理当然,在说明原理之前,我们首先需要了解什么是Java Agent。Java Agent是在JDK1.5之后引入的新特性,它支持JVM将字节码文件读入内存之后,JVM使用对应的字节流在Java堆中生成一个Class对象之前,用户可以对其字节码进行修改的能力,JVM使用修改之后的字节码进行Class对象的创建,从而实现Java应用的非代码侵入的业务逻辑修改和替换。Sermant Agent正是基于动态修改字节码的技术,在服务启动时,动态增强原服务的注册逻辑。那Sermant Agent是如何在不修改代码的前提下接入CSE呢?主要流程如下:Sermant Agent接入CSE的时序图包含以下6个步骤:首先服务携带Sermant Agent启动;服务启动时,针对服务执行字节码增强操作(基于Java Agent的字节码增强),主要针对注册与配置两块,在步骤3-5体现;通过字节码增强,动态识别原应用的注册中心;注入启动配置,动态关闭原应用的注册中心自动配置逻辑;随后通过Spring的SpringFactory机制注入基于Spring Cloud实现的注册CSE的自动配置类,由Spring接管;当应用发起注册时,会通过步骤5注入的注册逻辑向CSE发起注册,最终完成接入。四、 简单零代码修改,轻松接入CSE接入场景分为虚机接入和容器接入,大家可以根据自身需求选择合适的接入方式。虚机场景接入CSE虚机部署的应用可通过Sermant Agent接入到CSE,点击查看虚机接入CSE流程。接入流程基于ECS将应用接入CSE流程如下:容器场景接入CSE容器部署的应用可通过Sermant Injector自动挂载Sermant Agent,从而通过Sermant Agent接入到CSE,点击查看容器接入CSE流程。接入流程基于CCE将应用接入CSE流程如下:五、 更多支持版本当前Sermant已支持大部分业内主流版本,相关Spring及注册中心版本如下:开源方式接入除了上述接入方式,还可基于开源方式接入,您可在Sermant开源社区拉取最新代码,并自行打包,启动步骤可参考虚机接入流程。开源项目Sermant:https://github.com/huaweicloud/Sermant
-
(1)流媒体应用有:媒体采集系统、媒体制作系统、点播系统、视频流推送系统.几类应用比较适合容器化部署:一是功能单一的应用,即微服务(这也是为什么现在大家一谈到微服务就会谈到容器,一谈到容器就会谈到微服务的原因);二是无状态的应用,容器的一个最大的优点就是可以快速创建(秒级),对于无状态的应用,可以通过快速横向扩容来提升并发处理能力;三是变更频繁的应用,容器是基于镜像创建的,对于变更频繁的应用,只要能保证镜像在测试环境测试没有问题,那么在生产环境上线由于环境差异导致出问题的概率就会少的多;四是对于需要在一个站点快速部署的应用组,对于需要在一个新站点快速部署的应用组,使用容器技术能够结合容器平台自身的特性,快速创建一个新的站点。(2)容器化改造思路1:负载均衡应用改造点:选择合适的负载均衡器中小型的Web应用可以使用ngnix或HAProxy,大型网站或重要的服务可以使用LVS,目前该企业业务较小,选取nginx作为负载均衡器!2:web应用改造点:应用存在长时间执行请求 增加消息队列,通过消息队列将长任务与用户请求解耦3:应用服务器应用改造点:应用实例依赖于本地的存储来持久化数据如果是日志,建议变成流汇聚到分布式日志系统中。如果必须要使用存储,要使用共享文件系统如NFS(3)采用华为云CCE集群服务CCE引擎核心优势支持裸金属容器服务,流媒体服务性能提升200%以上。视频流媒体对网络性能以及服务器运算能力要求苛刻。CCE支持裸金属容器服务,如图1,视频应用可基于裸金属服务部署,容器直接运行在物理机上,无任何虚拟化性能缺失,可获得和物理机同等的超优性能,视频业务性能提升200%以上。图1 裸金属容器服务视频网站应用放在pod里视频文件放在OBS里有状态pod 无状态pod流媒体加CDN加速服务ClusterIP:集群内访问表示工作负载暴露给同一集群内其他工作负载访问的方式,可以通过“集群内部域名”访问Nodeport:在每个节点的IP上开放一个静态端口,通过静态端口对外暴露服务。节点访问 ( NodePort )会路由到ClusterIP服务,这个ClusterIP服务会自动创建。通过请求<NodeIP>:<NodePort>,可以从集群的外部访问一个NodePort服务Loadbalance:可以通过弹性负载均衡从公网访问到工作负载,与弹性IP方式相比提供了高可靠的保障,一般用于系统中需要暴露到公网的服务。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第三期2026/08/21 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;念擎-华为云AI开发者运营案例开发专家
本期直播内容:AI六层能力首次详细解读 + 新一代华为云开发者空间亮相 + 校园案例直播带练
回顾中
热门标签