模块 11查看课程目录
00起跑线:两门语言,一台机器01先建立 BEAM 心智模型02Elixir 基础:让数据流过函数03Erlang 基础:读懂 BEAM 的母语04两种语法,一套语义05从裸进程理解并发06从手写循环推导 OTP07监督树与应用08状态、吞吐与背压09分布式与可运维性10Erlang ↔ Elixir 互操作11综合项目:可靠任务调度器
11
实战项目ElixirErlangOTP

综合项目:可靠任务调度器

把函数式建模、进程协议、OTP、互操作、容量与运维串成一个系统。

4检查点
10 小时预计完成
为什么先学这个

先修正心智模型,再增加 API

零散练习容易把每个 API 都做对,却没有面对系统级取舍。这个项目刻意加入容量、失败和语言边界,让你必须说明:谁拥有状态、什么能重试、恢复半径多大、过载如何暴露。

学完你能做到

可验证的学习目标

  • 能从业务不变量推导进程与监督树
  • 能让 Erlang 与 Elixir 在同一发布包中承担真实职责
  • 能通过故障注入验证恢复,而不是只跑 happy path
前置知识
  • 完成前 11 个模块
  • 能独立编写 GenServer/gen_server 与 Supervisor
最小心智模型

先抓住三个词

01

at-least-once

任务可能重复执行。系统需要幂等键或去重策略,不能用“重试”假装恰好一次。

02

bounded queue

队列有固定容量;满时系统必须阻塞、拒绝或降级,而不是继续承诺。

03

runbook

面向运行者的诊断与处置说明:看什么指标、如何判断、可以执行什么安全动作。

双语代码桥

先对齐协议,再看标点

Elixir 管理易用 API 与输入验证;Erlang worker 明确掌控队列容量和调度状态。

Elixir
defmodule Scheduler.API do
  def submit(payload, opts \\ []) do
    with :ok <- validate(payload),
         {:ok, id} <- :scheduler_core.enqueue(payload, opts) do
      {:accepted, id}
    else
      {:error, :queue_full} -> {:rejected, :busy}
      {:error, reason} -> {:rejected, reason}
    end
  end
end
Erlang
handle_call({enqueue, Job, Opts}, _From,
            State = #state{queued = Queue, max = Max}) ->
  case queue:len(Queue) < Max of
    true ->
      {Id, Next} = add_job(Job, Opts, State),
      {reply, {ok, Id}, dispatch(Next)};
    false ->
      {reply, {error, queue_full}, State}
  end.
LAB
可运行实验

四次故障注入

约 15–25 分钟

不要把“进程重启了”当作验收。对 worker 崩溃、非法消息、任务超时、节点断开分别定义期望状态。

  1. 01

    执行中的 worker 主动 exit,检查任务重试与容量计数

  2. 02

    发送不符合协议的消息,确认服务不中断且有观测信号

  3. 03

    让任务超过 timeout,检查取消/隔离与迟到结果

  4. 04

    断开远程节点,检查 stale 状态与重连

在终端 / shell 中运行
mix test --only fault_injection --trace
预期观察
  • 所有长期进程仍在监督树中
  • 任务不会无限重试
  • 队列与并发计数最终恢复一致
  • 每次恢复都有结构化日志或指标
故意弄坏

删除重试上限并让任务稳定失败。观察 restart/重试风暴如何放大原始故障。

这个实验能证明

指定故障下,系统按已定义策略恢复或拒绝。

这个实验不能证明

四个场景不能穷尽生产故障;尤其不能证明恰好一次、跨节点一致性或外部副作用安全。

快速自测

任务失败后自动重试,最先必须明确什么?

本章挑战

毕业答辩

交付源码、监督树图、消息协议、容量预算、故障实验记录、release 与一页 runbook;用 10 分钟解释三个最重要取舍。

提示 1轻推一下

取舍必须包含一个你明确没有实现的保证。

提示 2缩小问题

演示 queue_full,而不是只演示成功提交。

提示 3接近实现

runbook 从“用户看到什么”反推需要的信号。

提示 4用验收标准反推

从下面每一条验收标准倒推一个最小测试。若某条无法写成测试,先把表述改成可观察结果。

完成标准
  • Elixir 与 Erlang 都有真实且合理职责
  • 并发、队列、timeout、retry 全部有上限
  • ExUnit 与 EUnit 穿过互操作边界
  • release 可启动,runbook 可由他人执行
带走这三句话

复习卡

  1. 1可靠系统先定义不变量、容量和失败语义,再选择进程结构。
  2. 2重试扩大副作用;幂等与上限必须成对出现。
  3. 3可运维性不是最后加日志,而是从协议开始保留证据。
继续核对

本章一手资料

Mix and OTPErlang ApplicationsElixir Releases