当前位置: 首页 > news >正文

依赖项的处理与层的创建与注册

Image

依赖项的处理与层的创建与注册

  • 依赖项的处理与层的创建与注册
    • 新问题
    • 什么是 layer?
    • layer 的创建与注册
      • 与函数同时创建和绑定
      • 单独上传 layer 再绑定函数(推荐)
    • 真正的运行时依赖
      • 注册包的约定
      • 与平台强关联的运行时
        • 1. 云端安装依赖
        • 2. 本地构建 Amazon Linux 2 容器环境
        • 3. 利用 CI 构建并进行上传和部署
    • 镜像部署
    • Next Chapter
    • 完整示例及文章仓库地址

新问题

在一个 nodejs 函数里,我们往往会去安装和使用各种各样的依赖包,来辅助我们项目的开发。

这些依赖以及对应的版本都被注册在了 package.json里 (由 npm init创建)。在安装依赖之后,它们会被存放在当前项目的 node_modules 目录里。而 sls deploy 默认也会把 node_modules 里所有文件,打包压缩后,和代码一起上传到云上。这点很好理解,没有依赖项,函数压根跑不起来。

但是当我们 node_modules 依赖足够大,足够深之后,整个 node_modules 就会变成一个黑洞。随随便便就有 1GB/2GB 甚至更多,这时候去进行 sls deploy 就会变成一种折磨,因为要压缩 node_modules,这个行为耗时太长了,即使压缩好了,上传到 S3 对象存储也要花费很久的时间。

如何解决? 这时候就需要让我们的 layer(层)出场了。

什么是 layer?

layer 你可以理解成,预先放置在我们 Lambda 函数容器中的文件包,你可以在里面放一些代码,库,数据文件,配置文件甚至是一些自定义语言运行时。比如我在使用的时候,往往会把 运行时 依赖的包,打成 zip 上传上去,又或者有些爬虫函数,需要使用 chromium 来模仿用户的行为,那么这种case则需要在 layer 里面直接内置一个 headless chromium

这些文件最终都会被挂载到函数容器中的 /opt 目录。

layer 的创建与注册

这里我给出一个示例,假设运行时的依赖只有 uuid (假设我们只依赖这一个包)

我们现在项目中安装 npm i uuid 并使用它:

// index.ts
import { v4 } from 'uuid'
v4()
// ...code...

这时候 uuid 在函数package.json这一层的 node_modules 文件夹里,测试运行后,运转良好。

让我们在当前目录下,创建一个 layers 文件夹,然后再在里面创建一个 uuid(名称可自定义)文件夹,创建 package.json 并写入:

{"dependencies": {"uuid": "^9.0.0"}
}

layers/uuid/package.json#dependencies 字段中的 uuid 即为你主目录下安装的版本。

然后执行 npm i/yarn 安装依赖 (不要使用pnpm),安装完成后会出现 layers/uuid/node_modules 文件夹,接下来就可以 layer 的上传和绑定了。

与函数同时创建和绑定

我们可以复用原先部署函数的那个 serverless.yml 文件,让它不但部署函数,也同时创建 layer 并进行绑定。具体配置如下:

layers:# layer 配置uuid:# 路径path: layers/uuid# aws lambda layer 里的名称name: ${sls:stage}-uuidfunctions:api:# ...package:individually: true# 既然我们把所有运行时都打成 layer 了自然不用上传 node_modules 了patterns:- "!node_modules/**"# layer 绑定配置layers:# 绑定 UuidLambdaLayer- !Ref UuidLambdaLayerenvironment:# 环境变量,告诉函数应该从哪里找依赖NODE_PATH: "./:/opt/node_modules"

其中最重要的就是2layers的配置了,其中 !Ref UuidLambdaLayer 这个其实就是引用了layers.uuid,只不过它的命名是一种约定,即 uuidu 大写加上 LambdaLayer,于是就变成了 UuidLambdaLayer 了,命名规则为 layer 名称的 Title_CaseLambdaLayer

注意!NODE_PATH: "./:/opt/node_modules" 这个环境变量是必不可少的,不然会导致无法从 layer 中加载 node_modules

相关配置的参考链接

此时使用 sls package 会在 .serverless 目录下生成 2zip:

  • api.zip 函数代码包
  • uuid.zip layer包

2个压缩包的名字,就是我们在 serverless.yml注册的名字。

sls deploy 会把它们依次上传,先layerfunction,并把layer上传部署后的结果,注册进我们的function,从而达成绑定的效果。

单独上传 layer 再绑定函数(推荐)

除了与函数同时创建和绑定的形式,我们还可以分步骤单独上传 layer 再绑定函数,这也是我推荐的方式。

这个就顾名思义,我们可以先上传layer拿到结果,在把结果写到函数的 serverless.yml 中去。这样步骤方面分为了 2 步,但是好处却是显而易见的。

它适用于这样的场景,我们的 layer 包很大,且不经常更新,这种情况是没有必要每次都去打包上传 layer 的。

我们部署只需要部署我们自己的函数代码,然后告诉 AWS 应该去绑定哪个 layer 的哪个版本就行。

按照这样的思路,我们就可以把刚刚那个 serverless.yml 拆成 2yml 文件:

  1. 单独上传 layer 配置文件
  2. 函数的 deploy 配置文件,加一行绑定 layer 的配置即可

单独部署 layer 的配置,内容如下:

# layers/serverless.yml
layers:uuid:path: uuidname: ${sls:stage}-uuid

执行 sls deploy 后上传部署成功会显示:

layers:uuid: arn:aws-cn:lambda:cn-northwest-1:000000000000:layer:dev-uuid:2

这一个字符串就是接下来我们需要写入函数 yml 配置进行绑定的关键,当然当时没保存刷了terminal也没关系,这个信息通过在当前目录执行 sls info 还会显示出来。

接下来我们去函数的 yml 配置去绑定 layers:

# serverless.yml
functions:api:# ....layers:# - !Ref UuidLambdaLayer 改为- arn:aws-cn:lambda:cn-northwest-1:000000000000:layer:dev-uuid:2

这样再在函数这一层执行 sls deploy 这层绑定关系就完成了,同时上传速度也要比 与函数同时创建和绑定 快不少,因为这种方法只要上传函数的代码包,再通过调用 AWS API 告诉它们这层绑定关系即可。

真正的运行时依赖

之前有一个细节没有讲,为什么我们上传 layer 是单独建一个 layers 的目录,在里面单个单个上传,而不是把外面函数的 node_modules 整个打包上传上去呢?

其实那样也可以,但是不够完美,因为这样做会导致layer代码包中的文件,过于冗余

举个简单的例子,默认情况下 npm 安装包时,会把 devDependenciesdependencies 都安装在 node_modules

比如 dependencies 里就是一些 express/lodash 啥的,devDependencies 里面就是 eslint/sass/webpack 这些开发时用的包,运行代码的时候用不着。

这时候,你直接打包上传 node_modules 显然是可以的,因为你所有的运行时依赖已经在里面了,不幸的是 eslint 等等许多无关紧要的包也进去了,这些加起来有可能会占用你 layer 包整体体积的一般以上甚至更多,显然这是没有必要的。

所以,你必须找到真正的运行时依赖!

注册包的约定

首先你必须在安装包时正确的注册 devDependenciesdependencies

我们把运行时用的到的放在 dependencies 里,到时候也从这里面抽出包名和版本,做成 layer。至于devDependencies 里我们只会把那些开发时用得到的包放在里面,它们就没有必要上传了,本地运行即可。

与平台强关联的运行时

其次你必须很清楚你的运行时是 nodejs 而不是什么浏览器。

虽然说 nodejs 是跨平台的,但是我们使用的第三方库里,有时候会存在着很多和平台强关联的二进制文件。

比如有些包会在下载下来之后,调用 postinstall 脚本获取我们的系统信息(平台,cpu架构),然后根据这些信息去使用不同的二进制文件。

又或者有些包基于 C++ addons 的,安装好之后,才在我们机器上实时去编译,生成适配我们系统平台的二进制文件。

这就导致一个问题,假如你直接用 win/macos 开发,你安装的二进制包,大概率无法在 aws lambda 环境下运行,因为它的环境是 Amazon Linux 2

所以,我们应该在挑选与线上 Lambda 运行时,相似的容器中,进行开发,上传代码和层 (layer)

具体怎么做呢?这里给出三种解决方案:

1. 云端安装依赖

顾名思义,直接在云上的目标容器环境中进行安装依赖这个行为,这也是最简单的解决方案。

2. 本地构建 Amazon Linux 2 容器环境

这要求我们在 docker 容器中开发,拉下 Amazon Linux 2 的镜像,在里面开发并上传层函数和代码包。

3. 利用 CI 构建并进行上传和部署

这个思路便是,由环境相同或者相似的 CI 容器,进行上传和部署。

比如我们可以利用 Github Action 去构建和上传,大致的配置如下:

name: Layeron:workflow_dispatch:jobs:upload:name: uploadtimeout-minutes: 15strategy:fail-fast: falsematrix:# 找一个相似的镜像 osos: [ubuntu-latest]node-version: [18]runs-on: ${{ matrix.os }}steps:- name: Check out codeuses: actions/checkout@v3with:fetch-depth: 2- name: Configure AWS credentials from Test accountuses: aws-actions/configure-aws-credentials@v3with:aws-region: cn-northwest-1aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}- name: Setup Node.js environmentuses: actions/setup-node@v3with:node-version: ${{ matrix.node-version }}- name: Install Serverlessrun: yarn global add serverless- name: Install puppeteer Layerrun: yarnworking-directory: apps/aws-express-api-ts/layers/puppeteer- name: sls deployrun: yarn deployworking-directory: apps/aws-express-api-ts/layers

镜像部署

当然,假如你使用镜像去部署 lambda,那以上这些问题都可以避免,但是代价便是冷启动时间比较长。

不过很多技术上的问题,都是可以通过付出更多金钱的方式去解决的,这点就综合考虑利弊吧。

Next Chapter

现在你已经学会了 layer 的用法和一些稀奇古怪的场景。

下一篇,《lambda nodejs 函数降低冷启动时间的最佳实践》中,将会详细介绍如何优化我们自身的代码,欢迎阅读。

完整示例及文章仓库地址

https://github.com/sonofmagic/serverless-aws-cn-guide

如果你遇到什么问题,或者发现什么勘误,欢迎提 issue 给我

相关文章:

依赖项的处理与层的创建与注册

依赖项的处理与层的创建与注册 依赖项的处理与层的创建与注册 新问题什么是 layer?layer 的创建与注册 与函数同时创建和绑定单独上传 layer 再绑定函数(推荐) 真正的运行时依赖 注册包的约定与平台强关联的运行时 1. 云端安装依赖2. 本地构建 Amazon Linux 2 容器环境3. 利用…...

Linux CentOS7 系统中添加用户

在linux centOS7系统中,添加用户是管理员的基本操作。作为学习linux系统的基本操作,对添加用户应该多方面了解。 添加用户的命令useradd,跟上用户名,就可以快速创建一个用户。添加一些选项,可以设置更人性化的用户信息…...

八、任务状态

1、任务状态简介 (1)任务状态可以简单的分为运行和非运行。 (2)非运行状态可以细分为:阻塞状态、暂停状态、就绪状态。 2、阻塞状态(Blocked) (1)举例说明:在日常生活的例子中,母亲在电脑前跟同事沟通时,如果同事一直没回复&a…...

基于python的反爬虫技术的研究设计与实现

摘 要 当下的网络是复杂的,网络上的信息非常的丰富,但也造成了大量的信息堆积,特别是大量的重复信息被反复的推送给用户。这是一个流量的时代,很多社会群体都会聚焦具备流量潜力的信息,从而发生蹭热度等行为来提升自己…...

msvcr120.dll放在哪里?怎么修复msvcr120.dll文件

当您在运行某些应用程序或游戏时遇到“msvcr120.dll缺失”错误时,这可能会影响您的使用体验。msvcr120.dll是Microsoft Visual C Redistributable的一部分,并且它提供了程序运行所需的运行时支持,今天我们来讨论一下msvcr120.dl文件缺失了要怎…...

Ubuntu搭建NFS服务

# 服务器初始化步骤 ## 查看磁盘 fdisk -l ## 格式化磁盘,后面的盘符注意对应关系 mkfs.ext4 /dev/sdc ## 新建文件夹 mkdir /mnt/nfs ## 挂载磁盘到创建的文件夹 echo "/dev/sdc /mnt/nfs ext4 defaults 0 0" >> /etc/fstab ## 重新挂载所有分区…...

PHP教学质量评估系统Dreamweaver开发mysql数据库web结构php编程计算机网页代码

一、源码特点 PHP教学质量评估系统是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 代码 https://download.csdn.net/download/qq_41221322/88301983 论文 https://down…...

ElementUI浅尝辄止15:Table 表格

用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。 Table组件比较常用,常见于数据查询,报表页面,用来展示表格数据。 1.如何使用? //当el-table元素中注入data对象数组后,在el-t…...

配置LVS_DR模式以及nginx负载均衡

一、配置LVS--DR模式: yum install ipvsadm 配置 LVS 负载均衡服务 ( 1 )手动添加 LVS 转发 1 )用户访问: www.uolookking.com-->vip 192 .168.79.110 ##> 这个是在 DNS 配置 hzitedu 域的 DNS 记录设置 w…...

虚拟数字人直播软件实现带货功能,成为新一代直播风口!

随着短视频带货市场的不断发展,虚拟数字人直播技术逐渐成为热门话题。而在现如今的市场趋势下直播带货则成为了一种火热的营销方式。那么,虚拟数字人直播软件是否可以结合起来,实现无人直播带货的效果呢?让我们来了解一下。 灰豚数…...

01背包问题暴力解法(回溯法)和经典解法

暴力解法(回溯法) import java.util.Arrays; import java.util.Scanner;public class Main {private final static int N 999;public static int SumValue 0;public static int SumWeight 0;public static int OptimalValue 0;public static int O…...

K8S的CKA考试环境和题目

CKA考试这几年来虽然版本在升级,但题目一直没有大的变化,通过K8S考试的方法就是在模拟环境上反复练习,通过练习熟悉考试环境和考试过程中可能遇到的坑。这里姚远老师详细向大家介绍一下考试的环境和题目,需要详细资料的同学请在文…...

docker清理

1. 查看docker 磁盘占用 docker system df 2. 参考: Docker磁盘占用与清理问题_docker system prune_蓝鲸123的博客-CSDN博客...

队列和栈两种数据结构的区别和Python实现

队列和栈是两种数据结构,其内部都是按照固定顺序来存放变量的,二者的区别在于对数据的存取顺序 栈是最后存入的数据最先取出,即后进先出 队列是先存入的数据最先取出,即先进先出 Python实现栈 使用append()方法存入数据,使用pop()方法读取数据 # 定义一个空列表(当做栈使…...

java 企业工程管理系统软件源码+Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展,企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性,公司对内部工程管…...

使用Smartctl脚本输入当前所有磁盘的状态

一、安装Smartctl yum install smartmontools 二、写一个脚本输出当前所有磁盘的状态并且按名称分别写入到文件中 #!/bin/bashfor dev in $(lsblk -l | grep disk | awk {print $1}) doecho "检测磁盘 $dev"smartctl -a /dev/$dev > $dev.smartctl done 以下是这…...

数学建模之插值法

目录 1 插值法概述2 插值法原理3 拉格朗日插值4 牛顿插值5 三次Hermite插值(重点)6 三次样条插值(重点)7 各种插值法总结8 n 维数据的插值9 插值法拓展10 课后作业 1 插值法概述 数模比赛中,常常需要根据已知的函数点进…...

rhcsa学习2(vim、创建管理用户、组等)

创建、查看和编辑文本文件 重定向符号 > 进程使用称为文件描述符的编号通道来获取输入并发送输出。所有进程在开始时至少要有三个文件描述符。如果程序打开连接至其他文件的单独连接,则可能要使用更大编号的文件描述符 上述通过通道1去写入,且写入的文…...

【使用教程】Github(自用)

1.下载Git⼯具 使在windows 命令⾏下边可以输⼊这两个命令: gitssh-keygen 2.配置git信息: 在命令⾏⾥输⼊: $ git config --global user.name “你在Github上注册的账号” $ git config --global user.email 你在Github上注册的邮箱 3. c…...

typeScript学习笔记(一)

学习资源来自: 类与接口 TypeScript 入门教程 (xcatliu.com) 一.TypeScript的安装和运行 1.安装TypeScript 通过npm(Node.js包管理器)安装Visual Studio的TypeScript插件:(Visual Studio 2017和Visual Studio 2015 Update 3默认包含了Ty…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

生成 Git SSH 证书

🔑 1. ​​生成 SSH 密钥对​​ 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​: -t rsa&#x…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

uniapp中使用aixos 报错

问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

相关类相关的可视化图像总结

目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系,可直观判断线性相关、非线性相关或无相关关系,点的分布密…...

解析“道作为序位生成器”的核心原理

解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

【若依】框架项目部署笔记

参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...

电脑桌面太单调,用Python写一个桌面小宠物应用。

下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...