V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bdbai
V2EX  ›  程序员

有关 Restful API 的疑问

  •  
  •   bdbai ·
    bdbai · 2015-09-03 08:39:33 +08:00 via iPhone · 4823 次点击
    这是一个创建于 3355 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如说有个获取帖子的 API ,应不应该把发布者的用户名、头像地址一起传回?还是只留个用户 ID 即可?
    33 条回复    2015-09-05 23:15:35 +08:00
    ljbha007
        1
    ljbha007  
       2015-09-03 08:50:56 +08:00
    一般要一起回传 节约流量
    zyx89513
        2
    zyx89513  
       2015-09-03 08:58:03 +08:00
    尽量在一次请求完成, 多次请求网络延时比较大
    minbaby
        3
    minbaby  
       2015-09-03 09:18:18 +08:00 via iPhone
    一般来讲,从逻辑上区分而不是从节省流量和时间上区分,逻辑上讲这些是有直接关联的所以更适合放在一起,如果处于其他考虑分开也是可以接受的
    gevin
        4
    gevin  
       2015-09-03 09:21:12 +08:00
    同意楼上,逻辑合理是第一位的
    bdbai
        5
    bdbai  
    OP
       2015-09-03 09:24:04 +08:00 via iPhone   ❤️ 1
    @ljbha007 为什么一起回传会节约?如果用户信息会缓存呢?
    @minbaby @zyx89513 那么就一起传回咯
    ljbha007
        6
    ljbha007  
       2015-09-03 09:29:01 +08:00
    @bdbai
    HTTP 请求头有开销呀
    还有多次请求对服务器的压力也会更大一些 同时加载速度也会有影响
    loading
        7
    loading  
       2015-09-03 09:41:48 +08:00 via iPhone
    如果不一次传回,你下一步不就要获取这些信息了?
    回帖必然要带用户信息吧,不然你后续如何区分?所以就一起回传了。


    你应该不会是指用户的头像数据吧?你要压成 base64 传?传个地址就行,这样浏览器才能使用缓存!
    learnshare
        8
    learnshare  
       2015-09-03 09:42:26 +08:00
    客户端用的话,一般要一次传回相关数据,否则让客户端多次查询,是很慢的。
    loading
        9
    loading  
       2015-09-03 09:43:54 +08:00 via iPhone
    如果你直流 id 号,你可以试下在这个 api ,每个 id 请求一次,顺便也能做个压力测试了…看你服务器能不能挡住,每个帖子 10 个回复,也就 10 个请求而已…
    bdbai
        10
    bdbai  
    OP
       2015-09-03 10:45:49 +08:00 via iPhone
    @ljbha007 其实加载倒问题不大 各种动画能糊弄一下
    @loading 主要是考虑到客户端缓存可以灵活一点 头像当然是地址咯
    @loading 我不会说我用 SAE 的
    iyangyuan
        11
    iyangyuan  
       2015-09-03 11:55:25 +08:00 via iPhone
    这得看具体需求,如果盲目一次传回,不仅会造成业务逻辑上的耦合,而且造成资源浪费,又违反按需加载的思想。但如果有接下来必须用到的关联数据,那就没必要分多次请求了。
    loading
        12
    loading  
       2015-09-03 11:58:31 +08:00 via iPhone
    如果你是全端,那你还不合格才会问这个问题!
    如果你是后端,问下你前端人员的意见!
    qiayue
        13
    qiayue  
       2015-09-03 12:11:46 +08:00 via Android
    需要什么就传回什么,比如帖子里需要显示发帖者的昵称头像,那么就只返回用户的这两个数据,用户的其他数据就没必要返回了
    jeansfish
        14
    jeansfish  
       2015-09-03 12:14:57 +08:00
    缓存就让客户端去判断, api 给出来就行了
    bdbai
        15
    bdbai  
    OP
       2015-09-03 12:56:29 +08:00 via iPhone
    @iyangyuan @qiayue @jeansfish 明白了
    @loading 虽然只是后端,不过经验严重缺乏。还请多指教。
    msg7086
        16
    msg7086  
       2015-09-04 04:27:16 +08:00   ❤️ 1
    @loading 每个 ID 请求一次?这是什么新鲜的逻辑?是不是 SQL 也只能一次请求和返回一条数据了?

    @bdbai 具体怎么做要看具体情况的。
    比如说你前端程序是不是 SPA ,如果是的话, SPA 内部可以缓存数据,每次只要返回差值即可。
    多次请求也就现在开销大点,然而现在的 SPDY 和以后的 HTTP/2 都会压缩报头和流复用,多个请求回复和单个合并的请求回复并不会有想象当中的那么大。

    另外,像你这个返回帖子数据的 API ,根本不用等用户数据下载完就可以显示帖子了。等用户数据下载完了再把更新后的数据写入页面即可。

    不过呢,如果你在创业公司的话,还是怎么简单怎么来,只要后端做好模块化,易于拆分的话,就算是合并输出也无所谓。毕竟初期快速迭代出产品比什么都重要。
    loading
        17
    loading  
       2015-09-04 06:27:11 +08:00 via iPhone
    @msg7086 希望你看清楚一点,我是说一个不合理的 api 设置造成的问题。
    bdbai
        18
    bdbai  
    OP
       2015-09-04 08:31:13 +08:00 via iPhone
    @msg7086 loading 说的是单独请求用户信息对服务器的压力...
    确实是 SPA ,还有手机 app 。因为是在 SAE 上的,所以 SPDY 和 HTTP/2 可能比较麻烦。等以后移植了再说。
    多谢指点。
    msg7086
        19
    msg7086  
       2015-09-04 08:47:39 +08:00
    @loading 看了半天没看明白你什么意思。
    1 个帖子 10 个回复, 10 个 id 拿用户数据也就 1 个请求就足够了,为何要去测什么 10 个请求。
    bdbai
        20
    bdbai  
    OP
       2015-09-04 10:31:22 +08:00 via iPhone
    @msg7086 你说的是"批量获取用户信息"?
    msg7086
        21
    msg7086  
       2015-09-04 10:35:34 +08:00
    @bdbai 是啊。这就是典型的 N+1 问题优化。 1 个请求+N 个子请求,优化成 1+1 一共 2 个请求。
    atom
        22
    atom  
       2015-09-04 11:02:24 +08:00
    孤立看问题的撕逼钓鱼贴 :)
    response 的 size 不是过大的时候,一次请求“就近”返回信息,减少连接数,效果是很客观的。
    没做过 APP ,单纯从桌面浏览器来看,连接数过多页面加载的效果非常差,而且 js 的调度,一般认为是个单线程的东西。
    loading
        23
    loading  
       2015-09-04 11:03:00 +08:00 via iPhone
    @msg7086 其实你看懂了,我为了说明楼主这个只传 id 的缺陷,就按没合并的情况下说的。

    楼主这个就是先给 id 然后又至少根据 id 查一次的情况,这个明显就应该合并!
    bdbai
        24
    bdbai  
    OP
       2015-09-04 13:27:05 +08:00 via iPhone
    @msg7086 @loading 好的好的 合并合并:)
    @atom 本无意钓鱼...
    msg7086
        25
    msg7086  
       2015-09-04 13:33:03 +08:00
    @loading
    @bdbai
    我反正觉得应该分开。
    loading
        26
    loading  
       2015-09-04 13:59:31 +08:00 via iPhone
    @msg7086 我发出以上内容的出发点是:楼主说的 id ,我理解是 id 号~因为我看到楼主还说了用户名这个东西,所以我就单纯地理解为 id 是个数字,也就是我们说的 uid
    loading
        27
    loading  
       2015-09-04 14:04:05 +08:00 via iPhone
    @loading 因为我觉得应该不会给用户一个数字,必须要把它变成用户名,如果只是这个问题,我的观点就是合并,在 sql 时就是一个 join 的问题,毕竟如果不返回,马上就必须来个请求找用户名了。

    这是我回答这个问题的过程。


    也许跑偏了太多~
    msg7086
        28
    msg7086  
       2015-09-05 02:26:18 +08:00
    @loading 所以我觉得应该分开,让 API 做到单一职责。

    以前用 PHP 的时候,习惯于大量用 SQL 语句做 JOIN ,因为这样方便,一句话返回所有我要的数据就行了。
    这种情况下自然就产生出你说的这种输出方式,用 JOIN 把用户数据一起加载进帖子数据里。

    现在用 RoR , ActiveRecord 倾向于分开查询,就是第一次先查帖子数据,然后用拿到的用户 ID 去做第二次查询。好处是查询更容易被缓存,以及表结构更容易做性能优化。(毕竟索引只要建在主键 /外键上就好了)这样就自然而然出现了两次查询的做法,即:

    get_json (:posts )
    .then {
    - display_posts
    - find_user_ids
    - return get_json (:users, user_ids )
    }.then {
    - replace_user_info_by_id
    }
    luago
        29
    luago  
       2015-09-05 10:36:32 +08:00
    建议回传,客户端如果已经缓存了头像,你的传输成本只是增加了用户名和头像地址的字符串长度而已。
    railgun
        30
    railgun  
       2015-09-05 12:01:12 +08:00
    加个开关,让客户端自己判断就好了
    bdbai
        31
    bdbai  
    OP
       2015-09-05 14:26:20 +08:00 via iPhone
    @luago 积少成多 另外客户端还能缓存用户信息呢
    @msg7086 隐约感觉外部可以全都传 系统里面还得抽象
    boywang004
        32
    boywang004  
       2015-09-05 19:12:57 +08:00
    个人倾向于接口设计成原子性的,减少接口设计和视图耦合后造成的接口数量爆炸或者维护成本陡增。至于减少请求次数或者减少 RTT 开销,可以交给底层做。比如吧,直接上 http/2 。
    至于楼主问的索引和实体数据要不要一起返回,如果架构设计允许,分开返回可以设计成客户端本地缓存部分数据,减少下行量(增加的一次请求开销在 http/2 或者 spdy3.1 下不会太多)。但是设计不好很容易增加复杂度和 bug 率或者响应时间陡增之类的,所以没啥时间简单做就一起返回啦。
    zhangv
        33
    zhangv  
       2015-09-05 23:15:35 +08:00
    RESTful 是 API 的设计约定,说的简单点就是你设计一个 function 的参数和返回值是什么样子的。 --- 这些首先取决于你的需求(也就是使用这个 function 的人),而不应该是首先考虑是否应该减少内存使用。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2851 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 02:21 · PVG 10:21 · LAX 18:21 · JFK 21:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.