2024年2月
亿级流量高并发春晚互动前端技术揭秘
前言
2022年1月,京东成为央视总台2022年春节联欢晚会独家互动合作伙伴,双方在红包互动、电商等方面展开全方位深度合作。在除夕当天产生691亿次互动,送出15亿元红包好物。
如何在这种大规模、高并发的场景下,确保系统的稳定性和性能,为用户提供稳定流畅的互动体验,成为了我们亟待解决的问题。
接下来我们主要从静态资源优化、缓存、容错、工程化几个方面来详细介绍前端团队所做的努力和创新。
静态资源优化
首屏资源加载策略
在春晚主持人口播之后,大量用户会集中在一段时间内涌入互动页面,这会导致流量峰值。为了降低页面打开时的请求次数和资源体积,我们根据页面交互,将所需资源分为三类:首屏、次屏以及操作后。
首屏资源主要包括:HTML文档、JavaScript、CSS以及样式图片。由于这是单页面应用,我们可以通过常规技术将JS和CSS进行打包。对于样式图片,我们可以通过按需加载的方式,显著减小首屏资源体积。
页面包含两个楼层,首屏的互动楼层和次屏的万券齐发楼层。其中,首屏会展示两排优惠券,因此,我们需要在首屏加载这部分券楼层的样式图片。互动主玩法中主要包括抽奖弹窗、邀人弹窗和击鼓游戏。通过拆分优化,首屏的样式图片体积减少约41%。再加上
CDN
降质和
WebP
参数的优化,样式图片的体积可以降低到178KB。
同时,我们将需要单独加载的击鼓游戏精灵动画图从首屏加载清单中剥离,使得首屏样式图片的加载次数从2次减少到1次。这样一来,用户在打开页面时,所需的请求次数和资源体积都得到了显著降低,进而提高了用户体验。
动画图片低损压缩
动画是页面资源消耗的主要部分。在春晚页面中,我们需平衡用户交互体验与资源优化。经过与设计和
CDN
团队多次沟通,我们决定采用技术手段降低资源消耗,同时保证用户体验。
首先是确定技术方案。设计团队最初提议使用3D模型,需借助
WebGL
进行渲染。但这存在两个问题:一是资源消耗大,3D模型通常包含3~4个文件,首屏加载请求数增加;二是兼容性问题,WebGL在低端机型上表现不佳。考虑到观众范围广泛,我们决定选用兼容性更好的方案。
经过技术调研,我们最终确定采用帧动画方案:设计团队将3D动画转化为精灵图,并将不变部分(如鼓架)单独抽离。精灵图仅包含运动部分(如鼓面敲击动画),有效降低资源消耗。

在确定方案后,设计团队导出了第一版资源文件。然而,精灵图大小为1236KB,主光效也有400KB,离我们的目标还有一定差距。经过双方反复尝试,我们通过抽帧方式将击鼓精灵图从24帧降至4帧,大小从1236KB降至265KB。结合降质参数和
WebP
格式,最终大小仅为78KB,下降了93%。此外,我们将主光效换成放大一倍的一倍图,并通过CSS属性scale实现放大,进一步节省资源。
雪碧图方案的演进
元素背景图使用雪碧图模式,是前端基本优化手段,可以显著降低请求次数。我们在首屏资源拆分后的情况下,可以将18个样式背景图合并成1个。相较于常规方案,春晚红包还扩展了2个功能:
1、css雪碧图在运行时为图片URL添加
CDN
降质参数和webp格式转换参数(someimage.png!q70.webp),极限降低CDN带宽。我们扩展开发了自动雪碧图脚本,可以支持自动生成2套
background-image
样式代码,分别对应普通图片URL和带!q70.webp的URL。通过运行时检测webp支持特性,切换HTML标签上的class名,来使对应的后代选择器的
background-image
属性生效。对于
webp
的特性检测的技术方案,我们考虑过如下两种方案:
a、通过版本判断,从caniuse看,可以按照只有iOS14以下不支持webp来作为判断依据。

b、通过创建一个Image对象,其src为一个基于base64的webp图片,根据load是否成功来判断是否支持webp。
比较这2个方案,方案a的优势是通过UA判断系统版本是同步执行的,可以在调用渲染页面前的任意地方执行并修改HTML标签的class属性。确保内容渲染后有正确的背景图css生效。不会对原有渲染逻辑产生入侵性修改。而方案b的优势是经过大规模实践,判断逻辑的可靠性较高,缺点是异步逻辑的,需要修改原来的渲染逻辑。由于我们这次需要支持全国亿万用户,为确保稳定可靠,所以最终选择方案b。
css文件中的背景图样式,是在渲染相应DOM的时候才发起请求,又由于React渲染是同步的,我们需要调整执行render的时机,以确保在渲染页面内容之前完成HTML的class属性设置,避免请求两次图片。

2、动态雪碧图。万券齐发楼层首屏露出2排8个坑位,对应8次logo图片请求,由于券和logo的数据是通过接口下发的,所以无法使用编译时雪碧图方案。为了将图片请求次数减少到1次,我们和后台、视觉、产品沟通后,设计了一套多团队协作的方案。设计同学可以根据产品提前确认的券位置将logo图合并成雪碧图,并上传到云存储。展示如下:

雪碧图规格确定后,通过固定的
background-position
属性,以及动态设置logo元素的
className
和背景图,即可实现动态雪碧图。

自动衍生WebP背景图css代码
上面提到运行时判断是否使用webp背景图,那对应的css代码就需要两套,利用PostCSS插件可以在编译时自动基于原有背景图样式代码生成webp背景图的代码,在紧张的开发过程中避免出错和遗漏。通过使用PostCSS插件中,CSS对象的
walkDecls
方法,我们可以遍历所有的
background-image
属性。然后,使用正则表达式匹配对应的样式,在编译打包时生成一套.webp .origin-class选择器的样式。在运行时,如果HTML标签具有
webp
属性,系统将后代选择器的样式覆盖原有样式。

除了img标签,我们在背景图也进行了webp优化,使得全站图片由902.4kb减小到512.6kb,经过多种流量和兼容性测试效果表现良好。由此可见,在项目中大量使用图片时,
WebP
格式已成为一个不容忽视的性能优化关键。
降低服务器成本及风险
春晚活动是一个典型的秒杀业务场景:随着春晚主持人一声令下,全国观众会同一时间涌入活动页面,给接口带来超高的流量压力。下面将从流量削峰、降级处理两个个方面介绍前端如何与后台合作应对这类高并发场景。
流量削峰
在高并发场景下,流量削峰有助于系统平稳度过流量高峰。本次活动中,初始化接口和击鼓抽奖接口流量最大,因此我们主要针对这两个接口进行削峰。
1.初始化接口:在页面加载之前,即资源位入口,配置一个“加载中”页面链接。这个页面随机加载1-3秒后跳转到活动页面。当流量超过系统承载能力时,开启灰度开关,部分用户进入此页面,然后等待几秒后进入活动页面。
2.击鼓抽奖接口:本次活动的核心玩法接口。如果仅仅是简单地随机延时几秒请求,会极大地影响用户体验。我们采用更精细化的处理方式。已知击鼓交互在用户敲击满次数或倒计时结束时触发抽奖接口,因此,随机设定敲鼓次数,将原本集中在1-2秒内的请求打散至10秒区间,用户几乎无感知。
即时状态的本地存储
针对用户优惠券领取状态的保存问题,权衡了多种因素,如活动规模、服务器端压力和活动持续时长等。最终,我们决定采用前端本地缓存来保存用户领券状态,从而提升性能并优化用户体验。
我们对比了前端常用的本地存储机制,如
cookie
、
localStorage
和
sessionStorage
。然而,这些机制各有优缺点:
cookie
存储空间较小(4K),且在与服务端通信时会占用请求头部,可能导致请求头过大,超过服务端设置的最大值,进而引发报错,并增加不必要的网络消耗。
sessionStorage
生命周期较短,仅适用于会话期间。
综合考虑后,我们选择了
localStorage
作为优化方案。它具有较长的生命周期和较大的储存空间(2.5M-4M),能满足业务需求。采用
localStorage
缓存数据,不仅可以简化调用链路、降低风险和节约成本,还能直接从本地读取券的领取状态,避免网络延迟导致的响应时间过长,提升用户体验。
工程化
为了使业务开发人员能更专注于自身业务开发,我们将手机兼容性、设备分级、环境判断、自动合成雪碧图、自动图片压缩、自动上传云存储、合并代码文件等通用解决方案统一纳入工程化层面处理。
通过工程化,可以最大程度的释放生产力和创造力。上述的各种前端各种优化方案,离不开工程化的助力,与此同时保证了在快速开发交付的效率和稳定性。
提供拟真的
MOCK
环境
我们搭建了一个拟真的
MOCK
环境,以在短时间内模拟所需场景,确保在任意场景下都能提供友好交互。该环境1:1还原了服务端的
MOCK
环境,能快速模拟正常数据,同时还能模拟请求超时、HTTP状态码异常、数据结构异常、非常规业务异常码等场景。在ajax模块中,我们采用透明转发方式,降低业务开发同学创作mock数据的成本,避免mock数据进入生产环境。如图所示,
MOCK
开发环境与联调开发环境对比,可以看出mock环境对业务开发来说是透明且无副作用的,同时又能快速
MOCK
数据。

编写稳定高效的发布脚本
春晚参与用户的设备种类繁多,我们需在不同设备上实现极致体验,同时减轻
CDN
过高
QPS
的压力。为此,我们与客户端团队联合,根据不同设备的不同版本,提供了内置包、离线包和线上
CDN
包等多套环境。结合多轮内测和公测,在短短27天内,需部署10多套环境。线上环境部署错综复杂,还包括资源收集和大小计算等工作。若采用人工方式,极易出现误操作,带来不良后果。幸运的是,项目初期便引入了环境变量,通过环境变量解决不同环境间的差异。此外,在编译前后加入了一系列脚本,替代人工拷贝上传、资源收集、大小计算等操作,避免人工操作失误,提高稳定性,确保每个环境稳定部署。

工程化的目标,始终是提升开发效率,降低开发难度,分离关注点,让业务研发同学更专注于自身业务的开发。
容灾
作为一档全球直播节目,现场不免会出现各种状况,需要做好各种紧急预案。降级处理分为主动降级和被动降级两类:
1.
主动降级:各个资源位和交互按钮上添加降级开关,上游接口或下游页面出现紧急情况时,可通过配置CMS快速打开降级开关。
2.被动降级:通过不同样式和文案提示区分各类接口异常码及系统环境,快速定位问题原因。这样一来,客服同学可以第一时间安抚客户,并提供相应处理方案。
总结
2022年央视春晚互动项目是一次大规模、高并发的挑战,前端团队通过静态资源优化、缓存、容错和工程化等方面的努力和创新,确保了系统的稳定性和性能,为用户提供了一个稳定流畅的互动体验。在静态资源优化方面,团队通过首屏资源拆分、帧动画方案替代3D模型、动态雪碧图和
WebP
格式优化等技术手段,显著降低了资源消耗和请求次数。在降低服务器成本及风险方面,选择
localStorage
作为非常规优化方案,提升用户体验。在容错方面,流量削峰和降级处理,确保系统稳定运行。在工程化方面,统一处理通用解决方案、提供拟真的
MOCK
环境和编写稳定高效的发布脚本,降低开发难度,确保每个环境稳定部署。通过这些技术手段和创新,前端团队成功应对了春晚互动项目带来的技术难题,为用户提供了一个稳定流畅的互动体验。
作者:京东零售 赵越
来源:京东云开发者社区 转载请注明来源
Docker安装
docker 官方文档:
https://docs.docker.com/get-docker/
docker 中文文档:
https://www.kancloud.cn/jingyucloud/docker/216412
搭建私有仓库参考:
https://zhuanlan.zhihu.com/p/511286328
开放远程API接口参考:
https://blog.csdn.net/ic_esnow/article/details/113284475
一、简介
容器概念
容器是一种轻量级、可移植、自包含的软件运行环境。它允许开发者将一个应用及其全部运行环境——包括代码、运行时、系统工具、系统库以及设置——全部封装在一起。这种封装确保了应用在任何环境中都能以相同的方式运行,无论是在开发人员的个人电脑上、测试环境中、还是在生产环境的服务器或云平台上。
核心特性
- 隔离性
:容器通过操作系统级别的虚拟化实现了进程和资源的隔离。每个容器都运行在一个独立的环境中,并且容器与容器之间、容器与宿主机之间都是相互隔离的。 - 轻量级
:与传统的虚拟机相比,容器不需要额外加载一个完整的操作系统内核,只需利用宿主机的内核即可运行。这大大减少了资源消耗和启动时间。 - 可移植性
:由于容器内包含了应用运行所需的一切,因此可以确保应用在不同的计算环境中运行时的一致性和兼容性。 - 微服务架构的支持
:容器非常适合微服务架构,因为它们允许每个服务单独容器化,这样可以独立地开发和扩展服务。
容器与虚拟机的区别
- 启动时间
:容器只需几秒钟即可启动,而虚拟机可能需要几分钟。 - 性能
:容器直接运行在宿主机的操作系统之上,几乎没有额外开销,因此性能接近物理机。虚拟机则需要额外的资源来运行完整的操作系统。 - 资源占用
:容器共享宿主机的操作系统内核,而虚拟机则需要为每个虚拟机实例运行一个完整的操作系统,因此容器更加节省资源。 - 隔离性
:虚拟机提供了更强的隔离性,因为它们彼此之间以及与宿主机之间是完全独立的。容器虽然也提供了隔离性,但因为它们共享宿主机的内核,所以相对较弱。
容器技术的出现和普及改变了软件开发、部署和运维的方式,使得应用的交付更加快速、高效。Docker 是目前最流行的容器平台之一,但也有其他技术如 Podman、containerd 等。
什么是Docker
Docker 是一个开源的应用容器引擎,允许开发者打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(默认情况下),更重要的是容器性能开销极低。
核心概念
- 镜像(Image)
:Docker 镜像是用于创建 Docker 容器的模板,可以将其理解为一个只读的文件系统。它提供了容器运行时所需的程序、库、资源、配置等文件,但不包含任何动态数据。用户可以基于镜像启动新的容器实例。 - 容器(Container)
:容器是镜像的运行实例。它可以被启动、开始、停止、删除,每个容器都是相互隔离、保证安全的平台。容器的核心是隔离性和临时性,这意味着当容器被删除时,容器内的更改和数据也会随之消失。 - 仓库(Repository)
:Docker 仓库是集中存放镜像文件的场所。最著名的公共仓库是 Docker Hub,其中包含了数量庞大的镜像供用户下载。除了 Docker Hub,用户还可以创建私有仓库来存放自己的镜像。
工作原理
Docker 使用客户端-服务器(C/S)架构模式。Docker 客户端与 Docker 服务器(Docker Daemon)通信,Docker Daemon 负责构建、运行和分发 Docker 容器。Docker 客户端和服务器可以运行在同一个系统上,也可以通过网络从远程客户端与 Docker Daemon 通信。
主要特点
- 快速、一致地交付应用
:Docker 可以快速构建、测试并部署应用,并确保应用在任何环境中都能以相同的方式运行。 - 响应式扩展与缩减
:根据业务需求,容易地在服务中增加或删除容器来扩展或缩减服务。 - 运行任何地方
:Docker 容器可以在开发者的本地笔记本电脑、物理或虚拟机、数据中心、云服务等任何地方运行。 - 隔离
:Docker 确保每个容器都在自己的隔离环境中运行,使得应用更加安全。 - 轻量级
:Docker 利用 Linux 容器技术,比传统的虚拟化技术更加轻量,提高了系统利用率和性能。
Docker 的出现极大地简化了部署应用的流程,让开发、测试、生产环境之间的切换变得更加容易和快捷,对现代软件开发和运维方式产生了深远影响。
二、Window安装
在Win10及以上系统安装Docker Desktop使用Docker
确保系统安装 Hyper-V 参考文章(
https://www.runoob.com/docker/windows-docker-install.html)
1、在
Docker Desktop下载
网页上点击Docker Desktop for Windows下载或者直接去
官网下载安装包
2、安装包下载好后,直接双击Docker Desktop Installer.exe文件进行安装,把接下来的页面所有选项全部选中
参考:
https://blog.csdn.net/qq_39611230/article/details/108641842
3、安装完成后,打开Docker Desktop应用,在setting页面选择 Docker Engine
内容如下
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"features": {
"buildkit": true
},
"registry-mirrors": [
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"
],
"insecure-registries": [
"192.168.1.153:5000"
]
}
//registry-mirrors 配置源,这里使用的是163的源
//insecure-registries 私有仓库地址
参考:
https://docs.docker.com/desktop/install/windows-install/
https://www.runoob.com/docker/windows-docker-install.html
https://zhuanlan.zhihu.com/p/191588757
https://blog.csdn.net/BThinker/article/details/123358697
三、CentOS安装
1、选择要安装的平台
Docker要求CentOS系统的内核版本高于3.10
#通过 uname -r 命令查看你当前的内核版本
uname -r
2、选择要安装的操作系统
3、首先卸载已安装的Docker
使用
Root权限
登录 Centos。确保yum包更新到最新。
sudo yum update
在尝试安装新版本之前,请卸载任何此类旧版本以及关联的依赖项,操作系统没有安装过Docker就跳过。
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
可能会报告您没有安装这些软件包,卸载 Docker 时,存储在
/var/lib/docker/
其中的映像、容器、卷和网络不会自动删除。
1、您可以设置 Docker 的存储库并从中安装,以便于安装和升级任务。这是推荐的方法。
2、您可以下载 RPM 软件包,手动安装它,并完全手动管理升级。这在无法访问 Internet 的气隙系统上安装 Docker 等情况下很有用。
3、在测试和开发环境中,您可以使用自动化便利脚本来安装 Docker。
4、使用rpm存储库安装
在新主机上首次安装 Docker 引擎之前,需要设置 Docker 存储库。之后,您可以从存储库安装和更新 Docker。
4.1、设置仓库
安装
yum-utils
软件包(提供
yum-config-manager
实用程序)并设置存储库。
## 安装Docker所需要的一些工具包
sudo yum install -y yum-utils
## 建立Docker仓库 (映射仓库地址)
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
4.2、安装 Docker Engine
若要安装最新版本,请运行:
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
如果系统提示您接受 GPG 密钥,请验证指纹是否匹配,如果匹配
060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35
,请接受它。
此命令将安装 Docker,但不会启动 Docker。它还会创建一个
docker
组,但是,默认情况下,它不会向该组添加任何用户。
4.3、启动 Docker
sudo systemctl start docker
4.4、通过运行
hello-world
映像来验证 Docker 引擎安装是否成功。
sudo docker run hello-world
5、软件包安装
如果无法使用 Docker
rpm
的存储库安装 Docker 引擎,可以下载
.rpm
版本的文件并手动安装。每次要升级 Docker 引擎时,都需要下载一个新文件。
前往
https://download.docker.com/linux/centos/
并选择您的 CentOS 版本。然后浏览并
x86_64/stable/Packages/
下载
.rpm
要安装的 Docker 版本的文件。
5.1、安装 Docker 引擎,将以下路径更改为下载 Docker 包的路径。
sudo yum install /path/to/package.rpm
Docker 已安装但未启动。组已创建,但未将用户添加到
docker
组。
5.2、启动 Docker。
sudo systemctl start docker
5.3、通过运行
hello-world
映像来验证 Docker 引擎安装是否成功。
sudo docker run hello-world
6、升级Docker 引擎
若要升级 Docker 引擎,请下载较新的包文件并重复安装过程,使用
yum -y upgrade
而不是
yum -y install
,并指向新文件。
使用便捷脚本安装
Docker 在
https://get.docker.com/
提供了一个方便的脚本,用于以非交互方式将 Docker 安装到开发环境中。不建议将方便脚本用于生产环境,但它可用于创建根据需求量身定制的预配脚本。另请参阅使用存储库安装步骤,了解使用软件包存储库进行安装的安装步骤。该脚本的源代码是开源的,您可以在 GitHub 上的
docker-install
存储库中找到它。
在本地运行脚本之前,请始终检查从 Internet 下载的脚本。在安装之前,请熟悉便利脚本的潜在风险和限制:
- 脚本需要
root
或
sudo
权限才能运行。 - 该脚本尝试检测您的 Linux 发行版和版本,并为您配置包管理系统。
- 该脚本不允许您自定义大多数安装参数。
- 该脚本在不要求确认的情况下安装依赖项和建议。这可能会安装大量软件包,具体取决于主机的当前配置。
- 默认情况下,该脚本会安装 Docker、containerd 和 runc 的最新稳定版本。使用此脚本预配计算机时,这可能会导致 Docker 意外的主要版本升级。在部署到生产系统之前,请始终在测试环境中测试升级。
- 该脚本并非旨在升级现有 Docker 安装。使用脚本更新现有安装时,依赖项可能不会更新到预期的版本,从而导致版本过时。
提示:运行前预览脚本步骤
您可以使用以下
--dry-run
选项运行脚本,以了解脚本在调用时将运行哪些步骤:$ curl -fsSL https://get.docker.com -o get-docker.sh $ sudo sh ./get-docker.sh --dry-run
此示例从
https://get.docker.com/
下载脚本并运行它以在 Linux 上安装 Docker 的最新稳定版本:
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
Executing docker install script, commit: 7cae5f8b0decc17d6571f9f52eb840fbc13b2737
<...>
现在,您已成功安装并启动了 Docker 引擎。该
docker
服务在基于 Debian 的发行版上自动启动。在基于发行版(如 CentOS、Fedora、RHEL 或 SLES)上
RPM
,您需要使用相应的
systemctl
or
service
命令手动启动它。如消息所示,默认情况下,非 root 用户无法运行 Docker 命令。
以非特权用户身份使用 Docker,还是以无根模式安装?
安装脚本需要
root
或
sudo
具有权限才能安装和使用 Docker。如果要授予非 root 用户对 Docker 的访问权限,请参阅 Linux 的安装后步骤。您还可以在没有权限的情况下
root
安装 Docker,或配置为在无根模式下运行。有关在无根模式下运行 Docker 的说明,请参阅
以非 root 用户身份运行 Docker 守护程序
。
安装预发行版
Docker 还提供了一个方便的
https://test.docker.com/
脚本,用于在 Linux 上安装 Docker 的预发行版。此脚本等同于 中的
get.docker.com
脚本,但将包管理器配置为使用 Docker 包存储库的测试通道。测试通道包括 Docker 的稳定版本和预发布版本(测试版、候选版本)。使用此脚本可以抢先体验新版本,并在它们作为稳定版本发布之前在测试环境中对其进行评估。
若要从测试通道在 Linux 上安装最新版本的 Docker,请运行:
$ curl -fsSL https://test.docker.com -o test-docker.sh
$ sudo sh test-docker.sh
使用便捷脚本后升级 Docker
如果使用方便脚本安装了 Docker,则应直接使用包管理器升级 Docker。重新运行便利脚本没有任何好处。如果它尝试重新安装主机上已存在的存储库,则重新运行它可能会导致问题。
卸载 Docker 引擎
卸载 Docker 引擎、CLI、containerd 和 Docker Compose 包:
$ sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
主机上的映像、容器、卷或自定义配置文件不会自动删除。要删除所有映像、容器和卷,请执行以下操作:
$ sudo rm -rf /var/lib/docker $ sudo rm -rf /var/lib/containerd
您必须手动删除任何已编辑的配置文件。
参考:
https://docs.docker.com/engine/install/
https://docs.docker.com/engine/install/centos/
索引构建磁盘IO太高,巧用tmpfs让内存来帮忙
在文本索引构建这种需要大量占用磁盘IO的任务,如果正巧你的内存还有点余粮,是否可以先索引存储到内存,然后再顺序写入到磁盘呢?,需要大量占用磁盘IO,如果正巧你的内存还有点余粮,是否可以先索引存储到内存,然后再顺序写入到磁盘呢?
将Linux的内存变为磁盘,可以通过tmpfs文件系统实现。
tmpfs介绍
以下是ChatGPT的介绍:
tmpfs文件系统是Linux内核自带的一种内存文件系统,它可以将内存空间作为虚拟磁盘使用。使用tmpfs文件系统将内存变为磁盘,可以通过以下步骤实现:
创建一个tmpfs文件系统:
sudo mkfs.tmpfs -m 100M -o size=100M /dev/shm/mydisk
这条命令将在/dev/shm/mydisk设备上创建一个大小为100MB的tmpfs文件系统。
挂载tmpfs文件系统:
sudo mount -t tmpfs /dev/shm/mydisk /mnt/mydisk
这条命令将/dev/shm/mydisk设备上的tmpfs文件系统挂载到/mnt/mydisk目录。
此时,/mnt/mydisk目录就可以像普通磁盘一样使用了。可以将文件写入到该目录,也可以从该目录读取文件。
docker使用tmpfs
在docker容器环境如何使用呢?是否需要在container里去挂载?
其实在docker里,tmpfs是默认支持的,可以通过 在启动命令里,加上类似
--mount type=tmpfs,destination=/mnt/tmpfs,tmpfs-mode=1770,tmpfs-size=12G
来实现挂载。
注意tmpfs挂载的,是container容器独享的,不能和其他容器共享,有效期就是容器的生命周期。
我们来实验:
[root@dev ~]#docker run -it --rm --mount type=tmpfs,destination=/mnt/tmpfs,tmpfs-mode=1770,tmpfs-size=12G gcc:12 bash
root@87b86fe9a4d0:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 182G 160G 13G 93% /
tmpfs 64M 0 64M 0% /dev
tmpfs 63G 0 63G 0% /sys/fs/cgroup
shm 64M 0 64M 0% /dev/shm
/dev/sda2 182G 160G 13G 93% /etc/hosts
tmpfs 12G 0 12G 0% /mnt/tmpfs
tmpfs 63G 0 63G 0% /proc/acpi
tmpfs 63G 0 63G 0% /proc/scsi
tmpfs 63G 0 63G 0% /sys/firmware
- 首先通过
docker run
挂载,制定大小12G - 在容器里,通过
df -h
可以看到挂载的
/mnt/tmpfs
类型为
tmpfs
,大小12G
K8S 使用tmpfs
在K8S里,tmpfs对应的是
emptyDir
Volume,将
emptyDir.medium
指定为
Memory
,可以让 Kubernetes 挂载 tmpfs(基于 RAM 的文件系统)。
emptyDir
的一些用途:
- 缓存空间,例如基于磁盘的归并排序。
- 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
- 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
emptyDir 配置示例
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 500Mi
medium: Memory
Spark on k8s
对于运行在K8S上的spark,也可以通过volumes参数来指定使用tmpfs。
spark提供下面几种类型的volume
- hostPath
: mounts a file or directory from the host node’s filesystem into a pod. - emptyDir
: an initially empty volume created when a pod is assigned to a node. - nfs
: mounts an existing NFS(Network File System) into a pod. - persistentVolumeClaim
: mounts a
PersistentVolume
into a pod.
可以通过下面的参数来配置Volume:
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.path=<mount path>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.readOnly=<true|false>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.subPath=<mount subPath>
对于VolumeType的配置,可以通过下面的形式来做:
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].options.[OptionName]=<value>
因此,spark on k8s支持
tmpfs
, 假设
VolumeName
为
spark-empty-dir
, 挂载路径
/mnt/cache-index
, 大小限制
12G
,那么提供任务时可以指定参数:
--conf spark.kubernetes.executor.volumes.emptyDir.spark-empty-dir.mount.path=/mnt/cache-index
--conf spark.kubernetes.executor.volumes.emptyDir.spark-empty-dir.options.medium=Memory
--conf spark.kubernetes.executor.volumes.emptyDir.spark-empty-dir.options.sizeLimit=12G
优化后,文本索引构建时IO占用:
下载、安装Git并拷贝GitHub项目到本地的流程
本文介绍分布式开源版本控制系统
Git
的下载、安装,并基于
Git
实现克隆
GitHub
中项目代码的方法。
Git
是一款开源软件,因此我们直接在
Git
的
官方下载地址
下载最新版本的
Git
即可。其中,在下图所示的位置选择适合我们操作系统的
Git
版本。
随后,选择下图红色方框内的内容,下载最新版的
Git
。
下载完毕后,双击得到的
.exe
文件,进入安装流程,如下图所示;接下来,我们仅对安装流程中比较重要的配置选项进行介绍,对于没有出现的窗口,大家直接选择默认的配置选项即可。
首先,配置好
Git
的安装路径。
其次,在如下所示的窗口中,建议将下图中红色方框内的选项勾选中,使得软件安装完毕后在桌面创建快捷方式;其余的勾选框,大家就使用默认的勾选状态即可。
随后,在如下所示的窗口中,需要配置
Git
所使用的编译器;这里我们就选择默认的选项即可。其实对于一般的用户而言,这里的设置我们应该也用不上。
在如下所示的窗口中,需要配置一个项目的初始分支的名称,这里选择默认选项即可。
在如下所示的窗口中,需要配置
Git
的环境路径选项,建议选择第二项,这样
Git
将自动配置环境路径。
对于其他没有提及的窗口,大家直接选择默认配置即可。随后,即可开始安装。
稍等片刻,
Git
将安装完毕。
随后,我们就可以开始使用
Git
的各项功能了。例如,假设我们需要基于
Git
从
GitHub
中复制
C++
包管理器
vcpkg
的相关代码,就可以在
Windows PowerShell
中,输入以下语句。
git clone https://github.com/microsoft/vcpkg
如下图所示。
其中,如果大家在
Git
使用过程中出现错误代码为
10054
的错误,如下图所示(下图中我将
microsoft
这个单词打错了,大家理解即可),则一般是因为网络出现问题导致的;此时可以重新尝试,如果有代理软件需要关闭代理。
此外,如果我们第一次通过
Git
建立与
GitHub
的连接,还会弹出一个
GitHub
的登录窗口,如下图所示。
如果出现这个提示,我们按照要求登录
GitHub
账号即可;登录完毕,即可开始执行
git
操作。
如上图所示,证明
git
操作已经成功。