个推 Node.js 微服务实践:基于容器的一站式命令行工具链

Node.js · jack · Created at · Last by yt5206978 Replied at · 1439 hits
434 1549005614

背景与摘要

由于工程数量的快速增长,个推在实践基于 Node.js 的微服务开发的过程中,遇到了如下问题:

  1. 每次新建项目都需要安装一次依赖,这些依赖之间基本相似却又有微妙的区别;

  2. 每次新建项目都要配置一遍相似的配置(比如 tsconfig、lint 规则等);

  3. 本地 Mac 环境与线上 Docker 内的 Linux 环境不一致(尤其是有 C++ 依赖的情况)。

为了解决上述问题,个推内部开发了一个命令行小工具来标准化项目初始化流程、简化配置甚至是零配置,提供基于 Docker 的一致构建、运行环境。

CLI: init, build, test & pack

新建一个 Node.js 项目的时候,我们一般会:

  1. 安装许多开发依赖:TypeScript、Jest、TSLint、benchmark、typedoc 等;

  2. 配置 tsconfig、lint 规则、.prettierrc 等;

  3. 安装众多项目依赖:koa、lodash、sequelize、ioredis、zipkin、node-fetch 等;

  4. 初始化目录结构;

  5. 配置CI 脚本。

通常,我们会选择复制一个现成的项目进行修改,导致出现众多看似相似却又不完全相同的项目,比如十个项目可能会对应十种配置组合。对于同时跨多个工程的开发人员来说,众多配置组合会增加他们的工作难度。而且,当安全审计发现某些 npm package 出现安全隐患时,开发人员则需要对每个引用这些包的项目逐一检查和修正。

在确定的开发场景下,几乎所有项目的开发依赖都差不多,开发配置也非常相似,因此我们基于 commander.js 写了一个 init 工具,它会开个命令行的向导,自动安装依赖、初始化项目目录结构和配置。从而创建项目,并按照场景将所有配置收缩为特定几种模板,进行统一处理。

随后,我们有了 build、test、pack 命令,托管了 tsconfig、jest 配置、打包配置,自动调用 tsc 编译,构建测试环境,然后调用 Jest 进行测试,进行标准化打包, CI 脚本基本可以简化为几行标准脚本。

CLI: Docker Build

在介绍这个命令前需要先简单了解一下个推的镜像体系:

前面提到我们将大部分依赖封装到了一个 npm 包,这一层封装也反映在个推的 Docker 镜像体系内,可以简单表述为下面的 Dockerfile:

# 公共依赖层的 Dockerfile
FROM node:10
RUN mkdir -p /usr/local/lib/webnode/node_modules \
  && cd /usr/local/lib/webnode \
  && npm install webnode
ENV NODE_PATH /usr/local/lib/webnode/node_modules
# 项目的 Dockerfile
FROM getui/webnode:1.2.3
COPY package*.json ./
RUN npm install
COPY . .

当把这层依赖直接做进 Docker 镜像时,虽然每个镜像的 SIZE 还是 1G 多,但是每个镜像的 UNIQUE SIZE 都是极小的,仅有数M的差分层。

一个简单的对比,比如有 800M 公共系统依赖 + 每个服务平均 200M 的 npm 依赖 + 1M 的服务代码,那么由于原先每个服务都会 npm install 大量重复依赖,20 个服务,就会有 800M + 200M * 20 + 1M * 20 = 4.82G 的总 UNIQUE SIZE。而采用依赖分层共享,则仅有 800M + 200M + 1M * 20 = 1.02G 的总 UNIQUE SIZE。在考虑应用的多版本之后,依赖分层共享带来在存储上的优势会更加明显。

我们以一定的依赖锁定周期和控制为代价,换取了:

  • 减少依赖组合、依赖版本组合的可能性,开发者选择包的简化、初始化项目的简化;审计简化、安全更新简化 。
  • CI 显著提速,节省等待时间。
  • 传输和存储的压力减少许多。
  • 公共依赖被多个项目使用,得到了更加充分的测试。

webnode docker build 命令可以帮助简化 Docker image 的构建过程,它内置了一个 Dockerfile 和dockerignore,该命令运行时,会基于这两个文件和当前的 Context,自动构建docker 镜像。其中 Dockerfile 内含一些优化和我们的最佳实践,开发人员只需要专注 Node.js 的项目的开发,这个命令则可以负责配置文件权限等操作以及生成标准化的、优化的 Docker 镜像。

其设计目标是:

  • 快:合理的依赖分层,最大程度应用 Docker 缓存机制,通过 .dockerignore 裁剪不必要的 Context,因此可以实现飞快的构建速度 。
  • 小:依据变更频度做 Docker 分层设计、应用 multi-stage build,尽最大可能缩小一个镜像的 UNIQUE SIZE 。
  • 可重现:同样的内容总是构建出相同的结果。

以 node_modules 依赖优化为例,下面两种 Dockerfile 其实会有很大的区别:

FROM getui/webnode:1.2.3
COPY . .
RUN npm install

FROM getui/webnode:1.2.3
COPY package*.json ./
RUN npm install
COPY . .

前者,每次 docker build 时,只要项目内任何代码变了,npm install 的缓存都会失效,需要重新安装,而后者仅当 package*.json 发生改变之时才会触发重新 npm install。另外,我们还会对 package.json 进行预编译,仅保留依赖相关的字段,避免出现修改 package.json 的版本号就重新 npm install的情况。

webnode docker build 不仅可以帮助开发者进行统一化的镜像构建、统一实践最佳优化,节约资源,还能避免所有开发人员都需要接触优化细节,省时省力。

CLI: Webnode Docker Start

在本地调试开发的过程中,我们遇到了一些环境差异引起的问题:

  • 生产环境与本地开发环境 Node.js 版本不一致。
  • 一些含有 C++ 代码的 npm 依赖运行的跨平台问题 。
  • 文件权限配置、系统目录结构与线上运行环境不完全一致 。
  • 启动初始化流程不一致(比如配置预拉取)。
  • 开发本地常常缺少一些二进制工具或版本不一致(比如 consul-template、nc 等)。 与本地直接启动 Node.js 程序有所不同,这个命令会优先基于当前项目利用上面的 webnode docker build 命令构建 Docker 镜像,然后启动镜像。

Docker 可以帮助消解环境差异:

  • 便捷地携带与生产环境一致的Node.js 版本以及其他二进制依赖。
  • 一致的初始化流程。
  • 轻松运行含有 C++ 的 npm 依赖。
  • 文件权限、目录结构与线上运行环境一致。 容器化的Node.js调试方法有些许变化,需要暴露Node.js的Inspector端口,然后配一下Visual Studio Code的localRoot和remoteRoot:
WEBNODE_HOST=${WEBNODE_HOST:-127.0.0.1}
WEBNODE_PORT=${WEBNODE_PORT:-3000}
DOCKER_RUN_OPTIONS="$DOCKER_RUN_OPTIONS \ 
   -it \
   --rm \
   --network=\"getui-dev\"
   -p $WEBNODE_HOST:$WEBNODE_PORT:3000 \
   -p 127.0.0.1:9229:9229 \
   -e NODE_FLAGS=--inspect=0.0.0.0:9229 \
   --name $CONTAINER"
docker run \
   $DOCKER_RUN_OPTIONS \
   $DOCKER_IMAGE_TAG
{
   "version": "0.2.0",
   "configurations": [
       {
           "type": "node",
           "request": "attach",
           "name": "Attach Local WebNode",
           "address": "127.0.0.1",
           "port": 9229,
           "restart": true,
           "protocol": "inspector",
           "localRoot": "${workspaceFolder}",
           "remoteRoot": "YOUR_REMOTE_ROOT",
           "sourceMaps": true
       },
   ]
}

基于容器开发 CLI 工具

基于容器的开发可以带来诸多好处。一是便于分发,基于 Docker 的 Tag,开发者可以很方便地做基于小版本、大版本、分支的分发,可以像 nvm 一样去切换版本。

二是CLI 脚本不用处处考虑跨平台兼容的问题,比如:

  • sed 在 Linux 和 Mac 下工作行为不一致的问题之类的。
  • 有的环境有 Python 3 有的环境只有 Python 2 所有的依赖通过容器带进来,简洁而高效。

在基于 Docker 的工具开发的过程中,我们也遇到一些问题:

一是容器内外 UID/GID 不一致,如果是以非 ROOT 用户运行 docker run,会导致容器内程序在挂载的目录产生的文件权限与当前用户不一致。

Docker for Mac对于文件权限有一些特别的行为,具体可以参见:https://docs.docker.com/docker-for-mac/osxfs/#ownership

对于 Host 是 Linux 的情况,尤其在 CI 时,需要考虑 UID/GID 的问题。对于这种情况,我们选择覆盖掉了 entrypoint ,然后用 gosu 去做降权来处理。

CLI_EXEC_UID=${CLI_EXEC_UID:-0}
CLI_EXEC_GID=${CLI_EXEC_GID:-0}

exec gosu $CLI_EXEC_UID:$CLI_EXEC_GID env "$@"

其实RedHat 旗下用于设计container runtime 的daemonless (例如 podman),就很适合做CLI工具,可以 rootless 运行,又尊重系统的权限配置。然而其目前尚未成熟,业界采用率也不高,仍需要继续观望。

二是有时候 docker run 速度较慢,个推的解决方案是在首次启动时启动一个 docker run --detach,然后后续的 CLI 执行完全通过 docker exec 来进行,这样避免掉了每次执行命令时启动的开销,速度提升明显。

小结

以上便是个推 Node.js 微服务开发实践中关于 CLI 工具的实践,个推试图标准化、优化项目结构以及镜像构建,减少组合的可能性,有效降低了存储、传输、构建的成本,让开发人员更加省时省力。

后续我们还会继续为大家介绍个推的 Docker 镜像体系设计以及Node.js 微服务开发框架,敬请期待。

参考

https://docs.docker.com/docker-for-mac/osxfs/#ownership

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypoint

https://www.projectatomic.io/blog/2018/02/reintroduction-podman/

https://www.slideshare.net/AkihiroSuda/the-state-of-rootless-containers

https://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html#s-virtual

共收到 8 条回复
1Floor Deleted
2Floor Deleted
3Floor Deleted
4Floor Deleted
5Floor Deleted
96
mm685265 · #6 ·

臺灣找小姐+賴:211861 大奶大粉嫩可看照.洗澡愛愛按摩口交全套服務
好吃的東西當然要一起分享~ 小弟昨天趁休假找茶姊約了個正妹 果然幫我安排的素質很讚 妹妹叫童童 目前還是個大學生 22歲 身材臉蛋都是我的菜 身高160 甜美可愛 美腿哦 罩杯Dcup 真材實料 吸起來彈性十足 妹妹雖然年紀小 但是性欲很強 喜歡在床上纏著我的腰扭屁股 真的是視覺上肉體上的100分滿足!!全程真的很主動 很會挑逗 皮膚也很棒很白嫩 全身鮑魚都可以隨意摸哦 全身都很敏感 妹妹也很緊 還會夾我的小弟 插起來水水很多 很有感覺 超級讚!!! 真的是個很淫蕩的小女生 讓你有回味無窮的感覺 喜歡的可以嘗試看看 加賴:211861 找童童可看照片 她家還要其他的姊妹 類型很多 加賴說是阿傑介紹 有好康喔!!!

96
ll211861 · #7 ·

@.全套服務(特別服務可喬)
@.看照約妹~自己看到妹妹滿意現金消費維護客人消費權利~
台灣外送茶可可外送茶【賴211861】【賴211861】專營臺灣本土妹 #情愛全台灣外送茶看照約妹叫小姐 #台灣外送茶 全省外送茶外約援交茶訊魚訊匯總 line茶訊-台灣最大的茶訊、魚訊、外送茶外約網 台灣外送茶價位怎麼算?台灣找小姐上門服務看照約妹會遇雷嗎 台灣找小姐價位多少?看照約妹之台灣酒店找女人上門服務外送茶 援交、魚訊、茶訊、外送茶【賴211861】【賴211861】按摩網站導航 什麼是外送茶- 2020台灣外送茶小貼士 感?茶友的外送茶攻略投稿 - 悅人外送茶 台北外送茶– 茶莊外送茶全套外約叫小姐台灣網友最推薦 外送茶|台北曖昧外送茶即時外約 【賴211861】【賴211861】
台北外送茶彙整- 十八摸外約茶莊-全套-喝茶 【台北推薦】評價最好的5家外送茶!茶莊、價格、外約、到府服務 對味外送茶 讓你有戀愛感覺 台中外約- 叫小姐、外送茶迅速又安全,中部打炮首選- 天使心外約 維珍妮台中茶莊,台中叫小姐及台中外約! - COCO4.5K外送茶 台中外送茶彙整- 十八摸外約茶莊-全套-喝茶 台中女生名單– 糖果外送茶【看照約妹】 台中外送茶 - 激情娛樂外送茶莊 台中外送茶 台中外約學生妹台中一夜情 高雄24小時外約彙整- 十八摸外約茶莊-全套-喝茶 高雄外送茶有著2020茶莊界最好的美眉! 想在高雄叫小姐嗎 #高雄外送茶#高雄看照?妹#高雄叫小姐 高雄外送茶- 最夯E杯大奶妹,擁有傲人的上圍,讓你體驗波濤洶湧 老王-吃魚喝茶術語大全教學 所謂的喝茶就是援交或性交易【賴211861】【賴211861】小資族喝茶吃魚如何少花冤枉錢 萬維論壇 台灣喝茶吃魚可馨蘿莉幼齒學生妹甜美可愛清純粉 [討論] 關於吃魚喝茶心得分享的人- 看板sex - PTT網頁版 台灣喝茶吃魚可馨蘿莉幼齒學生妹甜美可愛清純粉 [討論] 關於吃魚喝茶心得分享的人- 看板sex - PTT網頁版 大台灣出差旅遊找小姐喝茶吃魚喝茶吃魚找小妹貼心 中文色情??,成人??,自拍,偷拍,成人??翻?? 情色網站大全- 成人網站- 色情網 成人貼圖區 - 一世發論壇 全球十大熱門成人網站排名【211861】【賴211861】線上直播網紅模式將成主流 台灣論壇,伊莉論壇區,維克斯論壇,論壇成人版,微風論壇--奇雅網 成人園地 SOGO論壇 夜遊討論- 伊莉討論區 水蜜桃外送茶拉莉塔外送茶海盜外送茶佳佳外送茶妮娜外送茶志玲外送茶小妖精外送茶小騷騷外送茶#台北夜遊論壇 夜遊討論~ 茶魚飯後閒聊版-魚訊交流歐洲論壇神奇論壇東歐個工 小司機帶路西斯板Dcard 夜遊論壇 - 新竹找茶,新竹找魚茶, 桃園中壢OL兼職, LINE 【心得】 夜遊論壇,按摩論壇【休閒娛樂】 魚訊與個工評價討論-歡樂論壇 夜遊討論區-貓都論壇 傑克論壇按摩舒壓理容 武士成人娛樂論壇娛樂網男人碼頭/夜遊討論一世一夜 外約學生妹約茶高檔正妹麻豆藝人小模空姐援交妹學生處女台灣蘿莉送茶吃魚喝茶人妻女優泰洗處女敢玩3P雙飛無套全場3K起【有圖】【賴211861】【賴211861】 #高雄外送茶,#高雄約炮,#高雄外約,#高雄吃魚喝茶,#高雄找小姐,#高雄全套,#高雄茶莊,#高雄茶訊【賴211861】【賴211861】 #高雄約炮神器,#高雄一夜情,#高雄炮友,#高雄買春,#高雄叫雞,#高雄嫖妓,台中外送茶 台中學生 台中一夜情 台中找小姐 台中全套茶旅館愛愛 台中單親媽媽 #高雄找炮友#高雄外送茶 #高雄外送茶,#高雄約炮,#高雄外約 #台北外約 #台北外送茶 #台北買春 #台北叫小姐 #台北叫全套 #台北按摩 #台北半套 #台北找援交妹 #台北茶莊 #台北上門按摩 #台北找茶 #台北外約小姐 #台北找一夜情 #台北外約 #台北外送茶 #台北買春 #台北叫小姐 #台北叫全套 #台北按摩 #台北外約 #台北外送茶 #台北買春 #台北叫小姐 #台北叫全套 #台北按摩約炮 #台北找援交妹 #台北茶莊 #台北上門按摩 #台北找茶 #台北外約小姐【賴211861】【賴211861】 #台北找一夜情 #台北外約 #台北外送茶 #台北買春 #台北叫小姐 #台北叫全套 #台北按摩 #台北半套 #台北外約 #台北外送茶 #台北買春 #台北叫小姐 #台北叫全套 #台北按摩 #台北找援交妹 #台北茶莊 #台北上門按摩 #台北找茶 #台北外約小姐 #台北找一夜情 #台北外約 #台北外送茶 #台北買春 #台北叫小姐 #台北叫全套 #台北按摩 外出茶妹臺北買春優質茶莊台灣蘿莉送茶臺灣嫖妓兼職外約臺北喝茶臺中喝茶高雄喝茶【賴211861】【賴211861】外送茶-叫小姐-外約-全套外送服

96
yt5206978 · #8 ·

+賴:5206978 可看照片 洗澡愛愛按摩口交全套服務 狂插 耐幹 奶泡
聽魚友介紹說她超讚 馬上衝來試一下 見面發現本人比照片好看很多啊! 【超驚喜 XD】 人很熱情很會聊天不會冷場 聊天聊到一半 妹子就自己坐到我身上撒嬌要親親 親到受不了 抱著她衝近了浴室洗澡 互相洗右手摟著我脖子 左手撫摸我下面 妹子慢慢從嘴巴親到脖子在慢慢的跪在地上幫我吹 邊吹邊看著我 這感覺真不錯 超會吹 差點就繳械 還好小弟忍住了 把妹子拉了起來 讓她扶著墻 從後面衝刺 幹到妹子 一直喊不要了 受不了 直到第一發結束 我們一起洗澡去了 床上和她一起做前戲 問她可不可以69 妹子同意了 就互相口 鮑魚很有感覺 粉粉的穴穴 不會像之前約的魚下面超黑 xd 妹子被口到受不了一直扭動著腰 流了很多愛液沒幾分鐘自己就顫抖了起來 說自己要去了 太舒服了~ 呻吟也叫的超淫蕩 ~ 等結束後 妹妹也不會馬上洗澡 還會抱著我躺一會 再拉著我一起去洗澡 超有女友fu ~ 做完評價:妹子很不錯 奶有D奶

服務十分 外貿十分 有女友fu 可69 喜歡上位 超會搖 【推薦出來各位大大要珍惜 妹子是短期兼職 】
密碼:160cm/D/47kg23歲
介紹人:阿傑
LINE : 5206978

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up