AWS Lambda 中使用 Python 并发编程

无论在何处,有多重任务要处理时,并发编程总是要得到考虑的。比如有 IO 等待时的并发或 CPU 密集型时的并行计算,并发通常是指在同一个 CPU 上按时间片轮换执行,并行是任务在不同的 CPU 上执行。能有效使用 CPU 多核的语言可以让线程运行在不同的核上实现并行,如果是启动的子进程能由操作系统运行在其他 CPU 核上。

回到 AWS Lambda 中的 Python 代码,如果是处理 IO 等待,使用多线程并发就行,大致的代码如下:

with ThreadPoolExecutor(10) as executor:
    result = executor.map(task_function, task_inputs)

以上代码在 AWS Lambda 中是可以运行的。

如果是 CPU 密集型的任务,用 Python 的多线程就要歇菜了,因为存在著名的 Python's GIL 的约束。这时候就必须要考虑多进程并行的方式,同时应知晓当前选择的 Lambda 运行环境有多少个 CPU 内核,因为如果是单核的话再多进程也无济于事,没必要启动多于核心数的进程。底下是本人上篇博客测试收集的不同 AWS Lambda 内存选择对应的 CPU 核心数,以及实际可用内存大小的关系表 阅读全文 >>

配置 FastAPI/Uvicorn/Hypercorn 的访问日志

有了 FastAPI 之后,用 Python 实现 API 或 Web 都不再考虑 Flask 了。Flask 最早在 13 年前的 2010 年 4 月 1 日发布,实现的是 WSGI; FastAPI 较为年轻,于 4 年前的 2018 年 12 月 5 日发布,支持 ASGI。性能方面普遍是 FastAPI 比 Flask 高,编程方面就各取所好吧,使用 Flask 的时候还是 1.x 的版本,最近用 FastAPI 较多,所以无法对比。

FastAPI 本身没提供启动 Web 服务的代码,不像 Flask 还能通过 Flask 对象 或 flask 命令启动一个开发用途的 Web 服务,而 FastAPI 必须用其他的组件(ASGI server)来启动,比如各种 *corn 或 Daphne

  1. Uvicorn: FastAPI 官方的出品,默认启用访问日志,相关的参数有 --log-config <path>, --access-log/ --no-access-log 启用或关闭访问日志,默认是开启的。
  2. Hypercorn: 相关的配置选项有 --access-logformat, --access-logfile
  3.  Hypercorn: 它只是实现了 WSGI 规格的服务,所以不兼容 FastAPI, 只能作为 Uvicorn 进程的管理器。Gunicorn 作为 WSGI 服务器有丰富的访问日志配置,但访问日志仍然是由 Uvicorn 输出

阅读全文 >>

体验 Python FastAPI 的并发能力及线, 进程模型

本文进行实际测试 FastAPI 的并发能力,即同时能处理多少个请求,另外还能接收多少请求放在等待队列当中; 并找到如何改变默认并发数; 以及它是如何运用线程或进程来处理请求。我们可以此与 Flask 进行对比,参考 Python Flask 框架的并发能力及线,进程模型,是否真如传说中所说的 FastAPI 性能比 Flask 强, FastAPI 是否对得起它那道闪电的 Logo。

本文使用 JMeter 进行测试,测试机器为 MacBook Pro, CPU 6 核超线程,内存 16 Gb。

对于每一种类型 Web 服务基本的测试是每秒发送 2 个请求,连续发送 1000 个,500 秒发送完所有请求,程序中 API 方法接受到请求后 sleep 800 秒,保证在全部 1000 个请求送出之前一直占着连接,并有充足的时间对连接进行分析。在测试极端并发数时,由于在 Mac OS X 尽管设置了 ulimit 最多也只能创建 4000 多一点线程,所以在模拟更多用户数时,JMeter 在远程 Linux(Docker 或虚拟机) 上运行测试用例。

请求的 URL 是 http://localhost:8080/?id=${count}, 带一个自增序列用以识别不同的请求, JMeter 的 Thread Group 配置为 Number of Threads (users): 1000, Ramp-up period (seconds): 500 阅读全文 >>

Python __slots__ 的用法笔记

Python 是一个动态语言,可以动态的给实例或类增减属性或方法,给类添加的属性会影响到前后所有创建的实例。但是使用 __slots__ 属性可以限定类或实例属性和方法,如果没有 __slots__ 的话实例的属性和方法包含在实例的 __dict__ 字典中,类的属性和方法包含在类的 __dict__ 字典中。

在使用 __slots__ 按常规写法可能会出现的问题大概有

  1. AttributeError: 'Xxx' object has no attribute 'yyy'
  2. AttributeError: 'Xxx' object attribute 'yyy' is read-only
  3. ValueError: 'yyy' in __slots__ conflicts with class variable

我们来看下面的例子 阅读全文 >>

Python Flask 框架的并发能力及线,进程模型

本文旨在测试 Python Flask 框架的默认并发能力,即同时能处理多少个请求,以及请求等待队列大致有多大; 并找到如何改变默认并发数。虽然网上或许很容易找到它们的默认并发数,但通过实验的方式可以得到更感性的认识。

本文写作时使用的环境为

  1. 测试机器为 MacBook Pro, CPU 6 核超线程,内存 16 Gb
  2. JMeter 5.5 -- 连续发送请或压力测试
  3. Python 3.10.9
  4. Flask 2.2.2

从 JMeter 每半秒发送一个请求,连续发送 1000 个,程序中 API 方法接受到请求后 sleep 800 秒,保证在全部 1000 个请求送出之前一直占着连接,以此来找到同时被处理的请求数目,并且有足够的时间统计当前的 TCP 连接数。在测试极端规模的并发数时,由于在 Mac OS X 很难突破 5000 个线程的限制,这时就让 JMeter 分布到远程 Linux(Docker 或虚拟机) 上执行。

请求的 URL 是 http://localhost:8080/?id=${count}, 带一个自增序列用以识别不同的请求, JMeter 的 Thread Group 配置为 Number of Threads (users): 1000, Ramp-up period (seconds): 500 阅读全文 >>

Python 基于多环境的配置方式

部署到不同环境的应用会使用到各自的配置,如 Dev, QA, Stg, Prod 有自己的数据库等资源。Spring Boot 可采用 Profile 对应不同的环境,不同 Profile 选择自己的配置文件 application-${profile}.properties。本人还是偏爱在同一个文件中分组配置,容易查错与编辑,类如在 application.properties 文件中以下面的方式

db.host=aaa
%dev.db.host=bbb
%prod.db.host=ccc 

那么在 Python 的项目中应该如何针对不同环境进行配置呢?大概有以下几种

  1. 不同环境的 Config 类
  2. YAML 文件
  3. TOML 文件
  4. JSON 文件
  5. INI 文件
  6. dotenv(.env) 文件

第一种方式是本人推荐的,其他的方式只是在不同格式的配置文件中,按环境组织不同的配置值,其他方式的不同配置读入内存中基本是体现为字典变量。在 Python 配置中要支持像配置的 placeholder(像 ${host} 还需自己实现。 阅读全文 >>

向量间距离/相似度及用 Python 进行计算

计算距离的目的也是为了确定两个向量的相似度,这里的向量可以是纯数学的数组,或者是一系列带有某些可量化特征值的物件。写作本文的原由是需要用 Numpy 计算两个实际对象的相似度,实现代码非常简单,因此更不能满足于此,借此机会多多了解下向量之间距离和相似度的概念,还回顾下一些相关的数学知识。

计算两个向量的相似度有许多的方法,如

  1. 欧氏距离(Euclidean Distance): 点间直线距离,数值越小越相似
  2. 夹角余弦(Cosine): 余弦相似度(Cosine Similarity),计算两个向量之间的夹角,值在  -1 ~ 1 之间
  3. 曼哈顿距离(Manhattan Distance): 点间在坐标系上的绝对轴距总和
  4. 切比雪夫距离(Chebyshev Distance): 像国际象棋中的王从一格子到另一个格子间的距离
  5. 标准化欧氏距离(Standardized Euclidean distance): 先对各个分量进行标准化,再求欧氏距离
  6. 其他距离和相关系数,如马氏距离(Mahalanobis Distance), 兰氏距离(Lance Williams Distance); 皮尔逊相关系数(Pearson Correlation Coefficient), 杰卡德相似系数(Jaccard similarity coefficient)

本文主要关注到欧氏距离和余弦相似度这两个数值的求解上。 阅读全文 >>

Python 实现 RSA 非对称加解密

在阅读《HTTP/2 in Action》的 HTTPS 一节后,不觉一脚踏入到非对称加密这一领地而不能自拔。与非对称加密相对应的是对称加密,有点像是由一把钥匙反锁的门,只能用同一把钥匙打开; 而非对称加密是用一把钥匙反锁门,但只能用另一把特定的钥匙才能打开它,锁门的叫做公钥,开门的叫做私钥。

在此之前我理解的非对称加密以为是像 MD5 那种摘要(Digest), 由明文生成的 MD5 摘要信息是无法还原出原始数据的,谬以为那就是所谓的非对称。

1976 年,两位美国计算机学家 Whitefield Diffie 和 Martin Hellman 提出了非对称加解密的的构思。1977 年三位数学家 Ron Rivest, Adi Shamir 和 Leonard Adleman 实现了非对称加密算法,即 RSA,取自这三个的姓的首字母

具体的 RSA 算法原理可参考阮一峰的两篇网络日志:RSA算法原理 (一)RSA算法原理 (二), 大致就是通过互质的两个数,计算欧拉函数, 模反元素,最终算法公钥和私钥,公钥加密的数据只能用用私钥解密,以当前的算力,只要 RSA 的密钥足够长,如 1024 位以上,私钥是无法通过公钥推断出来的。 阅读全文 >>

Diagram as Code -- 用 Python 画框架图

最近注意到一个很有意思的项目 Diagrams, 用 Python 代码来绘制架构或流程图, 以前基本用 Gliffy 来画。继一系列 X as X, 如 PaaS, SaaS, IaaS, CaC(Configuration as Code), IaC(Infrastructure as Code) 等,Diagrams 喊出了 Diagram as Code 的口号。其实,在这之前, Markdown 就做了许多 Diagram as Code 的事情,也许更准确说是 Diagram as Document。

熟练的程序员大概不喜欢用可视化设计器来生成 GUI 代码,那会让代码变得极不简洁,而是直接写,眼中看到的是代码,头脑中即时产生映像。

Diagrams 就是这样一款写 Python 代码产生架构或流程图的库,它绘制的架构图支持主要的云服务提供商,如

  1. 知名的(本人认为的): AWS, Azure, GCP, IBM, DigitalOcean, AlibabaCloud, OCI(Oracle Cloud Infrastructure, 不是 Open Container Initiative), OpenStack
  2. 刚了解到的: Google 的 Firebase, Elastic(ElasticSearch 出品方也有自己的平台), Outscale
  3. 以及应用平台 K8S, Saas 和 OnPrem 中的元素
  4. 通用元素,编程语言及流程图,还能定制自己的节点图

阅读全文 >>

学习 Airflow 第一篇章

Airflow 起初是由 Airbnb 开发的, 用于调度和监控工作流的平台,后来开源了, 并于 2019 年 1 月成为了 Apache 的顶级项目。它是用 Python 编写的,管理的工作流是有向无环图(DAG - Directed Acyclic Graph), 这能满足绝大多数情况下的需求。

顺带插一句,Airflow 用了与 Google Photos 极其相似的 Logo,不知算不算侵权。

说到工作调度,头脑中很快会掠过 Cron, 计划任务, Quartz, Spring Schedule, 和 Control-M。除了商业的 Control-M 有调度和监控工作流的功能外,其他的基本只用来调度任务,监控全靠自己的日志。

还有一个类似的工具是由易观贡献给 Apache 的 DolphinScheduler, 它处理的也是 DAG 工作流,用 Java 实现的,所以体量大,硬件要求会高些。它的工作流的创建是通过 Web UI 可视化界面完成的,对程序员来说不那么友好。奇怪的是, 作为 Apache 旗下的项目,项目首页面是中文的,启动后控制台默认界面也是中文的。

而 Airflow 功能就厉害了, 它可动态管理工作流,易于扩展,可集群化进行伸缩,更有一个漂亮的 UI 用于实时监控任务。基于以上特性 Airflow 是很适于执行数据的 ETL(Extract, Transform, Load) 操作的。

这么好的开源产品, 免不了又被 AWS 盯上了, 以 Amazon Managed Workflows for Apache Airflow(MWAA) 服务进行出售,费用还真不菲。AWS 创造性的以 vCPU 数量,DAG 数量限制进行分层次进行收费,远比自己启动一两个 EC2 实例部署 Airflow 贵的多。但 MWAA 有个方便的特性就是 DAG 文件可以放到 S3 中自动部署,相信自己部署的 Airflow 也能进行扩展而从 S3 加载 DAG。 阅读全文 >>