JSON HTTP API用于将一个数值从一个计量单位转换为另一个计量单位

123 阅读3分钟

frinkconv-api

frinkconv-api 提供了一个JSON HTTP API,用于将一个数值从一个测量单位转换到另一个。

在引擎盖下,它使用frinkconv,这是一个围绕Frink的漂亮的CLI工具,用于测量单位的转换。

它的工作原理是在启动时产生一个可配置数量的长期运行的frinkconv REPL进程,然后传入的HTTP请求将从一个池中挑选一个可用的REPL(如果没有可用的REPL,则为块),用它来执行转换。

在我的测试中,它似乎在计算上相当轻巧,但运行更多的 REPL 进程会有内存成本。

每个请求的性能并不差;在所有情况下,使用我的2019年MacBook Pro(x86)来测试:

  • Docker
    • 1000 batch requests of 10 conversions each in 11.466923209s; 87.20735124615936 requests per second, 872.0735124615936 conversions per second
  • 本机
    • 1000 batch requests of 10 conversions each in 4.12123353s; 242.6457983321319 requests per second, 2426.4579833213193 conversions per second

正如你所期望的那样,由于虚拟化,Mac的Docker会慢一些;我敢说,对于基于Linux的机器来说,几乎没有任何成本。

任务

  • 功能性
    • 增加对 "多重转换 "的支持(参考);基本上是把目标值提取为一个元组的过程。
  • 缺陷/技术债务
    • 找到一种方法来固定在Docker构建时下载的frinkconv 的版本。
    • 在尝试转换之前,验证给定的source_unitsdestination_units
      • 如果不这样做,可能会有一些尚未被完全理解的代码注入风险
    • 可能是我正在做的某些REPL输出解析中潜伏的错误。
    • 看一下与Frink更紧密/直接的集成(跳过REPL)。
      • 据推测,这可能会更快/更少的资源负担

使用方法

使用发布的Docker镜像运行

先决条件

运行服务器

docker run --rm -it -p 8080:8080 initialed85/frinkconv-api

使用Docker Compose构建和运行

前提条件

构建和运行服务器

docker compose up --build

本地构建和运行

先决条件

构建服务器

go build -o bin/frinkconv-api cmd/main.go

运行服务器

bin/frinkconv-api -port 8080 -processes 4

通过API进行交互

先决条件

尝试一些单一的转换

# this should succeed
curl -s -X POST -d '{"source_value": 120.0, "source_units": "feet", "destination_units": "metres"}' http://localhost:8080/convert/ | jq
{
  "destination_value": 36.576
}

# this should fail
curl -s -X POST -d '{"source_value": 120.0, "source_units": "apples", "destination_units": "oranges"}' http://localhost:8080/convert/ | jq
{
  "error": "Warning: undefined symbol \"apples\".\nUnknown symbol \"oranges\"\nWarning: undefined symbol \"apples\".\nWarning: undefined symbol \"oranges\".\nUnconvertable expression:\n  120 apples (undefined symbol) -> oranges (undefined symbol)"
}

尝试进行批量转换

# this should succeed and fail
curl -s -X POST -d '[{"source_value": 120.0, "source_units": "feet", "destination_units": "metres"}, {"source_value": 120.0, "source_units": "apples", "destination_units": "oranges"}, {"source_value": 120.0, "source_units": "feet", "destination_units": "metres"}, {"source_value": 120.0, "source_units": "apples", "destination_units": "oranges"}]' http://localhost:8080/batch_convert/ | jq
[
  {
    "destination_value": 36.576
  },
  {
    "error": "Warning: undefined symbol \"apples\".\nUnknown symbol \"oranges\"\nWarning: undefined symbol \"apples\".\nWarning: undefined symbol \"oranges\".\nUnconvertable expression:\n  120 apples (undefined symbol) -> oranges (undefined symbol)"
  },
  {
    "destination_value": 36.576
  },
  {
    "error": "Warning: undefined symbol \"apples\".\nUnknown symbol \"oranges\"\nWarning: undefined symbol \"apples\".\nWarning: undefined symbol \"oranges\".\nUnconvertable expression:\n  120 apples (undefined symbol) -> oranges (undefined symbol)"
  }
]

贫民窟的性能测试

假设你已经有一个运行在8080端口的frinkconv_api 服务器:

go run test/main.go
2022/08/11 10:47:16 1000 batch requests of 10 conversions each in 3.970077757s; 251.88423532431082 requests per second, 2518.8423532431084 conversions per second