Apache Airflow 任务中使用模板或上下文

本文大概记录一下在 Apache Airflow 的 Task 或 Operator(这两个基本是同一概念) 中如何使用 模板(Template) 和上下文(Context). Airflow 的模板引擎用的  Jinja Template, 它也被 FastAPI 和 Flask 所采纳。首先只有构造 Operator 时的参数或参数指定的文件内容中,或者调用 Operator render_template() 方法才能用模板语法,像 {{ ds }}.  Apache Airflow 有哪些模板变量可用请参考: Templates references / Variables, 本文将会打印出一个 Task 的 context 变量列出所有可用的上下文变量, 不断的深入,最后在源代码找到相关的定义。

通过使用模板或上下文,我们能能够在任务中使用到 Apache Airflow 一些内置的变量值,如 DAG 或任务当前运行时的状态等 。

当我们手动触发一个 DAG 时, 在 Configuration JSON 中输入的参数也能在 context 中找到. 所有的 Operator  继承链可追溯到 AbstractOperator -> Templater, 因此所有的 Operator(Task) 都能通过调用 Templater.render_template() 方法对模板进行渲染,该方法的原型是 阅读全文 >>

Docker Compose 简单配置 Apache Airflow 3.0(PostgreSQL)

Apache Airflow 重新唤起我的注意力是因为 Airflow 3.0 在近日 April 22, 2025 发布了,其二则是我们一直都有计划任务的需求,以下几种方案都太简陋

  1. 用 Windows 的计划任务或 Linux 的 Cron 都不易管理,且有单点故障问题
  2. 在 Java Spring 项目中使用集群模式的 Quartz 有些麻烦,且对于 AutoScaling 也不怎么友好
  3. AWS 上用 CloudWatch Rule + AWS Lambda 的方案可靠性没有问题,但不适于监控 

因此还有必要再次尝试 Apache Airflow, 它有集中管理的界面,各个部件都是可伸缩的,如 WebServer, Workers 等。特别是刚出的 Apache Airflow 3.0 带来以下主要新特性

  1. 新的服务化架构,各个部件间耦合度降低
  2. 多语言支持,借助了 Task SDK, 可望用 Java, JavaScript, TypeScript 等语言写 DAG
  3. DAG 支持版本控制,可回溯历史
  4. 支持事件驱动,即  DAG 可响应外部事件,如文件到达,消息队列等
  5. 引入了资产驱动调度功能,可根据数据资产的变化 进行触发,可以说是事件驱动的一类
  6. 全新的 React UI 界面

阅读全文 >>

Wireshark 查看本地浏览器的 HTTPS 加密通信

继续 TLS(或 SSL, HTTPS) 的话题。在我们诊断 HTTP 请求时,为了验证代码中发送了什么样的请求,会用 curl 或 Postman 的辅助,但它们都可能会带上额外的请求头等信息,最为可靠的办法是用网络抓包工具如 Wireshark, 从中看到的 HTTP 文本协议内容才是真正往外发送的内容。可是对于 HTTPS 的协议数据用 Wireshark 抓取到了也没用,因为它是加密了的,作为 TLS 的 Payload, 如果不知道加密算法或密钥是解不开来的。客户端与服务端的密钥交换是采用非对称方式加密的,只通过抓网络包是不可能知道最终确定的密钥是什么,除非像 Zscaler 那样堂而皇之地作为中间人攻击(man in the middle attack)。

但既然是本地浏览器能理解的网页内容,只要浏览器留了口子的话,也是有办法在 WireShark  中显示出抓取到的 HTTPS 的内容,那就是设置环境变量 SSLKEYLOGFILE, 然后启动浏览器(FireFox 或 Chrome), 就会把通信过程中的密钥记录到文件中,WireShark  中引用该 SSLKEY  文件就能显示出确切的 HTTP 请求的内容。 阅读全文 >>

自签发证书配置 HTTPS 单向双向验证

好久以前阅读《HTTP/2 in Action》一书起了个头,又重新放回了书架。近来再次对 HTTPS/TLS 来了劲,自己的博客用的是 Let's Encrypt 签发的证书,这次实践一下自签发证书的过程与配置,并实现单向和双向的认证方式。

如果是配置单向认证的过程需要有以下三个证书

  1. 根(CA) 证书: root.crt
  2. 服务端私钥文件: server.key
  3. 服务端公钥证书: server.crt

证书是含有组织与域名或(CA) 信息以及公钥的文件, root.key 和 root.crt 将被用于签发其他的证书。这里的 crt 证书是 x509 格式的。

浏览器只会信任某些 CA 机构签发的证书,如 DigiCert, GlobalSign, GoDaddy, Amazon Root CA,Let's Encrypt 等。如果是不被信任 CA 签发的证书,我们在浏览器中打开相应的 HTTPS url 就会看到 'Not Secure - Your connection is not private' 的提示,要继续访问需自行承担可能的安全责任。 阅读全文 >>

TLS 与 mTLS 的私钥交换过程

不管是 HTTPS, SSH, SFTP, SCP 等都涉及到 SSL(Secure Sockets Layer) 或 TLS(Transport Layer Security),以及使用非对称加密交互私钥的过程。

很久很久以前傻傻的认为所谓的非对称加密是像 MD5 那样内容加密后,无法从 MD5 码中还原出原始内容,其实那不就加密,是摘要(Digest)。非对称指的是加密与解密使用是不一样的密钥,即用公钥加密,私有解密。

提到 SSL 和 TLS, 顺便了解一下它们的极简史

SSL 由 Netscape 于 90 年代开发,SSL1.0(94 年,未公开), SSL 2.0(95 年发布), SSL 3.0(96 年发布), 后来 IETF 出了个 TLS 1.0 作为 SSL 3.0 的继承者,再就是后面的 TLS 1.1(2006), 1.2(2008), 1.3(2018)。2015 年 TLS 正式的取代了 SSL,从此江湖不再有 SSL 了,而我们习惯说的 SSL 只是在向曾经的 Netscape 致敬,其实指代的就是 TLS。

HTTPS 并非一直使用非对称加密进行数据通信,而只是用 TLS 安全的交换密钥,而后的数据通信使用私钥进行对称加密。如果数据通信都用非对称的方式性能是不允许的,所以只用非对称的方式进行密钥交换。 阅读全文 >>

Ollama - 简化使用本地大语言模型

学习完用 Transformers 和 llama.cpp 使用本地大语言模型后,再继续探索如何使用 Ollama 跑模型。Ollama 让运行和管理大语言模型变得更为简单,它构建在 llama.cpp 之上,并有优化,性能表现同样不俗。下面罗列一下它的特点

  1. 从它的 GitHub 项目 ollama/ollama, Go 语言代码 90.8%, C 代码 3.4%
  2. Ollama 不仅能运行 Llama 模型,还支持 Phi 3, Mistral, Gemma 2 及其他
  3. Ollama 支持 Linux, Windows, 和 macOS, 安装更简单,不用像 llama.cpp 那样需从源码进行编译,并且直接支持 GPU 的
  4. Ollama 有自己的模型仓库,无需申请访问权限,可从 Ollama 拉取所需模型,或 push 自己的模型到 Ollama 仓库pull llama3.2-vision
  5. Ollama 仓库的模型是量化过的,某个模型有大量的 tag 可选择下载,如 llama3.2 的 tags 有 1b, 3b, 3b-instruct-q3_K_M, 1b-instruct-q8_0, 3b-instruct-fp16 等
  6. 如果在 Ollama 上没有的模型,可以到 HuggingFace 上下载,或量化后再传到 Ollama 仓库

其他更多特性我们将在使用当中体验,仍然是在 i9-13900F + 64G 内存 + RTX 4090 + Ubuntu 22.4 台上进行 阅读全文 >>

用 llama.cpp 体验 Meta 的 Llama AI 模型

继续体验 Meta 开源的 Llama 模型,前篇 试用 Llama-3.1-8B-Instruct AI 模型 直接用 Python 的 Tranformers 和 PyTorch 库加载 Llama 模型进行推理。模型训练出来的精度是 float32, 加载时采用的精度是 torch.bfloat16。

注:数据类型 torch.float32, torch.bfloat16, 与 torch.float16 有不同的指数(Exponent),尾数(Fraction)宽度, 它们都有一位是符号位,所以剩下的分别为指数位和尾数位宽度, torch.float32(8, 23), torch.bfloat16(8, 7), torch.float16(5, 10)。

模型依赖于 GPU 的显存,根据经验, 采用 16 位浮点数加载模型的话,推理所需显存大小(以 GB 为单) 是模型参数量(以 10 亿计) 的两倍,如 3B 模型需要约 6G 显存。如果对模型进一步量化,如精度量化到 4 位整数,则所需显存大小降为原来的 1/4 到 1/3, 意味着 3B 模型只要 2 G 显存就能进行推理。所以我们可以把一个 3B 的模型塞到手机里去运行,如果是 1B 的模型 int4 量化后内存占用不到 1G(0.5 ~ 0.67)。

本文体验 llama.cpp 对模型进行推理,在 Hugging Face 的用户设置页面 Local Apps and Hardware, 可看到一些流行的跑模型的应用程序,分别是

  1. 生成文本的: llama.cpp, LM Studio, Jan, Backyard AI, Jellybox, RecurseChat, Msty, Sanctum, LocalAI, vLLM, node-llama-cpp, Ollama, TGI 
  2. 文生图的: Draw Things, DiffusionBee, Invoke, JoyFusion

阅读全文 >>

试用 Llama-3.1-8B-Instruct AI 模型

IT 从业人员累的一个原因是要紧跟时代步伐,甚至是被拽着赶,更别说福报 996. 从早先 CGI, ASP, PHP, 到 Java, .Net, Java 开发是 Spring, Hibernate, 而后云时代 AWS, Azure, 程序一路奔波在掌握工具的使用。而如今言必提的 AI 模型更是时髦,n B 参数, 量化, 微调, ML, LLM, NLP, AGI, RAG, Token, LoRA 等一众词更让坠入云里雾里。

去年以机器学习为名买的(游戏机)一直未被正名,机器配置为 CPU i9-13900F + 内存 64G + 显卡 RTX 4090,从进门之后完全处于游戏状态,花了数百小时对《黑神话》进行了几翻测试。

现在要好好用它的 GPU 来体验一下 Meta 开源的 AI 模型,切换到操作系统 Ubuntu 20.04,  用 transformers 的方式试了下两个模型,分别是

  1. Llama-3.1-8B-Instruct: 显存使用了 16G,它的老版本的模型是 Meta-Llama-3-8B-Instruct(支持中文问话,输出是英文)
  2. Llama-3.2-11B-Vision-Instruct: 显存锋值到了 22.6G(可以分析图片的内容)

都是使用的 torch_dtype=torch.bfloat16, 对于 24 G 显存的 4090 还用不着主内存来帮忙。如果用 float32 则需更多的显存,对于 Llama-3.2-11B-Vision-Instruct 使用 float32, 则要求助于主内存,将看到

Some parameters are on the meta device because they were offloaded to the cpu.

反之,对原始模型降低精度,量化成 8 位或 4 位则更节约显卡,这是后话,这里主要记述使用上面的 Llama-3.1-8B-Instruct 模型的过程以及感受它的强大,可比小瞧了这个 8B 的小家伙。所以在手机上可以离线轻松跑一个 1B 的模型。 阅读全文 >>

ECS Task Definition 中需要的 image:tag 明明在 ECR 中存在却找不到 image

这是近些天遇到的一个问题,因为早先使用 ECS 为求快速验证新的 Docker Image, 一直是用相同的 Tag 覆盖 ECR 中原有的 Docker Image,然后停掉 ECS 中相应的 Task, 新的 Task 起来,拉取最新 Docker Image,这样不用重新部署 Infrastructure, 以最小的改动就能达到偷梁换柱的效果。比如下面的情景:

  1. ECS 任务定义中所用的 Image 是 123456789012.dkr.ecr.us-east-1.amazonaws.com/demo:1.10
  2. 构建新的 Docker Image, 然后再 docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/demo:1.10
  3. 覆盖后,在 ECR 中将有两个 Tag,  刚 push 的是 1.10, 被覆盖的变成 -, 多次覆盖将会产生更多的 -
  4. 停掉 ECS 相应的 Task, 新的 Task 起来,拉取 123456789012.dkr.ecr.us-east-1.amazonaws.com/demo:1.10 代表的新镜像

这种做法在以前是灵验的,每次修改代码,覆盖现有 Tag, 重启 Task 就能快速测试, 不用重新创建 Task Definition 和别的 Infrastructure。

然而最近突然不起作用了,本地不断的修改代码,构建新的镜像,覆盖原有 Tag, 重启 Task, 可是依旧跑的是老代码。怀疑 ECR 中的 Image 有问题,用 docker pull 下来看确实是新代码,就差进到 ECS Task 实例中去找问题。而且即使是重新运行 Terraform 来部署整个 Infrastructure 都无济于事,就是 aws_ecs_service 中指定了 force_new_deployment = true 也没辙,因为只要 Docker Image 的 Tag 没变,  Terraform 就认为是 no change阅读全文 >>

多线程环境中使用 Mockito 来 Mock 静态方法

回看三年前的一篇日志 Mockito 3.4.0 开始可 Mock  静态方法,最后对 Mockito 产生的缺憾是它无法用来 Mock 非测试线程(主线程)中的静态方法调用。其实这也是可以变通的,下面慢慢道来。

首先回顾一下 Mockito  的静态方法 Mock 的使用方法,随着 Mockito 版本的升级,引入依赖的方式也发生了些许的变化,以 Maven 项目为例,如果在 JUnit 5 下用 Mockito 的 pom.xml 依赖中为

由它引入的全部相关依赖

阅读全文 >>