彦祖们,这种 API 接口设计有哪些利弊? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
ibegyourpardon
V2EX    程序员

彦祖们,这种 API 接口设计有哪些利弊?

  ibegyourpardon 2021-07-27 10:01:34 +08:00 5646 次点击
这是一个创建于 1536 天前的主题,其中的信息可能已经有所发展或是发生改变。

最近在复刻一些产品做练手,发现了不少新产品的 web api 接口很有意思。两个典型参考对象是 wolai.comtodoist.com

传统上,我们会根据业务需求给不同的业务设计开发出不同的 api 接口出来给前端调用。

比如某个系统叫 V2EX,包含了对帖子的增删改查,我们往往会创建

/article/create
/article/update
/article/delete
/article/get/:id
/article/list/get

等接口。

然后处理分类还有
/category/create
/category/update
等等。

当然其中还有一些可以合并的,具体不一而足,因人而异。

但我最近看到了这样一些接口。使用方法类似于

/article

然后 payload 为

{ "resource_type": "article", "transaction": [{ "requestId": "some kind of uuid" "command":"updateArticle", "args": { "articleId": some int or uuid, "content": "some string", "blahblah": "blahblah" } }] } 

这个 payload 本身不难看懂,其中 transaction 是个数组,可以一次包含多个指令。

这个让我想起来以前我们有的时候开的玩笑,说根本不需要写很多接口,只要一个接口,传不同的参就可以干所有的事。现在看来这个玩笑不仅被人真的这么做了,还给了很完善的事务概念。

但我仍然有些困惑,这样的模式真的很好用吗?

我能想到一些优势,比如前面可以是一个很薄的 controller, 后面随着 args 的不同调用不同的 service 处理。service 可以很轻松的切换版本,不需要担心和前端的对接。队列在后端的应用也是显而易见的。

对前端来说,也不再需要看 N 个接口的文档,大多数接口会统一起来有一套标准,只要定义约定好相关的行为和参数就可以。

但这样的接口调用,是不是本身就太复杂了呢? 我大概想了下,似乎没有看到很明显的收益。我大概看了下相关的前端,有这样一个特性。

比如说列表页,我新增一个内容,传统模式是先 create,然后再获取 list,进行 data 更新。 现在会改成先操作本地 data,直接在 list 里 append,然后再发一个事务描述,告诉后端去做对应的相关操作。

我甚至在某个 app 中遇到过事务失败的问题,然后造成了多端登录的情况下有一个端死活同步不了( Todoist,事务 ID 对不上,死活不能同步数据。)

就想问问各位大佬,这种接口设计除了我自己臆想分析的特征,还有什么别的是我没考虑到的吗?

littlemcdull
    1
littlemcdull  
   2021-07-27 10:12:13 +08:00
我能想到的是这种接口挺适用增量更新的,比如,一段时间后服务端新增了若干条数据记录,有删除,有修改,有新增(比如在另外一个终端 iPad 上登录了同个帐号,进行了一些操作,然后又换了个 iPhone 设备同一个帐号,需要从服务端同步数据)
Morriaty
    2
Morriaty  
   2021-07-27 10:12:16 +08:00
es 的增删改接口 bulk 也是这个设计方式,和传统的 restful api 有啥优劣,我还真感受不出来,都一样
javalaw2010
    3
javalaw2010  
   2021-07-27 10:15:01 +08:00
我个人感觉第二种接口会在应用有离线需求、多端同步的时候使用,比如笔记应用新增一篇文章,你肯定不能因为没有网络而不让用户新增文章,多端同步的时候,A 设备上的操作可能只有部分操作同步到了 B 设备,等到有条件的时候再把剩余的操作同步到 B 设备上,这种情况下第二种的方案会比较方便些。
sudoy
    4
sudoy  
   2021-07-27 10:15:25 +08:00
只能说这操作太骚了,随着项目越来越庞大,这个看起来就很费劲了,不管前后端,维护性和可拓展性就慢慢变差了
zjsxwc
    5
zjsxwc  
   2021-07-27 10:15:49 +08:00
方便一次接口请求,就能完成原先 restful 方式需要 N 次请求的场景。
JerryCha
    6
JerryCha  
   2021-07-27 10:24:25 +08:00
可能它只是个 gayway,真接口隐藏在后面
ibegyourpardon
    7
ibegyourpardon  
OP
   2021-07-27 10:30:00 +08:00
@littlemcdull 其实这个模式我想过,颇有点类似 MySQL 了。
要实现同步数据,一个是传统的模式,拿最终数据。
二个是像这种模式一样,拿所有的操作行为日志,再完整走一次,就可以追回最终数据了。

但我想了下,这种前后端的场景中,走日志的模式代价远比直接获取最终数据高。
ibegyourpardon
    8
ibegyourpardon  
OP
   2021-07-27 10:31:39 +08:00
@javalaw2010 对对对,这个问题我也想过。
我甚至联想到了游戏服务器上,多玩家联网操作的逻辑同步。

但引申来了一个新问题。
我不同端操作先后有别,那我为了保证某种程度的最终一致性,后端除了记录数据,是不是还得记录下来自多个客户端的所有操作,类似 binlog 日志那样。
感觉又增加了存储队列上的额外操作。
dream4ever
    9
dream4ever  
   2021-07-27 10:34:13 +08:00   2
@JerryCha gayway ? gateway ?
intmax2147483647
    10
intmax2147483647  
   2021-07-27 10:38:08 +08:00   1
用后者不如用 GraphQL (也有些区别),用前者不如用 http method 区分不同的接口,写个 /create /get 在 URL 里面显得很多余,并不 RESTFUL
Symo
    11
Symo  
   2021-07-27 10:45:24 +08:00
我觉得至少 GET POST 语义上一定要区分, 但是后端上只是把本应给 uri 做的正则匹配, 变成了对 json decode 之后的某字段的匹配来区分业务, 性能可能略微受影响?
securityCoding
    12
securityCoding  
   2021-07-27 11:05:43 +08:00 via Android
你可以理解为命令模式,现在基本不这样用了
lanlanye
    13
lanlanye  
   2021-07-27 11:24:08 +08:00
好处是没有文档你根本不知道这个接口怎么用,坏处也是没有文档你根本不知道这个接口怎么用……
RESTful 应该也不会写 /create /update 之类的东西
lux182
    14
lux182  
   2021-07-27 11:32:58 +08:00
网关路由,限流等不太好做。其他的其实挺好的
learningman
    15
learningman  
   2021-07-27 11:37:52 +08:00
GraphQL, 请
bthulu
    16
bthulu  
   2021-07-27 11:44:53 +08:00   1
批量操作你的 create/update 接口就不能接收一个数组吗?
把所有接口统一到一个接口, 你文档怎么写?
按你这么想, java 要这么多类, 这么多方法干嘛呢, 就一个 main 类, 一个 main 方法, 方法里传不同的参数不就行了吗? jdkAPI 加起来也就几万到几十万吧, 用一个 int 作为第一个入参, 就可以区分几亿个操作了, 够 jdk 用的了. 以后大家的代码就是这样的, 是不是很简单明了, 一看就懂?
```
Main.main(1, xxxx);
Main.main(16515, xxxx);
Main.main(568, xxxx);
Main.main(35656, xxxx);
Main.main(956, xxxx);
...
```
harde
    17
harde  
   2021-07-27 11:46:04 +08:00
是我精神恍惚了么?早年 Servlet 不就这样么。。。 后来 RESTful 盛行,才慢慢没人这么干了
Macolor21
    18
Macolor21  
   2021-07-27 11:54:34 +08:00
@harde 一部分 java 开发除了大学学了 Servlet 之后,就再没接触过,大多都是基于 Spring 框架封装的东西在开发,早都忘了。另一部分可能压根没深入了解 Serlvet
no1xsyzy
    19
no1xsyzy  
   2021-07-27 11:56:37 +08:00
在说什么
这不就是一个变形了的 JSONRPC ?

状态模式和日志模式的代价难说,如果编辑是稀疏的,那显然日志模式代价小得多。
奇怪的优势是:日志模式可以减少需要解决的冲突。
apifox
    20
apifox  
   2021-07-27 12:31:20 +08:00
用 GraphQL 不香吗?
gfreezy
    21
gfreezy  
   2021-07-27 12:31:21 +08:00
这看起来像是 rpc 框架生成的。实际写的可能是类似 gprc 的 proto 文件,只是传输协议用的 json
Building
    22
Building  
   2021-07-27 12:34:41 +08:00 via iPhone
一个本地路由。
一个服务器路由。
Building
    23
Building  
   2021-07-27 12:39:59 +08:00 via iPhone
以前用 php 生成模版的时候,路由就已经绑定在按钮上了,现在很多项目都不用后端生成 UI 了,直接 js 获取数据再由前端渲染 UI,这样后端就不需要再绑定路由了,所以一个入口就可以。
harryhao
    24
harryhao  
   2021-07-27 13:04:15 +08:00
设置不同接口方便路由,比如不同接口的请求量、认证安全级别可能不同
whajcf
    25
whajcf  
   2021-07-27 13:33:43 +08:00
这个好眼熟.. 然后我想到个我目前在用的一个场景: IoT 通信协议的编解码,报文根据不同的功能码携带对应的指令数据...
waibunleung
    26
waibunleung  
   2021-07-27 13:40:43 +08:00
我感觉有点像 redis 的 pipeline 模式,管道式执行请求逻辑,一定程度上减少了接口的请求量,还能臆想到的就是能根据 command 来判断哪些 command 是可以异步 /并发执行的,哪些需要同步执行
jmyz0455
    27
jmyz0455  
   2021-07-27 13:50:58 +08:00
这种设计我还真没见过。
wolfie
    28
wolfie  
   2021-07-27 13:51:57 +08:00
wolai 之前抄袭道歉后 又上线了吗。
weichengwu
    29
weichengwu  
   2021-07-27 14:03:14 +08:00   1
@wolfie #28 wolai 从来没道歉过吧?记得之前有个叫什么舟的抄袭道歉下架了
bz5314520
    30
bz5314520  
   2021-07-27 14:24:31 +08:00
粗接口可以减少网络往返 ,接口设计粒度的太细就会导致业务逻辑散布到客户端,业务流交给了客户端控制。而且这也可能导致业务域不一致 比如一个上传文章 ,文章标签是必须的 ,你却把 api 拆成 上传文章再附加标签。具体如何抉择看业务,也是自身工程实践考验。软件哲学~~
111111111111
    31
111111111111  
   2021-07-27 15:05:05 +08:00
很自然的想到了 GraphQL,JSONRPC 啊什么的。。
karloku
    32
karloku  
   2021-07-27 16:33:16 +08:00
api 的 uri 能拆就拆, accesslog 的收集分析现成工具多, 好统计好分析
用这种单 endpoint 的 rpc 风格就得自己把监控收集分析都定制一套.
好处大概是比较容易配置新的行为模板, 方便在客户端那边生成按钮.
charlie21
    33
charlie21  
   2021-07-27 19:04:55 +08:00
web 开发中,有没有后端完全作为接口提供数据,转发请求等操作由前端 html+js 实现的例子
https://www.zhihu.com/question/21460500
2013 年发的帖子,那时候把它称为 重前端应用
关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     898 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 26ms UTC 20:47 PVG 04:47 LAX 13:47 JFK 16:47
Do have faith in what you're doing.
ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86