阿里如何实现100%容器化镜像化?八年技术演进之路回顾(转)

本文系转载。可以参考文中的以下内容:

  • 阿里的容器框架的演进路线;
  • 在大公司内部、跨多部门、并且已经有大量现有系统情况下的推广实施方案;
  • 框架设计的方法论、设计图纸等。

八年时间,阿里集团实现了 100%内部容器化镜像化,经历了几代演进。本文将从最初的架构开始,向大家介绍下阿里内部的容器化演化过程。

PouchContainer 现在服务于阿里巴巴集团和蚂蚁金服集团的绝大部分 BU, 包括交易&中间件,B2B/CBU/ICBU,搜索广告数据库,还有收购或入股的一些公司,比如优酷高德、UC等。其中体量最大的是交易和电商平台,在 2017 年双 11 的时候我们支撑了破纪录的峰值,背后的应用都是跑在 PouchContainer 里面,整体容器实例已经到了百万级规模。使用了 PouchContainer 的应用涵盖了各种各样的场景。这些场景从运行模式来看,有标准的在线 App,还有像购物车、广告、测试环境等比较特殊的场景。不同的场景对 PouchContainer 有不同的使用方式和需求。

从编程语言看,实际运行着 JAVA、C/C++,Nodejs,GoLang 等语言编写的应用。从技术栈的角度看,包含了电商、DB、流计算、大数据、专有云等场景,每个场景对于容器各方面要求,所用到的特性都不太一样,PouchContainer 针对每个场景的需求都在产品上都做了支持。

PouchContainer 容器技术在阿里的演进过程伴随着阿里技术架构本身的演进。阿里内部技术架构经历了一个从集中式单体应用到分布式微服务化的演进。

淘宝最开始是一个巨石型的应用,一个应用里包含了商品、用户、下单等等所有交易链路的功能。随着功能越来越完善,维护起来也越来越困难。为了提高研发效率,从 2008 年开始我们逐渐把这个应用拆分成了多个分布式应用,商品的,交易的,用户的,前台的,后端的;通过 HSF 远程调用框架,TDDL 分布式数据层和 Notify 分布式消息中间件串联起来。其中每个服务都有多个实例,都可以独立研发演进,并可以进一步继续拆分。于是就逐渐形成了一个庞大的分布式服务集群。

从巨石型应用到多个单一功能的轻量级服务型应用,总的应用实例数变多了,每个实例需要的系统资源变少了。于是从最初的每个实例直接使用物理机自然过渡到使用 xen,kvm 等虚拟化技术。VM 使用了一段时间之后,发现整体物理机的利用率还是很低。当时一个 24 核的物理机只能虚出 4 台 4 核的 VM,除了当时虚拟化本身的开销不小外,每个应用实例在 VM 里仍然用不完分到的资源。于是就想能不能不用虚拟机,用更轻量的基于进程级别的资源切分使用方式。

这个时候阿里内部的运维体系已经比较庞大了,从应用的构建部署到分发,到一些运行期的监控告警等管控系统,都依赖于一个应用实例跑在一个独立机器里的假定。这个假定已经不经意间贯穿到了研发运维的各个环节里面,包括系统的设计,运维习惯等都严重依赖这个假定。我们不可能重新搭建集群,把存量的业务停掉再到新的集群里面用新的运维模式去跑起来,这个业务和运维上都是没法接受的,不可能电商交易的研发停几个月,系统停几天来搞这个事情。所以我们首先要做到兼容,新的资源使用方式必须兼容原先的假定。我们经过仔细分析了这个假定的内涵,发现每个应用实例归纳下来无非有如下 4 点要求:

  • 有独立IP
  • 能够ssh登陆
  • 有独立的,隔离的文件系统
  • 资源隔离,并且使用量和可见性隔离

首先是有独立 IP,能够 SSH 登录。其次有独立的文件系统,应用程序跑起来,希望程序看到的整个文件系统都是给他专用的,因为现有的代码和配置中必然有很多路径的硬编码,需要满足这个潜在要求。还有不管通过工具还是代码,他只能看到分配给他自己的资源。比如 4 个 CPU,8G 的内存,他能够根据这些资源的用量做一些监控,做一些对自己资源使用量的采集和告警。这四个特点总结下来就是新的资源使用方式要做到和物理机或者 VM 的使用体验一致。能够做到这样的话原先跑在 VM 里的应用就可以很平滑的迁移过来,现有的应用系统和运维系统不需要做很大的改动。

我们为了能达到这四点,最开始是多隆大神手工 Hack 系统调用,glibc 基础库等,实现了一些资源上的隔离。像有独立的 IP 可登录 ,就用虚拟网卡,在每个容器里面起一个 sshd 进程;资源的隔离和可见性上,就用 Cgroup 和 Namespace 等内核特性;后来发现开源的 LXC 项目也在做同样的事情,并且比手工 Hack 更通用化,更优雅一些。于是我们集成 LXC,并且在内核上加了定制的资源可见性隔离的 patch,让用户的实例只能看到分配给他的 CPU和内存,另外还增加了基于目录的磁盘空间隔离的 patch,这样就形成了我们第一代的容器产品。这个产品当时代号是 T4,寓意是第四代淘宝技术,淘宝 4.0;在 2011 年的时候 T4 容器技术灰度上线。

T4 相比 VM,完全没有虚拟化 Hypervisor 层的开销,资源切分和分配上更加灵活,可以支持不同程度的资源超卖。这样就很好的支持了业务爆发增长的需求,控制了物理机按业务增长比例膨胀的势头。另外因为 T4 完全兼容了之前研发和运维对物理机和 VM 的使用习惯,绝大多数应用都能够做到透明的切换,应用无感知。因为有这些特性,在接下来的短短几年时间里,T4 逐步接管了交易和电商主体的在线应用。

到 2015 年的时候 Docker 技术火起来了。我们写程序的都知道有个著名的公式,程序=数据结构+算法。从程序交付使用变成一个软件产品的角度来看,我们可以套用这个公式:

  • 软件= 文件(集)+ 进程(组);

从静态来看,软件从构建分发到部署,最终形式是一个有依赖层次的文件集。从动态来看,这些文件集,包括二进制和配置,由操作系统加载到内存后执行,就是一个有交互关系的进程组。我们之前的 T4 容器在进程(组),或者说运行时上做的事情和 Docker 基本类似,比如说都使用了 Cgroup、Namespace、linux bridge 等技术。还有些是 T4 特有的,比如基于目录的磁盘空间的隔离,资源可见性隔离,对老版本内核的兼容等。

我们从最早物理机演化到 VM,再到现在的容器,内核的升级周期比较漫长,迭代很慢,15年的时候存量的机器上全部都是 2.6.32 内核,T4是兼容 2.6.32 内核的。 但是另一方面在文件(集)的处理上 Docker 做得更好,更加系统化。 T4 只做了很薄的一层镜像,给相同的业务域做了一个基础的运行和配置环境,这个镜像没有深入到每一个特定的应用。 而 Docker 是将每个应用的整个依赖栈打包到了镜像中。因此在 2015 年我们引入了 Docker 的镜像机制来完善自己的容器。

img

在将 Docker 镜像整合进来之后,原来基于 T4 的研发运维体系受到了很大的冲击。 首先交付方式变了,之前是 build 一个应用的代码包,把代码包交给我们的部署发布系统,后者创建一个空的容器,根据这个业务所在的很薄的模板把一个空的容器跑起来,再到容器里面安装依赖的一些 IPM 包,设置一些配置,按每个应用定好的一个列表一个一个的安装好,然后把应用包解压启动起来。这个应用依赖的软件和配置列表我们内部叫做应用的基线。

引入镜像之后,在将 Docker 镜像整合进来之后,原有的交付方式发生了变化。之前是 build 一个应用的代码包,把代码包交给我们的部署发布系统,后者创建一个空的容器,根据这个业务对应的很薄的一个模板,把一个空的容器跑起来,再到容器里面安装依赖的一些 RPM 包,设置一些配置,按每个应用定好的一个清单一个一个的安装好,然后把应用包解压到主目录启动起来。这个应用依赖的软件和配置清单我们内部叫做应用的基线。引入镜像之后,我们应用的代码包和依赖的所有的这些三方软件、二方软件都会打成一个镜像。之前通过基线维护应用依赖环境,现在都放到每个应用自己的 Dockerfile 中了,整个研发构建和分发运维的过程大大简化了。

做了这个事情之后,研发和运维之间的职责和边界就发生了变化。之前研发只需要关注功能,性能,稳定性,可扩展性,可测试性等等。引入了镜像之后,因为要自己去写 Dockerfile,要了解这个技术依赖和运行的环境倒底是什么,应用才能跑起来,原来这些都是相应运维人员负责的。研发人员自己梳理维护起来后,就会知道这些依赖是否合理,是否可以优化等等。

研发还需要额外关注应用的可运维性和运维成本,关注自己的应用是有状态的还是无状态的,有状态的运维成本就比较高。这个职责的转换,可以更好的让研发具备全栈的能力,思考问题涵盖运维领域后,对如何设计更好的系统会带来更深刻的理解。所以引入 Docker 之后对研发也提出了新的要求。我们总结新的时期,新的运维模式下对研发能力要求的几个要素,总结起来就是几个原则:

img

为了更好的把自己的系统建设好,我们要倡导研发从第一天建立系统的时候,就要考量最终的可运维性,比如参数是否可配置,是否可以随时重启。机器每天都有硬件故障产生,这些硬故障不可能每天都人工处理,必须要尽可能自动化处理,自动化处理时,虽然有些故障只影响了一部分实例,另一部分是好的,但是也可能需要一起处理,比如需要物理机上的业务全部迁移走来维修物理机的时候。所以不管当时容器里的业务是好的还是不好的,都要满足随时可重启,可迁移的要求。原来是部分交付,现在要考虑你到底运行环境是什么样的,什么样的运行环境才能跑起来,尽量做标准化的操作。

比如说启动,Dockerfile 里面写好启动的路径,不要再搞一些特殊的处理,如果有任何特殊的处理都没法做统一的调度和运维。统一的业务迁移,机器腾挪也没法做。我们的目标其实就是从一开始的比较粗放的运维,到不断的开发自动化的工具和系统,形成一个体系,通过前期人工运维的过程把一些固定的故障处理的流程模式化,最后提取出来一些可以自动处理故障,自动恢复的机制。我们的最终目标是无人职守。所有这些加起来其实就是我们引入镜像化之后,并且要朝着无人值守的方向演进时,对研发和运维的新的要求。

为了更好地把自己的系统建设好,我们要倡导研发从第一天建立系统的时候,就要考量最终的可运维性,比如参数是否可配置,是否可以随时重启。机器每天都有硬件故障产生,这些硬故障不可能每天都人工处理,必须要尽可能自动化处理,自动化处理时,虽然有些故障只影响了一部分实例,另一部分是好的,但是也可能需要一起处理,物理机上的业务全部迁移走来修物理机。所以不管当时容器里的业务是好的还是不好的,都要接受随时可重启,可迁移。原先是部分交付,现在要考虑你到底运行环境是什么样的,什么样的运行环境才能跑起来,尽量做标准化的操作。

比如说启动,Dockerfile 里面写好启动的路径,不要再搞一些特殊的处理,如果有任何特殊的处理都没法做统一的调度和运维。统一的业务迁移,机器腾挪也没法做。我们最后的目标其实就是从一开始的比较粗放的运维到很多人都能介入,到最后的自动化不断的开发自动化的工具,形成一个体系,通过前期人工运维的过程把一些固定的故障处理的流程模式化,最后提取出来一些可以自动处理故障自动恢复的机制,最后我们的目标是无人职守。所有这些加起来其实就是我们引入镜像化之后,并且要朝着无人值守的方向演进时,对研发和运维的新的要求。

img

上面是 PouchContainer 容器的 Roadmap, 2011 年的时候 T4上线 ,到 2015 年 3 月的T4 覆盖了交易的大部分应用。这个时候开始引入了 Docker 镜像机制,这里面做了很多兼容性的工作。

比如说原来 T4 轻量化的模板转化成对应的基础镜像,里面兼容了很多之前运维的习惯和运维的工具,如账号推送,安全策略,系统检测。我们在 2016 年初上线了第一个镜像化应用,到 5 月份的时候集团决定主站全部应用容器化。在做镜像之前阿里是有一两百人的团队做每个应用的部署,运维,稳定性控制,后来这个团队都没有了,全部转成了 DevOps,转向开发工具和运维平台,通过代码的方式,工具的方式解决运维的问题。之前专职做运维的同学最大的负担就是线上环境的变更,研发提交变更申请给运维同学,运维同学做线上操作,研发不知道代码运行环境具体依赖了哪些基础软件。

做了镜像化的事情后,研发自己负责编写 Dockerfile,运维就把环境变更的事情通过 Dockerfile 的机制移交给了研发。运维和研发之间的边界就非常清楚了,这个边界就是由 Dockerfile 来定义的。研发负责把他代码依赖的环境在 Dockerfile 定义好,运维保证其构建分发时没有问题。我们在 2016 年双11的时候完成了交易核心应用的镜像化 PouchContainer 化改造。在 2017 年双11的时候交易全部应用完成了镜像化改造。然后我们在 2017 年 11 月 19 日的时候宣布了 PouchContainer 的正式开源。

我们的内部 PouchContainer 经过大规模的运行,支持了各种各样的业务场景,各种不同的技术栈,不同的运行形态,积累了非常多的经验。这些经验之前跟阿里内部的环境耦合性比较大。比如说我们的网络模型,我们其实是嵌入到了阿里内部的网络管控平台,包括IP分配在内部都有独立的系统去完成。比如什么时候启用 IP,什么时候下发路由等等,这些是有一个统一的 SDN 网络管理系统来管理的。还有类似的内部存储系统,还有运维的一些指令推送系统。内部系统耦合性比较大,没法直接开源。

所以我们最后选择的策略是先在外部孵化一个从零开始全新的项目,把内部的特性一点点搬上去。这个过程中我们内部的版本也会做重构,把内部的依赖做一些插件化解耦合的方式,这样最后全新的项目在外部可以跑得很好;在内部用一些耦合内部环境的插件也可以跑起来,最终的目标是内外用一套开源版本。

那么我们的 PouchContainer 容器相对于其他容器有什么差异呢?主要体现在隔离性、镜像分发优化、富容器模式、规模化应用和内核兼容性几个方面。传统的容器隔离维度就是 namespace、cgroup;在资源可见性方面,我们前几年是通过在内核上打 patch,在容器内看内存和 CPU 利用率等数据时,把统计数值和当前容器的 Cgroup 和 Namespace 关联起来,使容器能使用的资源和已使用的资源都是容器自己的。

18年的时候我们引入了社区的lxcfs,这样就不需要对特定内核 patch 的依赖了。磁盘空间的限制也是在低版本内核上加了补丁,支持了基于文件目录的磁盘空间隔离,能够把每个容器的 rootfs 限制住。在 4.9 以上的内核上,我们是用 overlay2 文件系统来完成同样功能的。我们也在做基于 hypervisor 的容器方案,提升容器的隔离性和安全性,我们在 PouchContainer 里面集成了 RunV,用于一些多租户的场景

img

阿里内部的离在线混部之所以能推进,在同一个机器上既能跑在线的业务又能跑离线的一些任务,互相之间不会出现太大的干扰,其核心的技术就是 PouchContaienr 容器可以根据优先级,把不同业务的资源使用隔离开来,保证在线业务优先使用资源。这个资源包括很多的维度,比如 CPU、内存,CPU cache、磁盘、网络等等。

img

这是 PouchContainer 的镜像分发设计。我们内部有很多比较核心的应用,体量比较大,实例会分布在上万台物理机上。发布新版本的时候上万台机器同时拉镜像,任何中心的镜像仓库都扛不住。因此我们设计了一套镜像分发的二级架构,在每个地域建一个 mirror,在同一个地域内拉镜像的时候用 P2P 分发技术---我们内部的产品名叫蜻蜓,已经开源;需要拉镜像的服务器之间可以分散互相拉文件片段,这样就直接化解了中心镜像仓库的服务压力和网络压力。

后面其实还有更好的解决镜像分发的思路,我们正在尝试镜像的远程化,通过存储计算分离技术,用远程盘的方式挂载镜像,直接跳过或者说异步化了镜像分发这一步,目前正在内部环境灰度运行中。

img

这是 PouchContainer 内部版本的体系结构。在最底层的宿主机层面,我们会做一些管理和运维,目的是为了确保容器运行依赖的基础环境是健康的,包括宿主机的一些镜像清理,包括安全控制、权限管理等。OS 的低版本内核我们是适配到最低 2.6.32 内核,包括容器里面的进程管理也做了很多的适配。资源隔离前面讲过了,网络模型我们内部其实主体用的是 Bridge,但是其他各种各样的场景也都支持。

我们开发了很多插件,PouchContainer 开源后,我们才将这些插件逐步做了标准化,兼容适配了社区的 CNI 标准。最上层是一个富容器模式的支持,每个容器里面会启动一些跟内部的运维工具,运维系统息息相关的一些组件,包括一些发布模式的优化。可以看到我们内部体系结构是比较复杂的,尤其依赖内部的其他系统比较多,在外部直接跑是跑不起来的,因此也没法直接开源。

img

所以我们开源版本是重新开始搭建的,这样会比较清爽一些。我们引入了contained,支持不同的 runtime 实现,包括我们自己包装 lxc 开发的 RunLXC 运行时,可以用来支持老版本 2.6.32 内核。开源版 PouchContainer 兼容所有 Docker 的接口,也支持 CRI 协议,这样也就同时支持了比较主流的两种集群管理系统。

网络方面我们内部基于 libnetwork 做了增强,包括不同场景暴露出来的一些问题,一些稳定性,规模化的时候各种细节的一些优化。存储方面我们支持了多盘,内存盘,远程盘等各种不同形式的存储。PouchContainer 可以无缝集成到上层编排工具中,包括 Kubelet 和 Swarm 等。我们内部的 Sigma 调度系统,不同的版本Docker 协议和CRI协议都会使用。

这是 PouchContainer 的开源地址:https://github.com/alibaba/pouch

如何贡献:

https://github.com/alibaba/pouch/blob/master/CONTRIBUTING.md

最近 PouchContainer 开源版本 GA 已经发布,PouchContainer 能够在如此短的时间内 GA,离不开容器社区的支持,在超过 2300 个 commit 的背后,有 80 多位社区开发者的踊跃贡献,其中不乏国内一线互联网公司、容器明星创业公司贡献者的参与。

PouchContainer 开源版本发布 GA 之前,此开源容器引擎技术已在阿里巴巴数据中心得到大规模的验证;GA 之后,相信其一系列的突出特性同样可以服务于行业,作为一种开箱即用的系统软件技术,帮助行业服务在推进云原生架构转型上占得先机。

【Q&A】

Q:你们是怎么样做到把阿里巴巴集团包括高德还有菜鸟那些,都能把这个技术推过去,因为大公司在不同的部门跨部门甚至是跨子公司之间要想推行你们的某一个部门的研究成果是一件比较困难的事情。

A:这是一个好问题,我们其实也面临过这个问题。我们的方法就是首先要和大家宣导这个理念,让大家在认知上都接受镜像化运维能带来的优势,长远发展的好处。虽然很难有直接立竿见影的收益,长远来看一定能提高运维效率,降低资源使用的成本。实际上从这两年来看,我们确实降低了不少运维成本。

Q:你好,我想问一下容器里面的那些持久化是怎么处理的?

A:容器我们持久化现在大体分两类数据,一个是日志,一种是应用自己会写一些数据,像搜索业务。要么就是放在本地盘,放在本地的话做迁移的时候要自己处理数据的迁移,每个不同的业务处理的都不太一样。还有一种方式是用远程,数据远程化。我们有分布式存储系统“盘古”,通过容器创建的时候在远程存储集群建一块远程盘,我们现在用的是块设备,然后挂载到容器里面,容器用完或者是迁移的时候,数据是在远端的,可以随意迁移到另一个地方,再把这个数据盘挂载回来。

搜索也可以放远端,对于阿里各种搜索场景,我理解如果replica数多的话,用远端存储是比较经济划算的,如果replica数就1行,或2行,而且远端性能又满足不了部分场景的需求,短时间内就不如本地多块盘来进行混部。总体趋势来说,如果没有性能要求的话,都放远端是趋势。

Q:哪种方式会更多一些?

A:宿主机直接到容器里面,相对来说最大的场景是在数据库,数据库现在大部分是在本地,但是有一部分是放在远端的,正在演进的过程中,还没有百分之百完成存储计算的分离。后面有一天可能就完全没有本地数据了。

Q:这是云框架,一听到云这个架构就感觉很大,是一个什么海量运维,海量数据,对于中小型公司规模可能没那么大,对于要想用这套框架,实施的成本是多少,用户量在多少以下适合或者不适合?

A:很难有明确的临界点,说什么时候该用云化架构了。从中小型公司来说可以从第一天就往这个方向,或者是朝这个模式去实现。比如说搭一个很小的资源池,通过弹性混合云的方式,在云上去扩容,这也是一种很好的方式。如果第一天完全不考虑这些事情,怎么方便怎么搭建,也不考虑这些单点,容灾这些弹性的事情,后面改造起来可能就会比较痛苦。

Q:这个部署的成本,两个人或者三个人的研发团队,用你这个东西周期有多长时间呢?它的难易度,因为要理解整个框架,你要部署这个东西要理解这个东西,我觉得学习的曲线还有部署的难度到底是什么样的?

A:后面这套系统在做 Sigma 敏捷版就是解决中小企业的问题,两三个开发者不可能开发出一套像现在这个规模的完整云化架构,最好的是用云上支持这些场景的产品。云产品本身经过很多用户的考验,有这么多云上运作的一些经验,一些技术上的沉淀,比自己开发要靠谱得多。

Q:我想问一下 PouchContainer 这个容器跟底层还会去封装 Docker 之类的东西,我第一次接触这个,另外镜像库的话是能够跟 Docker 兼容吗?

A:首先镜像库跟 Docker 是完全兼容的,Docker 分了很多层,底层的 runv 和 containerd都贡献到了社区,是开源的,我们在 runv 和 containerd 的基础上做了增强。总体来说是兼容两个社区的两种主流的技术路线,两种集群管理系统,kubernetes 和 Docker 公司 swarm,这种两种路径都支持。


原文地址:原文

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

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

相关文章

project日历设置-大小周交替

关键点是用到日历中的“例外日期”的重复周期功能 效果 2020年1月 1月19日是 2020年春节调休,要上班,工作日 2020年2月 2月1日是2020年春节放假,不上班,非工作日

Axure元件库:ElementUI元件、蚂蚁金服元件

2022年12月31日更新 ant design 已更新到5.x版本,目前官网还没提供 axure的元件库,下文的入口官网已取消,资源可关注我的微信公众号,输入:axure,获取以下元件库,免费,祝设计愉快&am…

c++new时赋初值_优质 quot;嵌入式C编程quot; 必备指南

来自公众号 : 嵌入式ARM整理:bug菌1、聊一聊本文是bug菌为大家整理的好文,C语言其实是非常简洁的语言,语法相比那些高级语言可以说非常小巧了,然而C语言在嵌入式中却有着其独特的魅力,本文为大家展示了C语言在嵌入式中…

二手交易平台html代码,二手物品交易HTML5模板

二手物品交易HTML5模板资源下载此资源下载价格为4D币,请先登录资源文件列表codedown123-0820-18/about.html , 9117codedown123-0820-18/contact.html , 8364codedown123-0820-18/css/app.css , 115913codedown123-0820-18/img/accountcover.jpg , 74024codedown123…

浏览器安装Axure插件与配置

Axure发布到本地的html包,打开需要Axure插件。 chrome浏览器安装插件需要翻墙或者导入下载好的插件文件,不是太方便。国内的360极速,qq浏览器的应用扩展不需要翻墙,可以直接搜索安装。下面演示360极速浏览器的Axure插件安装与配置…

matlab 滤波器设计 coe_一种半带滤波器的低功耗实现方法

在如今数字技术中,半带滤波器因其通带阻带对称,系数具有偶对称性且滤波器阶数为奇数,有效系数少等特点广泛应用于通信、视频处理、语音识别等数字信号处理应用中,尤其常用于实现信号的2倍抽取。对于一个阶数为N(N为偶数)&#xff…

产品设计:APP个人信息保护指引

需求分析 2019年11月4日,工业和信息化部展开APP侵犯用户权益专项整治行动。即日起各安卓应用市场根据最新的规则审核市场里的各应用,审核不通过将下架处理。 调研了“手机qq”、“抖音”、“快手”、“今日头条”、“澎湃新闻”等APP&#xff0…

说说GIL

上一篇:线程深入篇引入 Code:https://github.com/lotapp/BaseCode/tree/master/python/5.concurrent/Thread/3.GIL 说说GIL 尽管Python完全支持多线程编程, 但是解释器的C语言实现部分在完全并行执行时并不是线程安全的,所以这时候…

2021重庆高考成绩名次排名查询,重庆高考排名对应大学-重庆高考位次大学(2021年理科)...

选择科目测一测我能上哪些大学选择科目领取你的专属报告>选择省份关闭请选择科目确定v>每年高考结束后,报大学、选专业、填志愿就成了考生与家长十分关心的一件事情。本期,圆梦志愿为大家整理了重庆高考理科2020年位次排名对应的大学,供…

Project项目信息的日程排定方法区别

日程排定方法分:项目开始日期,项目结束日期。 项目开始日期 设置如下 在“工期”单元格输入任意数字,任务开始日期会从项目开始日期2020年3月1日开始 给项目任务设置工期的时候,从任务的第一个开始设置,按正序进行&a…

gis里创建要素面板怎么打开_周末技术流 | GIS三维热力图分析

周末技术流NOW现在行动!我们的技术流是一个系列,最终带大家出一套完整图纸哦~(未经允许严禁盗用🚫)Rhino日照分析1.前期回顾本期内容一直关注我们的朋友到这期可能会有点熟悉,确实,我…

project提醒:无法链接这些任务,因为它们已通过另一个任务链链接

给45任务指定前置任务111时,提示“无法链接这些任务,因为它们已通过另一个任务链链接” 查了好久没找到原因,后来无意在46任务前置任务输入111,没有提示。 解决方法: 删除了提示的45任务,新建任务&#x…

企业网站 源码 e-mail_天津seo优化套餐服务收费_天津网站优化关键词价格

天津华阳在线专注于SEO关键词排名优化,品牌网站建设,营销型网站建设,App、小程序开发,搜索引擎seo优化,竞价托管sem,品牌口碑建设与代运营等服务。企业通过引进前BAT产品经理不断丰富产品线优化技术实力&am…

必须Mark下,2019 年度中国质量协会质量技术优秀奖

曾经和一群可爱的人儿做的项目,获得了2019 年度中国质量协会质量技术优秀奖,无心插柳柳成荫。 那几年工作得很快乐,工作与家庭都兼顾,是同事也是朋友。2019年末去过一次移动宁波分公司,特意去看了原来驻场的办公室&am…

python文件编码及执行

兼容中文编码 由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。 当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文…

这些Windows 10隐藏秘技,你知道几个?

1. 虚拟桌面 玩电脑的老鸟,估计都听说过虚拟桌面。简言之,平时要做的工作太多,又没有第二个显示器,那么“虚拟桌面”也就成了不二之选。微软Windows 10的虚拟桌面隐藏在WinTAB中,也就是所谓的时间线视图(T…

vant toast loading 倒计时_日期倒计时软件哪个好 苹果日期倒计时软件推荐

日期倒计时软件哪个好,相信大家也是经常会查看日期,来保证一些重要的事情能够按时进行,那么哪一款日期倒计时软件比较好用,能够提醒用户们日期将至呢。这里就为大家推荐几款。日期倒计时软件哪个好1.Days Matter Air作为Days Matt…

业务应用系统的业务操作日志设计

目的:记录业务的访问活动 操作时间:精确到秒 服务器IP:可能部署多台服务器,记录当前线程服务器IP地址 访问者IP:访问者ip地址 访问者账号:系统通过手机号登录,记录手机号 业务名称&#xf…

c char转int_c/c++基础之sizeof用法

在 C/C 中,sizeof() 是一个判断数据类型或者表达式长度的运算符。1 sizeof 定义 sizeof 是 C/C 中的一个操作符(operator),返回一个对象或者类型所占的内存字节数。The sizeof keyword gives the amount of storage, in bytes, as…

非结构化数据与结构化数据提取---- BeautifulSoup4 解析器

CSS 选择器:BeautifulSoup4 和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。 lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM的,会载入整个文档&#xff0c…