8000 科普文:为什么不能在服务器上 npm install ? · Issue #30 · atian25/blog · GitHub
[go: up one dir, main page]

Skip to content

科普文:为什么不能在服务器上 npm install ? #30

Open

Description

@atian25

背景

Node.js 很简单,容易上手。但也因此缺乏不少规范,使用者水平参差不齐。

最近经常看到的一个问题是:很多新手,在部署的时候,是直接在服务器上 npm install ,这是非常不推荐的。

存在的问题

无法确定唯一性

因为安装是有较大的网络耗时的,所以你甚至无法保证集群情况下,两台服务器上npm install 下来的包是一模一样的。

如果某个库刚好更新了,并且它有 BUG,然后你就是百思不得其解:一定概率出某个问题。排查起来简直想死。

当然,很多人为了解决这个问题,就选择「锁版本」这个方案。

鉴于 「锁版本」这个方案属于 「屎色自行车问题」 ,这里不想讨论,我们的观点参见:「知乎专栏 - 死马:为什么我不使用 shrinkwrap(lock)」。

上线耗时久,无法快速回滚

上线后,发现线上故障,要快速回滚止血的时候,就懵逼了:

  1. 要等待依赖安装,万一网络有个抖动啥的,妥妥的 P4 故障变为 P0 故障,年终奖没了。
  2. 万一问题是底层依赖导致的,回滚也没用。
  3. npm cache 解决不了问题,如机器扩容的时候。

推荐方案

development lifecycle

其中,关键点是:在构建期就把依赖打包进去。

优点:

  1. 解压即可立刻启动,无需等待网络耗时。
  2. 能保证肯定是可以运行的,因为此时依赖都是确定好的,且经过 CI 单测保障的。
  3. 可以快速回滚,止血。

缺点:

  1. 包体积大(但其实存储不值钱。。。)

流程图

如何实施

那有同学就要问了:我是小公司,不像你们有这些基建可以服务,怎么办?

其实成本真的很低:

  • 代码仓库 GitLab 自带就有 GitLab-CI 了,你只需要写个配置文件,触发自动构建即可。
  • 然后把构建后的文件,找个地方存储,如 OSS 啥的。
  • 服务器部署的话,有运维发布系统最好,没有的话,自己写个 shell 把 OSS 文件下载解压。
  • 当然,很多云服务都支持 Docker 镜像了,那就更简单了。

广告区

Activity

  1. atian25 commented on Jul 7, 2018

    @atian25
    OwnerAuthor

    最后那张图,是在语雀上直接用 PlantUML 画的。

    PlantUML 的优势是:

    • 类 Markdown 那样让你自然的画图
    • 可多人协作,可版本跟踪

    一般来说,你不需要太关注语法和布局,很自然的画即可。

    当然,它提供了不少特性,可以让你画的更好看点。

    如下就是那张图的源码:

    @startuml
    
    autonumber
    hide footbox
    title **Node 应用研发部署流程**
    
    actor "开发者" as user
    participant "代码仓库(GitLab)" as gitlab
    participant "持续集成系统" as ci
    participant "运维发布系统" as sys #orange
    participant "服务器" as server
    
    == 研发流程 ==
    user -> gitlab: 提交代码
    activate user
    deactivate user
    activate gitlab
    gitlab -> ci: 单元测试
    deactivate gitlab
    activate ci
    note right of ci: tar 或 docker
    ci -> ci: 打包
    ci -> sys: 推送
    note right of sys: 存储到 oss
    activate sys #orange
    deactivate ci
    deactivate sys
    
    ...
    
    == 上线/回滚流程 ==
    user -> sys: 选择要上线的版本
    activate sys #orange
    activate user
    deactivate user
    sys -> server: 推送
    activate server
    note right of server: **无需--安装依赖--,快速且确定**
    server -> server: 解压
    server -> server: 启动
    server --> sys
    
    @enduml
    

    看起来好像有点复杂,其实只是因为我有强迫症,喜欢用 activate/deactivate 来改变生命周期。
    可以简化为:

    @startuml
    
    autonumber
    hide footbox
    title **Node 应用研发部署流程**
    
    actor "开发者" as user
    participant "代码仓库(GitLab)" as gitlab
    participant "持续集成系统" as ci
    participant "运维发布系统" as sys #orange
    participant "服务器" as server
    
    activate user
    activate gitlab
    activate ci
    activate sys #orange
    activate server
    
    == 研发流程 ==
    user -> gitlab: 提交代码
    gitlab -> ci: 单元测试
    note right of ci: tar 或 docker
    ci -> ci: 打包
    ci -> sys: 推送
    note right of sys: 存储到 oss
    ...
    
    == 上线/回滚流程 ==
    
    user -> sys: 选择要上线的版本
    sys -> server: 推送
    note right of server: **无需--安装依赖--,快速且确定**
    server -> server: 解压
    server -> server: 启动
    server --> sys
    
    @enduml
    

    image

  2. changed the title [-]为什么不能在服务器上 npm install?[/-] [+]科普文:为什么不能在服务器上 npm install ?[/+] on Jul 8, 2018
  3. IEfucker commented on Jul 27, 2018

    @IEfucker

    具体操作没看懂,是说把依赖包也git提交吗,回滚的版本也是通过git控制?

  4. atian25 commented on Jul 27, 2018

    @atian25
    OwnerAuthor

    @IEfucker 跟 git 没啥关系,最后那张图不是画的很清楚了么,在 CI 上打包,推送到 oss 或 dockerlab,然后发布系统这边记录对应的地址即可。

  5. YardWill commented on Nov 8, 2018

    @YardWill

    其实docker是一个更好的解决方案,一旦打包完之后就可以直接push上去,服务器只需要pull就好了,还能配合k8s做动态扩容。

  6. atian25 commented on Nov 8, 2018

    @atian25
    OwnerAuthor

    正文一开始就声明了吧,docker 是终极解决方案。本方案是分享给那些没有条件的小团队使用。

  7. Gerhut commented on Dec 18, 2018

    @Gerhut

    跑单元测试时候的依赖版本和推送到发布系统的依赖版本需要保持一致吗?

  8. atian25 commented on Dec 18, 2018

    @atian25
    OwnerAuthor

    跑单元测试时候的依赖版本和推送到发布系统的依赖版本需要保持一致吗?

    必然啊,跑完单元测试后,直接打包推送发布系统了。

    PS:这里会有一个小 GAP 需要权衡,devdep 怎么办,是 prune 了重新 install --prod,还是直接打包。

  9. Gerhut commented on Dec 18, 2018

    @Gerhut

    OK 我把打包错理解成 docker build (install + pack) 了

    对于你的问题,npm prune --production 可解

  10. wotermelon commented on Apr 26, 2021

    @wotermelon

    那你保证发布机器和生产机器系统以及其他因素都一样吗?
    否则怎么保证一些node-gyp rebuild的依赖可以在这些机器上通用?

    问题不在于依赖应不应该在服务器上安装,而在于如何优雅地启动服务,包括健康检查、流量切换

  11. atian25 commented on Apr 26, 2021

    @atian25
    OwnerAuthor

    镜像啊

  12. genffy commented on Nov 10, 2023

    @genffy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0