Project Icon

rinha-de-backend-2024-q1

后端开发性能挑战与系统设计竞赛

rinha-de-backend-2024-q1是一个后端系统设计挑战项目,要求开发者实现高性能的交易和账户查询API。项目设置了严格的并发和资源限制,考验参与者在负载均衡、并发控制和数据一致性方面的技能。这个平台为后端开发者提供了实践和提升系统设计能力的机会。

后端擂台赛 - 2024年第一季度

结果在此

直播录像在此

后端擂台赛是一项以挑战形式分享知识为主要目标的比赛!这是第二届。提交作品的截止日期是2024年3月10日23:59:59,结果将于2024年3月14日19:00在YouTube上通过直播公布。

本届擂台赛的主要主题是关于贷记和借记(信贷)的并发控制,灵感来自于同行@lucascs@kmyokoyama这条这条评论中对这条推文的回应。

艺术图

如果你想更深入地了解擂台赛的精神,请查看第一届的仓库

需要做什么?

要参与,您需要开发一个具有以下端点的HTTP API:

交易

请求 POST /clientes/[id]/transacoes

{
"valor": 1000,
"tipo" : "c",
"descricao" : "descricao"
}

其中

  • [id](在URL中)必须是一个整数,表示客户的标识。
  • valor必须是一个正整数,表示分(我们不处理分的分数)。例如,10元相当于1000分。
  • tipo只能是c表示信用或d表示借记。
  • descricao必须是1到10个字符的字符串。 所有字段都是必填的。

响应 HTTP 200 OK

{
"limite" : 100000,
"saldo" : -9098
}

其中

  • limite必须是客户的注册限额。
  • saldo必须是交易完成后的新余额。 成功的交易请求的HTTP状态码必须是200!

规则 借记交易绝不能使客户的余额低于其可用限额。例如,限额为1000(10元)的客户余额绝不应低于-1000(-10元)。在这种情况下,-1001或更低的余额意味着后端竞赛中的不一致!

如果借记请求会导致余额不一致,API应返回HTTP状态码422,并且不完成交易!这种情况下的响应体不会被测试,您可以选择如何表示它。如果有效载荷字段不符合规范,例如descricao字段超过10个字符或tipo字段不是cd,也应返回HTTP 422。如果valor字段指定了非整数,您可以返回HTTP 422或400。

如果URL中的[id]属性是不存在的客户标识,API应返回HTTP状态码404。这种情况下的响应体不会被测试,您可以选择如何表示它。如果API返回类似HTTP 200并在响应体中表示未找到客户,或者返回无响应体的HTTP 204,我将极度沮丧,后端竞赛将永远取消。

对账单

请求 GET /clientes/[id]/extrato 其中

  • [id](在URL中)必须是一个代表客户标识的整数。

响应 HTTP 200 OK

{
"saldo": {
"total": -9098,
"data_extrato": "2024-01-17T02:34:41.217753Z",
"limite": 100000
},
"ultimas_transacoes": [
{
"valor": 10,
"tipo": "c",
"descricao": "descricao",
"realizada_em": "2024-01-17T02:34:38.543030Z"
},
{
"valor": 90000,
"tipo": "d",
"descricao": "descricao",
"realizada_em": "2024-01-17T02:34:38.543030Z"
}
]
}

其中

  • saldo
    • total 必须是客户当前的总余额(不仅仅是以下显示的最近交易)。
    • data_extrato 必须是查询对账单的日期/时间。
    • limite 必须是客户的注册限额。
  • ultimas_transacoes 是按日期/时间降序排列的交易列表,包含最多10笔最近交易,具有以下内容:
    • valor 必须是交易金额。
    • tipo 必须是 c 表示贷记,d 表示借记。
    • descricao 必须是交易期间提供的描述。
    • realizada_em 必须是交易的执行日期/时间。

规则 如果URL中的 [id] 属性是不存在的客户标识,API必须返回HTTP状态代码404。在这种情况下,响应体不会被测试,你可以选择如何表示它。你已经知道如果你的API返回2XX范围内的东西会发生什么,对吧?谢谢。

客户初始登记

为了在测试中强调并发性,应该只登记和测试少数客户。因此,测试前必须预先登记以下五位客户,包括他们的ID、限额和初始余额 - 这一点至关重要!

ID限额初始余额
11000000
2800000
310000000
4100000000
55000000

注意:请勿特意登记ID为6的客户,因为测试的一部分是验证ID为6的客户确实不存在,且API会返回HTTP 404错误!

如何制作和提交?

与之前的后端竞赛一样,你需要将你的API和其他使用的组件容器化为docker-compose格式,遵守CPU和内存资源限制最低架构配置,以及制品结构和提交流程(你的内容需要提交什么、在哪里提交、何时提交)。

你可以个人提交,也可以2人组队、3人组队,甚至50人组队。没有人数限制。你和/或你的团队可以提交多个作品,只要API不同即可。

工件、流程和截止日期

要参与,只需在本存储库中创建一个拉取请求,在participantes中包含一个子目录,其中包含以下文件:

  • docker-compose.yml - 可由docker-compose解释的文件,其中包含组成您的API的服务声明,遵守CPU/内存限制最小架构
  • README.md - 至少包括您的姓名、使用的技术、API源代码存储库的链接,以及如果获胜时的联系方式。您可以自由添加其他信息,如网站链接等。
  • 在此处也包括任何其他必要的目录/文件,以确保您的容器正确启动,例如nginx.confbanco.sql等。 这里有一个提交示例可以帮助您。 重要! 所有在docker-compose.yml中声明的服务必须公开可用!否则,将无法执行测试。为此,您可以在hub.docker.com上创建一个账户来提供您的镜像。这些镜像通常格式为<user>/<image>:<tag> - 例如,zanfranceschi/rinha-api:latest。 上一届比赛中的一个常见错误是将镜像声明为本地存在。这对于构建镜像的人可能是正确的(在本地进行了构建),但对于执行测试的服务器来说并非如此! 重要! 必须将包含API源代码的存储库设为公开访问,并在提交的README.md文件中提供信息。毕竟,后端擂台赛的主要目标是分享知识! Ana的提交/拉取请求示例可能包含以下文件:
├─ participantes/
|  ├─ ana-01/
|  |  ├─ docker-compose.yml
|  |  ├─ nginx.config
|  |  ├─ sql/
|  |  |  ├─ ddl.sql
|  |  |  ├─ dml.sql
|  |  ├─ README.md

提交拉取请求的截止日期/时间是2024-03-10T23:59:59-03:00。在此日期/时间之后,任何拉取请求都将被自动拒绝。 请注意,在截止日期/时间之前,您可以提交任意数量的拉取请求!

API的最小架构

这里所说的"API"指的是为了使处理HTTP请求的服务能够运行而涉及的所有服务,如负载均衡器、数据库和HTTP服务器。

你的API至少需要包含以下服务:

  • 一个使用轮询算法进行流量分配的负载均衡器。与之前的版本不同,你不必使用Nginx - 可以选择(甚至自己开发)任何一种,比如HAProxy。负载均衡器将是接收测试请求的服务,它需要在9999端口接受请求
  • 2个Web服务器实例用于处理HTTP请求(由负载均衡器分发)。
  • 一个关系型或非关系型数据库(不包括以内存存储为主要特征的数据库,如Redis等)。
flowchart TD
G(压力测试 - Gatling) -.-> LB(负载均衡器 / 端口9999)
subgraph 你的应用
LB -.-> API1(API - 实例01)
LB -.-> API2(API - 实例02)
API1 -.-> Db[(数据库)]
API2 -.-> Db[(数据库)]
end

注意:你可以使用额外的组件,如果你想的话。但请记住,CPU和内存的限制必须遵守以下规则:所有服务声明的限制总和不得超过1.5个CPU单位和550MB内存!请使用常识和诚信,不要添加一个关系型数据库和一个Redis,然后只使用Redis作为存储 - 毕竟,Rinha只是一个促进学习而非不公平竞争的小游戏。

CPU/内存限制

在您的docker-compose.yml文件中,您应该限制所有服务,使它们的总和不超过以下限制:

  • deploy.resources.limits.cpu 1.5 – 所有服务之间分配的一个半CPU单位
  • deploy.resources.limits.memory 550MB – 所有服务之间分配的550兆字节内存 注:请使用MB作为内存计量单位;这样可以更容易验证限制。
# docker-compose.yml文件中某个服务配置的部分示例
...
nginx:
  image: nginx:latest
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
  depends_on:
    - api01
    - api02
  ports:
    - "9999:9999"
  deploy:
    resources:
      limits:
        cpus: "0.17"
        memory: "10MB"
...

帮助你的示例文件

以下仅为示例文件,以便你不必从零开始,如果遇到任何困难或只是想加快 API 的构建过程。显然,你可以根据自己的需要进行修改,但要遵守之前解释的所有限制。再次强调,你不一定要使用关系型数据库 - 以下示例仅作说明用途。

docker-compose.yml

version: "3.5"

services:
  api01: &api
    # 请记住,你的 HTTP 服务必须托管在公开可访问的仓库中!
    # 例如:hub.docker.com
    image: ana/minha-api-matadora:latest
    hostname: api01
    environment:
      - DB_HOSTNAME=db

    # 除了负载均衡器的端口外,不需要暴露任何其他端口,
    # 但人们通常会这样做以便在开发阶段测试他们的 API 并连接到数据库。
    ports:
      - "8081:8080"
    depends_on:
      - db
    deploy:
      resources:
        limits:
          cpus: "0.6"
          memory: "200MB"

  api02:
    # 这个语法重用了 'api01' 中声明的内容。
    <<: *api
    hostname: api02
    environment:
      - DB_HOSTNAME=db
    ports:
      - "8082:8080"

  nginx:
    image: nginx:latest
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - api01
      - api02
    ports:
      # 负载均衡器必须暴露/使用 9999 端口!
      - "9999:9999"
    deploy:
      resources:
        limits:
          cpus: "0.17"
          memory: "10MB"

  db:
    image: postgres:latest
    hostname: db
    environment:
      - POSTGRES_PASSWORD=123
      - POSTGRES_USER=admin
      - POSTGRES_DB=rinha
    ports:
      - "5432:5432"
    volumes:
      - ./script.sql:/docker-entrypoint-initdb.d/script.sql
    deploy:
      resources:
        limits:
          # 请注意,这里声明的所有服务限制总和
          # 是 1.5 个 CPU 单位和 550MB 内存。
          # 这里的分配只是一个例子 - 你可以根据需要进行分配。
          cpus: "0.13"
          memory: "140MB"

# 使用 `bridge` 模式应该适合测试中使用的负载。
# 上一版本受益于 host 模式,因为请求量相对较高,网络虚拟化成为瓶颈,
# 但这种模式配置更复杂。你可以自由选择想要的模式,
# 只要不与操作系统中常用的端口冲突即可。
networks:
  default:
    driver: bridge
    name: rinha-nginx-2024q1

script.sql

-- 在这里放置初始脚本
CREATE TABLE...

DO $$
BEGIN
  INSERT INTO clientes (nome, limite)
  VALUES
    ('o barato sai caro', 1000 * 100),
    ('zan corp ltda', 800 * 100),
    ('les cruders', 10000 * 100),
    ('padaria joia de cocaia', 100000 * 100),
    ('kid mais', 5000 * 100);
END; $$

nginx.conf

events {
    worker_connections 1000;
}

http {
    access_log off;
    sendfile   on;
    
    upstream api {
        server api01:8080;
        server api02:8080;
    }

    server {
        listen 9999; # 还记得必须使用 9999 端口吗?

        location / {
            proxy_pass http://api;
        }
    }
}

测试工具

与上一版本一样,本次仍将使用Gatling工具进行性能测试。在开发阶段执行测试可以帮助发现潜在的问题和瓶颈,这一点非常重要。测试脚本可在本仓库的load-test目录中找到。

测试环境

要了解环境详情(操作系统和软件版本),请访问测试环境规格

请注意,测试将在Linux x64环境中执行。因此,如果您的开发环境使用不同的架构,您需要按以下方式构建Docker镜像: $ docker buildx build --platform linux/amd64 例如: $ docker buildx build --platform linux/amd64 -t ana/minha-api-matadora:latest .

执行测试

以下是快速执行测试的说明:

  1. https://gatling.io/open-source/ 下载Gatling
  2. 确保已安装JDK (64位OpenJDK LTS(长期支持)版本:11、17和21) https://gatling.io/docs/gatling/tutorials/installation/
  3. 确保将GATLING_HOME环境变量设置为Gatling安装目录。 要确认变量设置正确,以下路径应该有效: Linux上的$GATLING_HOME/bin/gatling.sh和Windows上的%GATLING_HOME%\bin\gatling.bat
  4. 配置./executar-teste-local.sh脚本(如果在Windows上,则使用./executar-teste-local.ps1
  5. 在9999端口启动您的API(或负载均衡器)
  6. 运行./executar-teste-local.sh(如果在Windows上,则运行./executar-teste-local.ps1
  7. 等待测试完成并打开报告 模拟结束时会显示报告路径。 结果/报告保存在./load-test/user-files/results中。

请随意修改模拟以测试不同方面和场景。请不要在提交的pull request中包含这些更改!

不客气 :)

预测试

在上一届Rinha中,测试在容器启动后几秒钟就开始了,由于CPU和内存限制,并非所有服务都能在如此短的时间内准备好接收请求。在本届中,测试开始前,一个脚本将在最多40秒内每2秒检查一次API是否正确响应(通过GET /clientes/1/extrato)。因此,请确保所有服务在40秒内能够接收请求!

关于编写测试的重要说明!

模拟中包含了一个超出性能测试常规范围的余额/限额逻辑测试。我这样写只是因为后端Rinha的特殊性。通常情况下,请避免在性能测试中这样做,因为这不是推荐的做法。逻辑测试应该与源代码一起以单元测试或集成测试的形式进行!

后端大战获胜标准

惊喜!:)

测试执行状态跟踪

后端挑战赛部分状态链接

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号