聚美优品云平台实践

640

当下Kubernetes事实上已成为容器届编排的标准,但对于围绕容器构建的周边生态却是各有千秋。聚美优品云平台项目从2017初开始调研到现在落地推广也有快两年的时间,虽然享受到了Kubernetes对容器标准化操作的红利,但实际上在推进过程中,改造原有的架构去适配容器环境,仍会有不小的挑战。本文将围绕聚美云平台内部实现的细节和在电商平台中应用的场景,希望给大家带来一个不同的设计和思路。
项目背景

640


云平台第一版
聚美优品的云平台项目是从2017年上半年开始调研的,当时在面对基础设施管理这块我们主要面临两个选择,一个是业界比较成熟的OpenStack私有云架构,另一个是刚出来不久的Kubernetes容器方案。由于之前我们的运维团队有OpenStack相关的技术沉淀,而对于Docker方面的技术栈几乎为0,所以早期云平台选型时的方案是基于OpenStack Mitaka来做的。虽然云平台第一版做出来上线后确实为我们节省了一部分计算资源的交付时间,但是对于线上业务系统的交付运维仍然需要花大量时间去配置和调试。
云平台第二版
得益于Docker镜像环境的一致性和Kubernetes调度的灵活性,所以很快我们在2018年初开始对云平台进行重构,主要为其引入了Kubernetes来解决我们电商大促期间的弹性资源调度问题和日常物理资源的管理问题。聚美云平台第二版又名Galaxy,直译过来代表星系,寓意群星闪耀,翻译成中文也可理解为一群出色的人。在Galaxy中,目前我们已经完成了对Kubernetes,OpenStack和公有云的资源对接,并有统一的管理页面提供给运维和研发团队使用。对于Galaxy的定位,它更像是一个公共的基础设施服务,让运维从传统繁琐的基础操作中解脱出来,将重心倾向于check业务层面的东西。
Galaxy主要支持如下功能:
  • 统一的管理界面,同时支持多机房,多种资源的接入和管理;

  • 支持对Kubernetes内部资源的管理(命名空间,Deployment,DaemonSet、Service等);

  • 支持应用的健康检查和容器生命周期配置管理;

  • 支持应用的服务注册与发现;

  • 集成内部CI/CD平台,提高了运维效率;

  • 提供带权限管理的WebConsole;

  • 支持API,提供外部服务调用。


目前聚美Galaxy云平台运行在2个机房,下面资源层各分别部署了3套OpenStack和Kubernetes集群,同时还支持腾讯云、阿里云和UCloud等三方公有云资源的接入,运行时的最大规模是2K+宿主机和2W+的容器实例。

640


容器结构

640


信号量管理
为了保证Docker中的进程足够轻量和简单,我们摒弃了使用传统的Sysvinit或Supervisor的方式来管理容器内部的1号进程。取而代之的是采用dumb-init这个工具来作为容器的1号PID。dumb-init是一个天生为轻量级容器而设计的进程管理器,它能够很好向下传递信号量,并且还能够接管因子进程退出而无法找到其父进程的僵尸进程。对于容器运行时的挂起,我们采用是pause这个工具,通过Linveness探针来监控容器内进程的存活性。在处理容器内部子进程优雅退出的流程时,是通过trap这个命令来捕获terminal信号量的。一个基础的容器启动脚本如下:

640


容器内部调用
由于容器内进程做的足够轻量,所以当一个Pod内的多个Container服务之间有内部调用时,我们优先使用网络套接字的方式处理。如果有的业务只能使用套接字文件的话,在Kubernetes的编排中,我们添加了一个emptyDir来临时存放套接字文件,然后通过挂载Volume的形式让每个容器能够正常发现套接字文件的路径的形式来实现服务间通讯,当然套接字文件的名称和路径需要和研发同事协商一致。例如下面这个样例主要就实现了,容器A和B中的服务通过读取/var/run/service目录下的套接字文件来实现过程调用。

640


容器启动与停止
因为Kubernetes对于Pod内容器的启动和停止是无序化的管理方式,这对于我们在管理Container起停之间的依赖也来了一些挑战。以目前我们PHP-FPM类的容器来举个例子,每个容器都会在启动阶段去check自己依赖的容器是否已经正常运行,如果检查失败则退出重新运行,直到依赖的从容器启动完成后自己才会进行接下来的启动逻辑。同理,容器在停止的时候,利用preStop这个特性在停止容器前sleep不同的时间来控制容器停止的顺序。

640

640


代码容器
聚美优品的持续构建交付平台由于是自研的,和业界利用Jenkins生态构建的平台有很大差别,所以这里我仅举一个比较有代表性的例子来跟大家分享我们是如何在容器平台下解决代码发布的问题。首先,我们在线上的deployment编排里面大量运用了Kubernetes中的initContainer容器,它能够在正常容器起来之前预处理一些东西,例如配置下载、环境的设置等等。我们通过initContainer提前将业务打包好的代码下载解压到code volume中,等到业务容器启动时,code volume会随着容器的启动挂载到指定的代码存放路径。code volume我们使用的emptyDir来存放代码,它会随着容器的生命周期消失而销毁,所以这里我们会与研发协商好代码目录中不会有任何需要持久化到本地的数据。
640
容器网络

640


CNI
云平台的容器网络插件是采用IPVLAN来实现内部通信和外部通信。IPVLAN是Linux内核4.2+版本新支持的一个网络虚拟化方案,其工作原理类似于Macvlan。IPVLAN主要提供三种工作模式L2、L3和L3S。我们主要采用的是L2模式,简单来说,在L2模式下,操作系统内核会在master网卡上虚拟出多块网卡分给Docker容器使用,而每一块虚拟网卡都共享master网卡上的Mac地址,但是每块虚拟网卡是可以有独立的IP地址的。一个简单的基于IPVLAN构建的虚拟网络拓扑结构如下图:

640


IPAM
对于IPAM我们是通过host-local的方式来管理的,也就是说我们在宿主机上会预配置好一个固定给容器使用的IP地址段,而对于容器的网络规划主要是通过自研的容器网络管理平台来实现统一分配和管理。使用的逻辑如下,首先我们会在IDC机房提前规划好一批容器使用的网络,并在接入层交换机上配置好路由和访问规则,其次将容器的网络和宿主机的元数据录入到管理平台,平台会自动根据录入的元数据为宿主机分配一个全局唯一的IP地址段,同时存入到Consul的KV当中。当新增加kubelet节点宿主机在初始化CNI的时候,就会从Consul中读取到自己所对应的值去渲染CNI的配置文件。

640


服务和配置管理

640


统一配置中心
对于容器中的应用配置管理这块,我们采用的是聚美自研的配置管理系统(Dove),它能为各业务系统(不限于业务系统)提供统一的配置管理平台和方案。主要解决目前我们各项目配置维护困难、容易失误、同步效率低、管理成本太高等问题。
Dove主要的技术特性如下:
  • 极度松散耦合,不需改动原业务代码即可集成或弃用配置管理系统。

  • 高效,无需额外开销,配置即本地开发语言对象。

  • 多环境统一管理

  • 配置分组权限控制

  • 变更日志:可追溯历史内容及修改者。

  • 离线运行:配置获取后,即使配置服务下线也不会影响应用当前版本的运行。

  • 离线恢复:在无配置服务器在线的情况下,应用或其服务器重启可以自动回复上次的配置,继续正常运行。

  • 调试模式:使用调试的客户端(DEV环境),开发者可以在本地编写自己的配置内容来忽略服务端进行调试。


640


SOA服务治理
随着核心服务往容器化方向迁移,传统的通过填写IP地址管理服务上下线的运维方式也得跟着改变。首先我们面临的问题是,容器IP地址是随着容器的生命周期而存在,如果容器重启后IP发生变化,要求运维将新的IP配置到应用当中已经变得不再现实。所以在18年初,我们花了大量时间投入到SOA服务框架(Lark)的研发和落地当中,其中重点解决的问题之一,就是服务发现的问题。

640


lark-agent以Sidecar模式和业务容器共同组成一个Pod实例,当发起一个服务调用时,客户端会将RPC协议的请求数据发送至lark-agent,Lark根据协议中的服务名称将请求转发到后端状态正常的服务实例中去。经过一年时间的沉淀,我们已经将线上所有核心业务接入到lark平台当中,而带来的收益也非常明显,其中主要就包含:
  • 为客户端和服务端增加Lark代理,将复杂的长连接协议隐藏起来,降低了不同语言间协议的适配成本;

  • Lark主动向云端上报心跳,根据自定义策略报告服务器负载情况,把运维成本降到最低;

  • 实现与云端定时通讯,获取当前集群运行参数,根据定制化的策略,智能选择最优节点,拒绝“雪崩”情况的发生;

  • 自动剔除无法与云端进行心跳保持的节点,让上下线服务器,业务升级更加平滑;

  • 实现故障节点自动惩罚机制,连接类错误容错重试,将大大减少服务器“抖动”类问题。


非SOA架构的服务
对于非SOA架构的服务,因为kube-proxy使用iptables转发的效率问题,我们并没有直接采用Kubernetes的Service的方案,而是选择了聚美已有的一套API服务注册平台。这套平台主要是基于Consul集群、Consul-Template和Tengine/Haproxy来实现服务的管理。Consul集群本身支持多数据中心模式,我们将consul-agent容器和业务容器共同组成一个Pod实例。当容器服务器被拉起来时,consul-agent会根据ConfigMap定义好的健康检查接口对内部服务发起请求,只有服务状态正常的容器才会被渲染至Upstream或Backend配置当中去。

640


服务注册与销毁
运行在容器中的服务注册和销毁主要依赖Kubernetes的Pod生命周期管理的postStart和preStop钩子来实现的。在容器上线前,利用postStart调用我们预先定义好的health脚本去检查业务状态,当退出码为0时,我们认为容器服务正常,便会将服务注册到服务管理平台。同理,在容器销毁前,利用preStop去调用health脚本触发服务下线。在Kubernetes的编排中如下示例:

640



容器日志与监控

640


日志采集
容器内日志采集的问题,业界一直存在两个大方向,一种是日志落盘后通过log-agent方式将日志发往服务端,另一种是日志不落盘,通过异步方式发送日志到服务端。这两个方案各有各的好处,这里我们不做讨论。聚美云平台使用的是第一种方案,即业务代码通过聚美自研的日志组件MNLogger将正常日志和exception日志全部落地到服务器本地硬盘上,再由客户端发往至Logstash做日志过滤后转发至Kafka集群。日志采集客户端采用的是log-courier,实例是跟随着业务容器在一个Pod里面运行。

640


容器Mount目录
对于在容器中,如何将日志持久化到硬盘上,我们采用的是hostPath的方式,将挂载一个宿主机的日志目录给容器使用,而在容器里面主要通过创建软连接的方式将业务日志写入Volume当中。

640

640


监控服务
聚美在云平台之前就已经有了自己完善的监控体系,其中就包含链路追踪、日志监控、性能监控和统一告警几大要素。而对于云平台的接入,我们除了要收集业务的异常日志外,还需要对容器性能和状态的指标有一个全面的收集。

640


这里我简单列举两个点跟大家分享。
  1. 容器的性能数据的采集,云平台主要利用Prometheus联邦配合服务发现来实现的。对于不同业务逻辑的我们划分了三种服务类型的Promethues实例,最终由上层Prometheus实例负责汇总所有Metrics。这里需要着重强调的是,大家在自己在开发和设计Metrics的Labels时,应保证遵循一个统一的命名规范,最好能够结合被采集实例的元数据命名。这样有助于后期大家在出监控图时候利用Label关联多项Metrics。

    640


  2. 对更新正在运行时日志容器的配置文件,我们自己研发了日志采集管理平台,用户只需通过在平台上去更新日志采集路径、日志类型、kafaka topic_id等参数。参数提交成功后,平台会自动将其渲染成业务所需要的配置文件,并通过HTTP服务生成一个全局唯一的URL提供给客户端下载。当客户端检查到配置文件更新就会下载最新的配置文件,并触发进程的reload机制。

    640


内部应用场景

640


大促弹性扩容

聚美优品是一家以主打化妆品限时特卖的网上电商平台。众所周知,国内的电商平台每年都会有那么几天会推出"剁手"季的活动,例如刚刚过去的双11/双12购物节。那么该如何去满足公司在大促活动期间对资源的弹性需求呢,我这里简单发几条我们遇到的需求场景,希望起到抛砖引玉的作用引发大家思考:
  1. 扩容的资源需灵活调度容器,并支持跨机房的调度;

  2. 容器大规模上线或镜像更新,带来的镜像pull洪峰问题;

  3. 大促前需要业务承载能力进行压测评估,扩容资源会经历多次创建和销毁;

  4. 电商活动一般会在整点迎来处理请求的峰值,甚至在某个时间点前端请求出现翻数倍的场景;

  5. 对扩容资源的稳定和成本之间平衡出一个最优的结果。


其实聚美云平台内部,机房的网络环境与三方云提供商已经做了VPC网络专线的互通,对于大促期间扩容的计算资源,我们通过定义内部的元数据服务来确定在云主机启动之后自己该注册到哪个Region的Kubernetes Master。如果资源元数据发生变动,可以很快的通过下发脚本的方式重新对资源进行注册。
关于第2点,镜像洪峰问题,我们会提前将docker镜像植入到云主机镜像当中,这样当云主机在pull镜像时只需拉取镜像更新的差异层,可以节省大量流量,缩短容器上线时间。
对于第3、4、5点,我们主要利用Kubernetes的DaemonSet类型来满足容器的创建,调度和销毁需求。目前我们对于大促期间的容器使用策略是一主机一项目的机制,也就是说扩容的云主机上,我们只会调度一个项目的容器在上面运行,同时Pod的网络采用hostNetwork。这样主要有两个好处,一是调度足够简单,通过对Node添加项目标签的方式快速实现一个项目容器的上线。二是单容器实例可以有效避免因高并发来临时多容器间资源争抢问题引起滚雪球式的报错。另外还有一个不得不考虑的问题是云上容器网络选型问题。对于聚美私有云来说,公有云上的资源运行不是常态,所以我们会直接让容器使用主机网络与外部通信以降低网络的开销。

640


大数据Yarn弹性资源
聚美优品大数据团队的服务经常需要在凌晨跑各种业务统计数据和其它离线数据,受限于硬件资源的扩展,导致可用资源非常紧张,经常会出现数据出不来或者很晚才出来的情况,严重影响了业务同学的进度和工作。与大数据业务场景相反,业务的资源在凌晨的使用率是很低的,所以在今年年中,我们尝试和大数据团队合作,将大数据现有Yarn服务容器化后接入到的聚美私有云平台来弥补资源紧张的状况。
这里着重强调的是在Yarn容器下线过程中如果有任务正在执行,就可能导致这些任务失败。具体来说,当AM失败并且在配置的重试次数内,整个Application可以重新开始执行;如果是分配给Application(MR类型)的非AM用的Container挂掉了,AM会为其重新申请Container在其他机器上运行。所以我们修改Yarn源码让除了MR任务的Spark、Flink等任务不要分配到Docker容器中的Node上。还禁止了AppMaster分配到Docker节点中,避免因为下线Docker导致的任务异常。

640


结束语

640


总体来说,聚美云平台经过2年时间沉淀,能够满足我们大部分的日常使用场景。但是未来仍然有很多东西需要去持续优化和改进,例如对容器网络的QoS支持和动态的容器调度等等。
Q&A

640

Q:为啥采用Consul作为容器的服务发现与配置管理,而不采用默认的etcd?A:这个问题主要是聚美对于Web类服务已经存在了基于Consul的发现机制,所以云平台在推广时就利用了现有的架构。
Q:请问IPVLAN网络会不会导致容器内无法访问本地物理网卡?或者说宿主机无法访问本地的容器?A:这个问题很好,最初我们采用IPVLAN时也遇到了kubelet在通过Liveness探针时与容器网络不通。后来我们通过将主机网络和容器网络分开,解决了这个问题。
Q:服务间的Socket通讯原理是通过挂载Volume方式进行访问,这个/var/run/service内容能透露一下吗?是聚美优品的RPC框架通信协议文件吗?A:/var/run/service其实就是一个临时目录,里面就保存了Pod的各个Container中运行进程的Sockets文件。至于服务间(不同Pod间)通讯是聚美这边自己实现的一个私有的RPC框架通信协议。
Q:问一下,你那边的不同业务分配资源的时候是每个节点都打上labels吗?A:是的,我们主要还是通过label的的形式来做容器的调度。另外每个deployment都会通过resourcelimit来做资源限制。目前对于高资源利用的容器还是通过平台kill容器的方式,重新拉起新的容器。
Q:Prometheus是什么运行方式,拉取数据会有什么问题注意吗,单节点够用吗?A:目前我们Prometheus是部署在Kubernetes当中,根据不通过的服务发现模式做了逻辑切分。上层通过Prometheus Federation来统一汇聚数据。
Q:那不同的业务之间访问有状态应用是通过定义ExternalName吗?比如访问MySQL或Redis等?A:目前我们大部分跑在云平台上的容器都是无状态的服务,对于有状态的服务,还是建议通过传统的方式运行。
Q:请问你那边Pod是直接跑在虚拟机上吗,还是做了一层虚拟化分配使用虚拟机呢?A:Pod的运行主要分两块类型。对于DaemonSet方式运行的容器,我们大都通过虚拟机或者云主机来支撑,分享里面也提到我们通过DaemonSet方式来解决我们大促期间快速扩容的需求
Q:Pod跨节点的访问是怎么做到的,如果两个节点不在同一个swtich下,需要跨路由器的情况下?A:IPVLAN的网络是提前规划好的,并保存在网络配置管理平台上。对于IPVLAN不同网段的之间的通信,还是在三层交换机上做路由来实现的。


基于Kubernetes的DevOps实践培训

640?


基于Kubernetes的DevOps实践培训将于2019年1月18日在上海开课,3天时间带你系统掌握Kubernetes本次培训包括:容器特性、镜像、网络;Kubernetes架构、核心组件、基本功能;Kubernetes设计理念、架构设计、基本功能、常用对象、设计原则;Kubernetes的数据库、运行时、网络、插件已经落地经验;微服务架构、组件、监控方案等,点击下方图片查看详情。
640?

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

(0.50mm)TF31-4S-0.5SH 4 位置 FFC,FPC 连接器、G846A10221T4EU(1.0MM)矩形连接器 互连器件

TF31-4S-0.5SH (0.50mm)脚距前开盖式FFC/FPC连接器的安装深度为5.7mm,可最大限度地节省电路板空间,并能够自动放置电路板。Hirose Electric TF31连接器具有高FPC保持力(采用FPC侧拉手设计),易于…

形容谣言的四字词语_形容谣言的四字成语

形容谣言的四字成语以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 1. 中国20世纪的一位大作家说的 是余秋雨“谈中国文化弊病”说的。 造谣无责,传谣无阻;中谣无助,辟谣无路;驳谣无效,破谣无趣;老谣方去,…

以太坊是匿名化的影子银行?将如何适应并影响传统金融?

以太坊经常被描述为传统金融权力的对立面。实际上,以太坊的目标并不是去颠覆传统金融领域,而试图去补充和改善它。未来,这两个系统将会有更多的交集。 多极世界中的中立性 以太坊并不是一种隐形的货币替代品和匿名的影子银行,目前…

四、初探[ElasticSearch]集群架构原理与搜索技术

目录 一、浅析Elasticsearch架构原理1.Elasticsearch的节点类型1.1 Master节点1.2DataNode节点 二、分片和副本机制2.1分片2.2副本2.3指定分片、副本数量2.4查看分片、主分片、副本分片 三、Elasticsearch工作流程3.1Elasticsearch文档写入原理3.2Elasticsearch检索原理 四、El…

服务器修改合作模式,饥荒的服务器合作模式 | 手游网游页游攻略大全

发布时间:2015-11-21 合作模式专家难度 第一:FPS游戏的硬件基础 1.一个能帮你准确分辨声音方向的耳机.某些人,队友不在他的视线内被HUNTER扑了,SMOKER拉了,他浑然不知还津津乐道地打他前面的僵尸(特殊僵尸出 ... 标签: 生存之旅 发布时间:201…

未转变者2.2.4怎么创建服务器,未转变者2period;2period;4墙怎么做 | 手游网游页游攻略大全...

发布时间:2016-08-18 里面大家见过可以自动修复的墙吗?今天小编就为大家带来了我的世界可自动修复墙的制作视频教程,非常不错的哦,想学的话下面跟我一起来看看吧. 自动修复墙制作视频教程 标签: 攻略 我的世界 建筑 红石 视频解说 发布时间:…

背包DP-入门篇

目录 01背包: 完全背包: 多重背包: 分组背包: 01背包: [NOIP2005 普及组] 采药 - 洛谷https://www.luogu.com.cn/problem/P1048 01背包背景 在一个小山上,有个n个黄金和一个容量为w的背包,…

独自去旅行你必须知道的事—勇气小姐独行攻略(内有拍照秘籍哦)

前言 每一次准备出游前,遇到的朋友总会问我“这次和谁一起出发?”80%的时候我的答案都是“和我自己!”随着我一次次平安归来后分享的旅行趣事,朋友们的情绪也从担心、不解、疑惑转变成钦佩、向往和难以抑制的冲动。可是&#xff0…

Three.js打造H5里的“3D全景漫游”秘籍

近来风生水起的VR虚拟现实技术,抽空想起年初完成的“星球计划”项目,总结篇文章与各位分享一下制作基于Html5的3D全景漫游秘籍。 QQ物联与深圳市天文台合作,在手Q“发现新设备”-“公共设备”里,连接QQ物联摄像头为用户提供2016年…

QQ物联打造H5里的“3D全景漫游”秘籍

QQ截图20160524143715.jpg (21.15 KB, 下载次数: 15) 下载附件 2016-5-26 10:58 上传 近来风生水起的 VR 虚拟现实技术,抽空想起年初完成的“星球计划”项目,总结篇文章与各位分享一下制作基于 Html5 的 3D 全景漫游秘籍。 ————本文很长——能看完是…

html5 3d场景设计,打造H5里的“3D全景漫游”秘籍 - 腾讯ISUX

原标题:打造H5里的“3D全景漫游”秘籍 - 腾讯ISUX 近来风生水起的VR虚拟现实技术,抽空想起年初完成的“星球计划”项目,总结篇文章与各位分享一下制作基于Html5的3D全景漫游秘籍。 QQ物联与深圳市天文台合作,在手Q“发现新设备”-“公共设备”里,连接QQ物联摄像头为用户提…

星际战一直显示网络无法连接服务器,星际战甲服务器连接失败 | 手游网游页游攻略大全...

发布时间:2016-01-26 星际战甲可能很多玩家认为是个坑.因为有些段位的考试有点难.有点坑.所以会失败.那么来看看小编的星际战甲段位考试失败了怎么办 段位考试失败怎么重新参加吧. 当你在段位考试中失败,你需要等待24小时才能再次参加段位考试,同样 ... 标签&#x…

软件工程期末题目分析

一、软件工程概论 1.当你准备参与开发一个系统的时候,如果你对这个系统的问题领域不是很熟悉,那么最好不要采用以下哪种系统开发模型?(A) A、瀑布模型B、原型模型C、螺旋模型D、喷泉模型 瀑布模型模型要求用户需求明…

TS_React:类型化EventHandler

❝ 焦虑可分为「有用焦虑」和「无用焦虑」两种。 有用焦虑指向现在 无用焦虑指向未来,它的本质,是对现在失控的恐惧 ❞ 大家好,我是「柒八九」。 今天还是--「TypeScript实战系列」的文章。前面的文章中,我们从不同的角度介绍了&a…

OpenHarmony的线程间通信EventHandler

一、初识EventHandler ​ 在OpenHarmony的开发过程中,如果遇到处理下载、运算等较为耗时的操作时,会阻塞当前线程,但是实际操作中又不希望当前线程受到阻塞。比如:我们的app在界面上有一个下载文件的处理按钮,如果在按…

cocos 的EventHandler 事件派发器

cocos 的EventHandler 事件派发器 cc.Component.EventHandler 类 官方说明 “EventHandler” 类用来设置场景中的事件回调,该类允许用户设置回调目标节点,目标组件名,组件方法名,并可通过 emit 方法调用目标函数。 */export clas…

C# 的 事件 与 EventHandler

事件接受与发送是通过 委托来实现的,随意,在学习事件之前一定要知道委托。 首先我们先看下图:上的图不完整人,但大概是这个意思。 我们要创建一个事件管理。 来处理发布者发送消息和订阅者的接受消息中间转接。 然后订阅者去创建…

C# 实例解析事件委托之EventHandler

概述 事件属于委托的一个子集,像我们平时界面上的鼠标点击按钮后响应事件、事件的发布和订阅等都需要用到委托.通过委托可以很好的实现类之间的解耦好。事件委托EventHandler的 函数原型如下:delegate 表示这个个委托,事件委托没有返回值&…

wpf中EventHandler的使用

应用情景:比如点击A界面的a按钮,跳转到B界面了,点击b按钮后,触发了业务逻辑,然后需要回到A界面中执行某一个方法。不是唯一的方法,可以使用别的方法,类似观察者模式,有变化了&#x…

使用Transformer模型进行计算机视觉任务的端对端对象检测

Transformer模型是google团队在2017在论文attention is all you need中提出的一个用于NLP领域的模型,但是随着VIT模型与Swin Transformer模型的发布,把Transformer模型成功应用到计算机视觉任务中。 上期图文,我们使用hugging face的transformers模型进行了VIT模型的对象分…