如何做好一个随机图片api
随机图片api是什么
随机图片 API 是一种可以返回随机图片的接口,通常用于网站的背景图、头像等。
一个随机图 API,每次请求都返回不同的图片。从流程上来说,需要有一个图片库,然后通过 API 端点随机返回其中一张图片。
一个最简单的,最直接的架构如下
或者返回 URL,图片资源托管在其他地方:
鉴于国内高昂的带宽成本,第一种直接返回图片的方式 在实际应用中并不常见,更多时候是使用第二种方式——将图片存储在 CDN 或对象存储中,然后通过 API 返回图片的 URL,客户端再通过 URL 去获取图片。同时直接返回方式的随机抽取逻辑和图片读取逻辑都在服务器端,对于大图片库来说,会消耗较多的服务器 CPU 和带宽资源。
那么这就是我们引入第二个问题:如何保证 API 的快速、高清、稳定?
现有图片API分析
多个API测试结果
随机图片 API 在网络上已经有很多成熟实现和开源项目,简直是浩如烟海,有站点记录一些随机图 API 的地址 =w=
我们来小小测试一下,浅浅测试几个 API,各测试 22 次,间隔 1 秒,去掉最高最低取平均,汇总如下:
| API | 总耗时 (ms) | 302 耗时 (ms) | 图片耗时 (ms) | 平均大小 (KB) | 平均分辨率 | 网络 | 稳定性 |
|---|---|---|---|---|---|---|---|
| 栗次元 | 775.75 | 361.79 | 412.68 | 544.36 | 1786 x 1041 ~ 8000 x 4464 | 腾讯云 EdgeOne | 文件大小/分辨率波动极大 |
| LoliAPI | 924.69 | 375.62 | 547.74 | 734.5 | 1920 x 1080 ~ 7680 x 4320 | 腾讯云 EdgeOne | 分辨率集中在 1920x1080,大小波动中等 |
| 樱花API | 3306.73 | 直接返回无302 | 3306.73 | 908.41 | 1920 x 1080 ~ 2048 x 1152 | 新浪图片 + 百度 | 直接返回,速度慢 |
| 夜轻 Blog | 981.58 | 294.47 | 687.10 | 1588.68 | 1228 x 868 ~ 9000 x 5039 | 腾讯云 EdgeOne | 302 较快,但图片体积大,格式混杂 |
| 本站API | 716.61 | 214.98 | 501.63 | 614.73 | 2455 x 1706 ~ 4659 x 2160 | 腾讯云 EdgeOne / 阿里云 ESA 混合 | 302 最快,AVIF 格式 |
| 东方Project | 1076.81 | 323.04 | 753.77 | 164.34 | 1200 x 804 ~ 4000 x 3000 | 日本东京单服务器直连 | WebP 格式 |
点击查看 栗次元 22次原始测试数据
| 次数 | 总耗时 (ms) | 302 耗时 (ms) | 图片耗时 (ms) | 格式 | 大小 (KB) | 分辨率 |
|---|---|---|---|---|---|---|
| 1 | 981.23 | 432.20 | 549.02 | webp | 1529.78 | 4936 x 2515 |
| 2 | 674.35 | 388.14 | 286.21 | webp | 173.69 | 2008 x 1080 |
| 3 | 796.11 | 366.39 | 429.72 | webp | 120.10 | 2000 x 1178 |
| 4 | 689.48 | 408.41 | 281.07 | webp | 356.01 | 3840 x 2160 |
| 5 | 803.04 | 399.46 | 403.58 | webp | 794.84 | 4608 x 2592 |
| 6 | 721.35 | 339.07 | 382.28 | webp | 245.94 | 2560 x 1440 |
| 7 | 654.65 | 357.60 | 297.05 | webp | 194.15 | 4096 x 2658 |
| 8 | 666.20 | 327.46 | 338.75 | webp | 672.06 | 3800 x 2136 |
| 9 | 634.71 | 340.83 | 293.88 | webp | 232.82 | 2560 x 1809 |
| 10 | 817.93 | 326.90 | 491.03 | webp | 464.44 | 2480 x 1754 |
| 11 | 746.79 | 343.15 | 403.64 | webp | 802.89 | 5760 x 3240 |
| 12 | 630.67 | 331.89 | 298.78 | webp | 245.94 | 2560 x 1440 |
| 13 | 681.07 | 365.64 | 315.43 | webp | 329.47 | 3265 x 1837 |
| 14 | 719.51 | 395.35 | 324.17 | webp | 346.53 | 4495 x 1041 |
| 15 | 728.98 | 363.30 | 365.68 | webp | 106.49 | 2500 x 1548 |
| 16 | 702.79 | 375.55 | 327.24 | webp | 566.39 | 3075 x 2048 |
| 17 | 1419.38 | 378.18 | 1041.20 | webp | 1349.94 | 4000 x 2667 |
| 18 | 722.48 | 341.03 | 381.45 | webp | 435.62 | 4608 x 3072 |
| 19 | 1361.95 | 337.25 | 1024.70 | webp | 4093.51 | 3840 x 2160 |
| 20 | 784.11 | 321.10 | 463.01 | webp | 1235.90 | 8000 x 4464 |
| 21 | 914.97 | 347.89 | 567.09 | webp | 654.52 | 3949 x 2170 |
| 22 | 713.36 | 402.40 | 310.96 | webp | 136.21 | 1786 x 1248 |
| 平均(去高低) | 775.75 | 361.79 | 412.68 | - | 544.36 | - |
点击查看 LoliAPI 22次原始测试数据
| 次数 | 总耗时 (ms) | 302 耗时 (ms) | 图片耗时 (ms) | 格式 | 大小 (KB) | 分辨率 |
|---|---|---|---|---|---|---|
| 1 | 921.38 | 378.70 | 542.68 | webp | 694.36 | 1920 x 1080 |
| 2 | 1027.19 | 348.96 | 678.23 | webp | 513.47 | 1920 x 1080 |
| 3 | 675.71 | 355.77 | 319.94 | webp | 523.20 | 1920 x 1080 |
| 4 | 698.66 | 368.88 | 329.78 | webp | 158.05 | 3000 x 1815 |
| 5 | 917.37 | 343.50 | 573.87 | webp | 137.84 | 2367 x 1540 |
| 6 | 728.38 | 368.14 | 360.23 | webp | 679.46 | 1920 x 1080 |
| 7 | 941.48 | 384.27 | 557.21 | webp | 1626.53 | 7680 x 4320 |
| 8 | 1032.88 | 392.63 | 640.26 | webp | 1060.73 | 2048 x 1152 |
| 9 | 816.60 | 369.54 | 447.05 | webp | 333.14 | 3600 x 2100 |
| 10 | 788.42 | 350.10 | 438.32 | webp | 1176.20 | 3763 x 1972 |
| 11 | 775.60 | 397.94 | 377.66 | webp | 645.02 | 1920 x 1080 |
| 12 | 819.66 | 426.31 | 393.35 | webp | 627.72 | 1920 x 1080 |
| 13 | 919.94 | 397.50 | 522.44 | webp | 275.50 | 1920 x 1200 |
| 14 | 967.21 | 384.03 | 583.18 | webp | 519.84 | 1920 x 1080 |
| 15 | 1845.19 | 367.75 | 1477.44 | webp | 3698.94 | 4800 x 2700 |
| 16 | 926.40 | 407.22 | 519.18 | webp | 425.94 | 2048 x 1152 |
| 17 | 1306.89 | 371.49 | 935.40 | webp | 4321.09 | 3800 x 2193 |
| 18 | 1769.44 | 384.44 | 1385.00 | webp | 311.36 | 1920 x 1200 |
| 19 | 955.23 | 406.15 | 549.07 | webp | 376.65 | 1920 x 1080 |
| 20 | 811.14 | 333.21 | 477.93 | webp | 358.03 | 1920 x 1080 |
| 21 | 681.64 | 371.02 | 310.62 | webp | 259.90 | 1920 x 1080 |
| 22 | 688.38 | 364.29 | 324.09 | webp | 425.96 | 2800 x 1680 |
| 平均(去高低) | 924.69 | 375.62 | 547.74 | - | 734.5 | - |
点击查看 樱花API 22次原始测试数据
| 次数 | 总耗时 (ms) | 302 耗时 (ms) | 图片耗时 (ms) | 格式 | 大小 (KB) | 分辨率 |
|---|---|---|---|---|---|---|
| 1 | 2169.88 | 0.00 | 2169.88 | jpg | 528.61 | 1920 x 1080 |
| 2 | 2427.12 | 0.00 | 2427.12 | jpg | 969.02 | 1920 x 1080 |
| 4 | 2440.28 | 0.00 | 2440.28 | jpg | 996.06 | 1920 x 1080 |
| 5 | 2455.69 | 0.00 | 2455.69 | jpg | 844.58 | 1920 x 1080 |
| 6 | 2617.61 | 0.00 | 2617.61 | jpg | 972.44 | 1920 x 1080 |
| 7 | 1985.79 | 0.00 | 1985.79 | jpg | 716.33 | 1920 x 1080 |
| 8 | 2009.12 | 0.00 | 2009.12 | jpg | 643.61 | 1920 x 1080 |
| 9 | 2532.53 | 0.00 | 2532.53 | jpg | 1202.27 | 1920 x 1080 |
| 10 | 1774.98 | 0.00 | 1774.98 | jpg | 442.60 | 2048 x 1152 |
| 11 | 12864.04 | 0.00 | 12864.04 | jpg | 1505.49 | 1920 x 1080 |
| 12 | 2089.21 | 0.00 | 2089.21 | jpg | 805.05 | 1920 x 1080 |
| 13 | 8964.69 | 0.00 | 8964.69 | jpg | 1238.41 | 2048 x 1152 |
| 14 | 1873.94 | 0.00 | 1873.94 | jpg | 370.74 | 1920 x 1080 |
| 15 | 2386.17 | 0.00 | 2386.17 | jpg | 716.36 | 2048 x 1152 |
| 16 | 1569.79 | 0.00 | 1569.79 | jpg | 1208.70 | 1920 x 1080 |
| 17 | 5893.84 | 0.00 | 5893.84 | jpg | 711.35 | 1920 x 1080 |
| 18 | 3627.94 | 0.00 | 3627.94 | jpg | 1713.32 | 2048 x 1152 |
| 19 | 2559.84 | 0.00 | 2559.84 | jpg | 996.06 | 1920 x 1080 |
| 20 | 10340.63 | 0.00 | 10340.63 | jpg | 1193.50 | 1920 x 1080 |
| 21 | 2611.45 | 0.00 | 2611.45 | jpg | 1198.52 | 2048 x 1152 |
| 22 | 2067.25 | 0.00 | 2067.25 | jpg | 256.99 | 1920 x 1080 |
| 平均(去高低) | 3306.73 | 0.0 | 3306.73 | - | 908.41 | - |
点击查看 夜轻 Blog 22次原始测试数据
| 次数 | 总耗时 (ms) | 302 耗时 (ms) | 图片耗时 (ms) | 格式 | 大小 (KB) | 分辨率 |
|---|---|---|---|---|---|---|
| 1 | 984.98 | 295.50 | 689.49 | jpg | 507.14 | 1920 x 1080 |
| 2 | 986.73 | 296.02 | 690.71 | jpg | 1214.92 | 4552 x 2560 |
| 3 | 948.57 | 284.57 | 664.00 | jpg | 1479.03 | 2560 x 1440 |
| 4 | 901.43 | 270.43 | 631.00 | webp | 1030.74 | 3675 x 2160 |
| 5 | 916.08 | 274.82 | 641.26 | jpg | 1139.30 | 9000 x 5039 |
| 6 | 1525.26 | 457.58 | 1067.68 | jpg | 4534.13 | 3000 x 1753 |
| 7 | 784.15 | 235.24 | 548.90 | jpg | 908.65 | 3500 x 2475 |
| 8 | 966.04 | 289.81 | 676.23 | jpg | 1201.54 | 2560 x 1440 |
| 9 | 901.77 | 270.53 | 631.24 | jpg | 992.94 | 2560 x 1553 |
| 10 | 1259.40 | 377.82 | 881.58 | jpg | 2963.49 | 3440 x 1440 |
| 11 | 1786.97 | 536.09 | 1250.88 | png | 6059.66 | 4000 x 2250 |
| 12 | 778.98 | 233.70 | 545.29 | jpg | 521.86 | 2560 x 1282 |
| 13 | 1055.70 | 316.71 | 738.99 | png | 2174.52 | 1756 x 1239 |
| 14 | 934.82 | 280.45 | 654.37 | jpg | 1185.00 | 3508 x 2480 |
| 15 | 805.22 | 241.57 | 563.65 | jpg | 1214.92 | 4552 x 2560 |
| 16 | 710.57 | 213.17 | 497.40 | jpg | 521.86 | 2560 x 1282 |
| 17 | 688.55 | 206.57 | 481.99 | jpg | 343.47 | 1228 x 868 |
| 18 | 1193.69 | 358.11 | 835.58 | jpg | 2923.50 | 3508 x 2480 |
| 19 | 1171.85 | 351.55 | 820.29 | jpg | 2616.58 | 4439 x 2392 |
| 20 | 908.22 | 272.47 | 635.76 | jpg | 1417.73 | 3300 x 1856 |
| 21 | 673.85 | 202.15 | 471.69 | jpg | 447.21 | 1786 x 1248 |
| 22 | 1209.49 | 362.85 | 846.64 | png | 2778.56 | 3200 x 1800 |
| 平均(去高低) | 981.58 | 294.47 | 687.10 | - | 1588.68 | - |
点击查看 本站API 22次原始测试数据
| 次数 | 总耗时 (ms) | 302 耗时 (ms) | 图片耗时 (ms) | 格式 | 大小 (KB) | 分辨率 |
|---|---|---|---|---|---|---|
| 1 | 883.37 | 265.01 | 618.36 | avif | 746.68 | 3728 x 2160 |
| 2 | 638.16 | 191.45 | 446.71 | avif | 332.66 | 3210 x 1812 |
| 3 | 751.17 | 225.35 | 525.82 | avif | 475.59 | 2560 x 1440 |
| 4 | 751.52 | 225.46 | 526.07 | avif | 718.16 | 3055 x 2160 |
| 5 | 753.27 | 225.98 | 527.29 | avif | 592.23 | 3840 x 2160 |
| 6 | 677.78 | 203.33 | 474.45 | avif | 442.02 | 3632 x 2160 |
| 7 | 942.02 | 282.61 | 659.41 | avif | 368.96 | 2877 x 2160 |
| 8 | 847.60 | 254.28 | 593.32 | avif | 517.21 | 2880 x 2160 |
| 9 | 624.76 | 187.43 | 437.33 | avif | 307.16 | 2811 x 2160 |
| 10 | 770.82 | 231.24 | 539.57 | avif | 846.45 | 2788 x 1782 |
| 11 | 621.16 | 186.35 | 434.82 | avif | 895.71 | 2591 x 2160 |
| 12 | 724.33 | 217.30 | 507.03 | avif | 444.40 | 3580 x 2160 |
| 13 | 844.85 | 253.46 | 591.40 | avif | 386.96 | 3049 x 2160 |
| 14 | 831.29 | 249.39 | 581.90 | avif | 372.70 | 2455 x 1706 |
| 15 | 674.02 | 202.21 | 471.81 | avif | 653.75 | 3556 x 2000 |
| 16 | 622.62 | 186.79 | 435.84 | avif | 382.88 | 2756 x 2036 |
| 17 | 607.81 | 182.34 | 425.47 | avif | 908.79 | 3438 x 2160 |
| 18 | 647.08 | 194.12 | 452.96 | avif | 1007.10 | 2880 x 2160 |
| 19 | 657.89 | 197.37 | 460.53 | avif | 1021.04 | 4659 x 2160 |
| 20 | 758.91 | 227.67 | 531.24 | avif | 776.08 | 3840 x 2160 |
| 21 | 643.75 | 193.12 | 450.62 | avif | 680.23 | 3283 x 2160 |
| 22 | 580.97 | 174.29 | 406.68 | avif | 746.13 | 2932 x 1694 |
| 平均(去高低) | 716.61 | 214.98 | 501.63 | - | 614.73 | - |
点击查看 东方Project 22次原始测试数据
| 次数 | 总耗时 (ms) | 302 耗时 (ms) | 图片耗时 (ms) | 格式 | 大小 (KB) | 分辨率 |
|---|---|---|---|---|---|---|
| 1 | 1039.05 | 311.71 | 727.33 | webp | 93.24 | 1583 x 1117 |
| 2 | 1110.60 | 333.18 | 777.42 | webp | 189.93 | 2143 x 999 |
| 3 | 1122.66 | 336.80 | 785.86 | webp | 186.64 | 1800 x 1525 |
| 4 | 1006.19 | 301.86 | 704.33 | webp | 79.64 | 1400 x 885 |
| 5 | 1111.17 | 333.35 | 777.82 | webp | 179.81 | 2000 x 2000 |
| 6 | 1051.61 | 315.48 | 736.13 | webp | 168.86 | 1600 x 1200 |
| 7 | 1204.79 | 361.44 | 843.35 | webp | 561.93 | 2850 x 2000 |
| 8 | 1071.14 | 321.34 | 749.80 | webp | 137.11 | 1411 x 1000 |
| 9 | 1057.06 | 317.12 | 739.94 | webp | 111.18 | 1600 x 1131 |
| 10 | 1053.82 | 316.15 | 737.67 | webp | 132.99 | 1600 x 1200 |
| 11 | 1069.40 | 320.82 | 748.58 | webp | 211.68 | 3500 x 2458 |
| 12 | 1130.39 | 339.12 | 791.27 | webp | 128.86 | 1500 x 1100 |
| 13 | 1035.21 | 310.56 | 724.65 | webp | 131.66 | 1200 x 1200 |
| 14 | 4008.75 | 1202.63 | 2806.13 | webp | 616.95 | 3600 x 2242 |
| 15 | 985.16 | 295.55 | 689.61 | webp | 53.54 | 1600 x 1200 |
| 16 | 1134.10 | 340.23 | 793.87 | webp | 112.52 | 1318 x 1040 |
| 17 | 974.56 | 292.37 | 682.19 | webp | 82.40 | 1200 x 804 |
| 18 | 1092.27 | 327.68 | 764.59 | webp | 219.26 | 4000 x 3000 |
| 19 | 1102.21 | 330.66 | 771.54 | webp | 119.37 | 1350 x 750 |
| 20 | 1119.08 | 335.73 | 783.36 | webp | 220.92 | 3508 x 2480 |
| 21 | 1005.16 | 301.55 | 703.61 | webp | 104.16 | 2000 x 1414 |
| 22 | 1035.19 | 310.56 | 724.63 | webp | 114.70 | 1600 x 1200 |
| 平均(去高低) | 1076.81 | 323.04 | 753.77 | - | 164.34 | - |
从数据可以看出:
- 本站API 总耗时平均约 717 ms,速度最快,302 响应仅 215 ms(所有 API 中最快),格式统一为 AVIF
- 栗次元 总耗时平均约 776 ms,速度第二,但文件大小和分辨率波动极大
- 东方Project 总耗时平均约 1077 ms,302 中等(323 ms),但图片加载较慢(754 ms),格式统一为 WebP,平均体积仅 164 KB(所有 API 中最小),但第 14 次异常缓慢(4 秒),应该是跨境网络问题
- LoliAPI 总耗时平均约 925 ms,速度中等,分辨率集中在 1920 x 1080
- 夜轻 Blog 总耗时平均约 982 ms,302 响应较快(294 ms),但图片加载慢(687 ms),且平均体积高达 1.59 MB,格式混杂(jpg / webp / png)
- 樱花API 总耗时平均约 3307 ms,速度慢且极不稳定(1 次超时,多次 3~12 秒),直接返回 jpg 导致服务器带宽压力大
发现使用 302 跳转方式的 API 显著优于直接返回类,因为上述几个 API 的 302 通常由部署在 CDN 边缘的 Pages / Workers 完成,响应时间极短,到用户的网络延迟最低。虽然图片资源也要回源才能加载,但整体延迟仍然较低。
更何况使用直接返回方式的 API 还是用的 世界上最好的语言 PHP,从请求到返回图片不知道要几十次用户态拷贝,不慢就怪了。
那么,这些延迟数字背后有没有理论支撑?用户到底能接受多久的等待?我查证了一下 HCI 领域的延迟感知研究,整理如下:
延迟等级评估
| 等级 | 总延迟 | 用户感知 | 行为影响 | 依据(已核实) |
|---|---|---|---|---|
| 极速 | 300–600 ms | 即时,无等待感 | 满意度最高 | Nielsen 1993:<1s 用户思路不中断(网页通用阈值,最近似参照) |
| 良好 | 600 ms–1.2 s | 轻微感知,流畅 | 注意力未被打断 | Nah 2004:Web 对象容忍上限约 2 s;此区间在容忍范围内 |
| 可接受 | 1.2–2 s | 明显等待感 | 开始分心,但不放弃 | Nah 2004:2 s 是可容忍等待上限;Ramsay et al. 1998:延迟影响页面感知质量 |
| 偏慢 | 2–4 s | 明显挫败感 | 移动端放弃率上升 | Google/SOASTA 2017:>3 s 跳出率 53%;Ramsay 1998:延迟越长页面越被视为无趣 |
| 很慢 | 4–8 s | 认为出错/崩溃 | 大量放弃,信任受损 | Nielsen 1993:>10 s 用户离开(工程估算:此区间已触发放弃行为) |
| 不可用 | >8 s | 视为服务崩溃 | 几乎全部放弃 | Nielsen 1993 10 s 极限;需 fallback,否则违反基本可用性原则 |
已核实来源
- Ramsay, Barbesi & Preece (1998) — Interacting with Computers, 10(1), 77–86.
doi.org/10.1016/S0953-5438(97)00019-2· 测试 2 s–数十秒延迟对用户页面感知的影响,含图片资源延迟。 - Nah, F.F.H. (2004) — Behaviour and Information Technology, 23(3), 153–163.
doi.org/10.1080/01449290410001669914· Web 对象可容忍等待时间约 2 s。 - Nielsen, J. (1993) — Usability Engineering, Academic Press. 0.1 s / 1 s / 10 s 三级响应时间阈值,HCI 基准。无 DOI(书籍)。
- Google/SOASTA (2017) — “The State of Online Retail Performance.” 行业报告,非学术论文。
thinkwithgoogle.com
重要说明
- 以上论文研究对象均为网页整体加载,不存在专门针对”随机图片 API 端到端延迟”的学术论文。本表延迟数值由真实 302 跳转链路物理计算 + 上述研究的用户感知阈值推导而来,非直接引用数据。在正式文档中引用时,建议注明”参考自 Nah 2004 / Ramsay 1998,结合工程测量估算”。
最终方案
根据以上数据和研究:
直接返回的架构虽然理论上一次请求复用连接,但是随机和静态资源返回都在一个服务器上,一旦 QPS 大于 10,在国内这个带宽比金子还贵的情况下,想必不那么经济。
有没有不吃经济的打法呢?还是边缘函数(Pages / Workers)又快又好,稳定性还高,总不可能阿里云腾讯云的服务器都同时挂掉吧。虽然比直接返回的架构多出来一次跨域握手耗时(其实这个也可以通过路径代理解决),但是各个方面还是更好滴。
那么问题来了,具体该怎么设计呢?
首先我们应该知道一个好的图片 API 应该做到什么:当然是清晰、快速、稳定。那么为了实现这三个目标,我们需要尽可能把请求在边缘节点就处理了,这样可以减少网络延迟,提高响应速度。图片资源虽然需要源站对象存储,但是可以开启 CDN 的缓存,也能从边缘节点获取,这样就大大减少了网络延迟。同时我们还需要尽可能压缩图片大小,但是又不能损失太多画质——那么就该请出一个神奇的图片格式:AVIF。
图片格式对比
| 格式 | 压缩类型 | 透明 | 动画 | 相对大小 | 浏览器支持 | 编码速度 | 最佳场景 |
|---|---|---|---|---|---|---|---|
JPG | 有损 | ✗ | ✗ | 100% | 100% | 极快 | 兼容旧浏览器 |
WebP | 有损 / 无损 | ✓ | ✓ | ~60% | 97%+ | 快 | 照片 / API 首选 |
PNG | 无损 | ✓ | ✗ | ~300% | 100% | 中等 | 图标 / 截图 |
AVIF | 有损 / 无损 | ✓ | ✓ | ~45% | ~93% | 慢(5–20× WebP) | 预生成图库 |
随机图片 API 推荐策略
既然图片库是静态的,最佳做法是预生成 AVIF 后直接返回:
- 同质量下体积只有 JPG 的 40–50%,WebP 的 70%
- 解码速度接近 WebP,现代浏览器支持率已达 93%+
- 边缘节点只负责 302 跳转,零实时转码压力
分辨率选择
同时还有个问题,上述测试 API 有的图片返回十几个 MB、8K 分辨率,这是完全没有必要的——都 2026 年了,1080p 的图片虽然不能满足要求,我们的 API 还是应该尽量返回 2K 以上的图片。但太高了除了浪费带宽以外毫无用处,综上所述,返回 2K–4K 分辨率的 AVIF 格式图片 是最经济且效果最好的打法。
推荐架构
边缘 Pages 函数负责 302 跳转,图片资源放在 nginx 静态站点并套 CDN,整体链路如下:
各层职责
| 层级 | 组件 | 职责 |
|---|---|---|
| 接入层 | 边缘 Pages Functions | 接收 API 请求,从预生成列表随机选择,返回 302 |
| 逻辑层 | image-list.ts | 构建时生成,运行时只读,避免文件系统访问 |
| 存储层 | nginx 静态站点 + CDN | 托管 AVIF 图片,边缘缓存,就近返回 |
为什么这样设计
- 302 在边缘完成:用户到边缘节点的 RTT 最低,随机选择逻辑只消耗几 KB 内存和几 ms CPU
- 图片走 CDN:AVIF 预生成后静态托管,CDN 边缘缓存命中率极高,图片加载时间和带宽成本都最低
- 零实时转码:所有格式转换在构建时完成,运行时零压力
- 可扩展:新增分类只需在
config.ts添加路径映射,重新构建部署即可
成功上线
基于以上的架构描述,我自己写了一个随机图片 API 喵。
仓库
API 地址
境内使用 ESA / EdgeOne 混合加速,境外使用 Cloudflare 加速。
评论区