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

服务端 API 设计到什么程度算合适

  •  
  •   Immortal · 2017-02-13 11:22:32 +08:00 · 5828 次点击
    这是一个创建于 643 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我是做服务端这块的,主要现在是做 API
    最近工作中碰到一些不是很顺利的情况,不知道是不是我自己想法不对,在我概念里,如果不涉及到安全问题,很多数据展现上的逻辑工作都应该可以放在客户端处理.具体我也不好举例子,现在客户端(主要是 APP)的要求就是要做到他们数据是拿来就用,不用经过任何处理那种(遍历整理数据等操作).宁可增加网络请求,也不太愿意客户端自己处理掉,最好我这边都全部帮他们解决了.
    我是这么想的:
    1\考虑到服务器的负载,所以想把一定计算量放到客户端
    2\考虑到流量,但客户端同事总说现在到处是 wifi,大家流量也很多,这些都是忽略不计的.道理也没错,但这不还有一方面是服务器的带宽么...
    3\考虑到版本迭代,因为如果服务端数据处理到很细节,适用性很低,基本没法复用,一个需求本来是几个基础 api 提供的数据客户端整合处理下能解决的,需要我提供一个新接口,我不是非常乐意.当然如果整合的接口多,逻辑复杂我也愿意处理的,这里指的是很简单的那些. 客户端一个版本逻辑处理写死了,下个版本改了就改了,作为服务端每次改动要考虑到兼容性,所以我不太愿意维护这么多小接口.

    有点罗嗦,也不知道有没有表达清楚意思.就是想问下大家在做 api 的时候是设计到什么尺度? 真要做到客户端拿到数据只需要展示这种程度么?

    第 1 条附言  ·  2017-02-13 13:40:29 +08:00
    看评论想了下
    是不是比较合理的都分的层数比较多:
    1.基础数据层:提供各种最底层的数据,最基础的获取,不会有任何逻辑
    2.数据逻辑层:这个也是服务端做,就是之前争论的 api 做还是客户端做的那些操作,全部放到这一层,向上从基础数据层获取数据,向下对客户端提供数据.
    3.最后才是客户端

    应该很多都大概这么分的吧..
    如果争论问题比较大,以后我想慢慢改成这样
    67 回复  |  直到 2017-02-15 10:17:47 +08:00
        1
    kulove   2017-02-13 11:27:53 +08:00
    客户端能做且数据不重要那就客户端做,流量不用太在意但也不能滥用,接口加版本号
        2
    Immortal   2017-02-13 11:33:01 +08:00
    @kulove 我大概也是这么个意思 客户端大佬们觉得 数据处理这种事情就不应该放在客户端做 这个问题每次都能争好久 接口加版本号这个懂的 想问下 你那对于每个版本的接口路由分发 做在了 web 服务器那层(比如 nginx) 还是项目的路由里 我不知道做哪里和是 我这边用 golang 写的
        3
    dangyuluo   2017-02-13 11:36:20 +08:00
    大家都在推诿,做客户端的肯定想偷懒啦。
        4
    minbaby   2017-02-13 11:37:24 +08:00
    @Immortal 哈哈,这个问题我遇到过,客户端的同学特别“拗”,能让我( API )做的都让我做,恨不得我把所有工作都做了,为了一个东西能争论很久(有这个时间早做完了),目的是让我明白我的思路是错的。恩,就这样,结果是我还在这家公司。
        5
    Immortal   2017-02-13 11:40:26 +08:00
    @dangyuluo 的确有这个问题...有时候我在表达我的想法,客户端大佬们觉得我想偷懒,少写点代码...我是觉得应该做的都会去做不会推卸,不应该做(意思是不应该放在服务器处理的)就不是很乐意做,不过最后都会妥协..因为项目组 ios+安卓有 2 个大佬,而服务端就我一个小弟,百口莫辩啊
        6
    Immortal   2017-02-13 11:41:00 +08:00
    @minbaby ...我现在正在遇到这个问题,大佬们心情好点就少说我两句,帮我分担点,一般都是我这边都处理掉了
        7
    ytmsdy   2017-02-13 11:42:09 +08:00
    1:无关紧要的计算放在客户端,服务器的计算量能省一点是一点。如果客户量大,省下来的计算量也是很客观的
    2 :流量,先保证 app 正确可用,闲着无聊可以做流量的优化。
    3 :具体情况具体分析,如果都是 get 的请求。如果返回的数据包大,那就让客户端分多次来,数据包小那就你整理一下一个 API 返回。如果是 post ,或者是 put , delete 涉及到数据操作的,最好在一个 api 里面做完,要不然网络中断什么的,出现脏数据是很讨厌的。

    按照你的说法,客户端的同事只是想省力一点而已。
        8
    helloccav   2017-02-13 11:43:54 +08:00 via Android
    我也遇到这个问题,对了,我是那个客户端
        9
    Immortal   2017-02-13 11:46:28 +08:00
    @ytmsdy 对于 1,可能我自己太理想话了,想把性能上的问题在开发时候能考虑到的顺手都做了,客户端的意思是现在不用考虑这么多,等流量大了服务器啥的就多了,说不定客户端代码都重写了云云,我不知道怎么说服,三观不是很和. 2 我同意你说的,我思路主要和 1 一样,开发时候想到的想顺手做,这个优化的确可以滞后. 3 明白你的意思,对于事务操作肯定是放一个 api 处理了,这边主要是指的 get,数据整合类的逻辑,有时候需求数据可以从几个基础 API 获取自己整合,客户端不是很乐意

    我也就吐槽下,他们想省力我也不是很有办法说服他们多写代码...
        10
    Immortal   2017-02-13 11:47:09 +08:00
    @helloccav 可以说下你们客户端的想法...我看看我们逻辑差在哪里
        11
    rockyou12   2017-02-13 11:49:36 +08:00
    还是看业务吧, app 重新发布需要用户自己更新,不像 web 这么方便,很多业务要变的话放 app 里面很不方便。除此我觉得 app 多请求几次去处理没什么问题
        12
    Immortal   2017-02-13 11:51:55 +08:00
    @rockyou12 主要不是在业务逻辑上,业务逻辑因为很多涉及到安全问题,基本都放服务端了,很多问题是在展现逻辑上,这个数据要帮他们整理好,这个数据帮他们拼接好等等,但是其实是可以从 A 接口和 B 接口里获取自己整合,现在需要给他们新写一个 C 接口,我就不太愿意,一个是增加维护成本,一个就是没复用性
        13
    helloccav   2017-02-13 12:35:53 +08:00 via Android
    @Immortal 我们客户端的想法就是和你题目里面那个客户端的想法一样,想要服务器端处理好各种计算,客户端只负责直接展示。在我们这个项目里服务器端的工程师自己就是这样设计的,不用客户端的工程师去提要求。
    我们项目里面,服务器端和客户端的工程师的关系还是挺好的,不会为了这个吵架。
        14
    Exin   2017-02-13 12:36:43 +08:00 via iPhone
    这种事需要一个统管前后端的上级来做决定,
    因为两边都可以做、都有理,争论难休
        15
    helloccav   2017-02-13 12:41:16 +08:00
    @Immortal 我自己在有些项目里开发客户端,有些项目里开发服务器端。对于一个展示要同时读 A 接口和 B 接口然后组合数据这样的情况,我们一般都是要求服务器端整合成一个 C 接口提供数据,主要原因是减少网络请求。
    我们的要求是:
    1 、尽量减少网络请求
    2 、后期业务的调整尽量通过服务器端实现,客户端不修改。所以我们把尽可能多的计算和逻辑放在服务器端口实现。例如某个预订的总价是商品价格+服务费,这个总价的计算 就放在服务器端而不是客户端,这样以后想去掉服务费可以只改服务器,不用改客户端,免得客户端要重新上架(这个例子可能举得不太对,但我一时找不到更好的例子。)。
        16
    learnshare   2017-02-13 12:49:29 +08:00
    客户端来做无关紧要的处理比较合适。服务端的 API 应该定位成可以服务于多种客户端的( Android/iOS/Web 等),不是以某个客户端为主。

    But 真的要分析具体问题,最好是有一个独立的 API 方案或者方法,服务端和客户端都按文档来,彼此不关心实现。
        17
    xiaoyangsa   2017-02-13 12:51:06 +08:00
    能后台处理就后台处理吧。前台永远给他们做展示好了。
    这就想 mvc 里面的 view 层一样,只做数据展示就行。
    以后要换客户端的人就会简单得多。
    要加入一个新的客户端平台也会很方便。
        18
    nanlong   2017-02-13 12:52:07 +08:00
    1, 流量必然要考虑,必定会碰到没有 wifi 的情况,优化流量也能提高项目整体性能,何乐不为。
    2, GraphQL 解决了数据组合、复用的问题。
    3, 写客户端也是程序员啊,该干的、能干的不可以推诿,别给程序员丢脸。一些处理放在客户端必然能缓解后端服务器的压力,凭啥不做。
        19
    rockyou12   2017-02-13 13:04:17 +08:00
    不涉及业务那你给他们写什么,难道界面改了你后台还要改?这不增加大家工作量嘛
        20
    ideascf   2017-02-13 13:10:04 +08:00
    观点: 后台提供的 api 应该是面向数据的,而不是面向页面的。 面向页面的接口,一旦页面发生变动, api 就要发生对应的调整。 而且这样的接口也不够通用,会导致很多割裂的接口,这不是一个好的现象。
    方案: 如果大佬讲理由讲不通,那也只得按他们的来咯。 但是你可以考虑增加一个 API gateway , 由这个 api gateway 完成面向页面的 api 封装,向后调用面向数据的 api 。 如果前端后 node.js 的话,直接丢给他们做。
        21
    ideascf   2017-02-13 13:19:15 +08:00
    补充一个连接: [微服务实战(二):使用 API Gateway]( http://dockone.io/article/482) 或许有些帮助。
        22
    helloccav   2017-02-13 13:21:04 +08:00 via Android
    @ideascf 如果 api 面向而不是面向页面,那么一个页面由很多部分组成,那就要调用好几个接口,这就大大增加了网络请求的负担。在我们的项目里面, api 都是面向页面的,一个页面尽量只请求一次 /一个 api
        23
    hwiiago   2017-02-13 13:24:17 +08:00
    没有业务场景单纯谈该放哪边来计算是没有意义的。
        24
    wizardoz   2017-02-13 13:27:27 +08:00
    不考虑用户的流量,我觉得是很作死的行为。
    要是用户哪天打开流量统计,发现你的 app 是流量大户,说不定就卸载了。
        25
    Immortal   2017-02-13 13:29:13 +08:00
    @Exin 是的 的确有发现这个问题 扁平化管理的缺陷
        26
    Immortal   2017-02-13 13:30:05 +08:00
    @helloccav 明白你的意思了 这种会影响业务逻辑的改动 的确需要考虑进去 学习了
        27
    Immortal   2017-02-13 13:31:42 +08:00
    @ideascf 很同意你的说法 应该面向数据而不是页面, 做着做着就做到页面的误区了.回头想了下,主要应该是一般开发没文档,都是看着页面+口头问需求的原因...
        28
    Immortal   2017-02-13 13:32:43 +08:00
    @wizardoz 会有这个可能,主要用户量不上来,很多问题不愿意也可能都想不到,光凭嘴巴说服不了很尴尬
        29
    ystop   2017-02-13 13:32:58 +08:00
    我觉得 一般情况下 这些逻辑是要放在后台做的。 因为 APP 发版的成本很高,而且客户端过多的接口业务反而会导致项目复杂度的提高,平时有什么 BUG,问题的,兼容的 后台直接改就好了,非常方便。 对于通用性,我觉得底层的服务代码肯定是通用的,不同的端确实是需要不同的接口的,需要加个 api 层完成面向页面的 api 封装.
        30
    Immortal   2017-02-13 13:35:42 +08:00
    @helloccav 这个问题感觉又很难完全有个标准.按页面有按页面的好处,按数据也是.前者连接数是会少,后者更加灵活和容易维护.扯到最后又要扯到具体需求了,不过这种我觉得可以灵活的定,但是可以有一个侧重面
        31
    crashX   2017-02-13 13:39:06 +08:00
    看你后台有几层了,如果你是中间层对接客户端应该做,如果是底层需要对接所有端那应该给客户端做。
        32
    susucoolsama   2017-02-13 13:42:19 +08:00
    感觉 APP 还是面向页面写接口好啊,面向数据很蠢的,虽然通用性好,但是架不住一个页面请求好几次接口,逻辑也写在 APP 里,网络请求负担很大。
        33
    ideascf   2017-02-13 13:42:39 +08:00
    @helloccav 是的,如果有多个模块,就请求多个 api ,我们目前就是按照这样的方式处理。 这样 api 在很大程度上能得到复用,这更有利于 api 维护管理。 如果全部面向页面来做 api ,我认为越往后走, api 维护以及代码维护的成本就会越来越高。 当然,这样肯定就会面临多次网络 io 的开销,但我认为在目前 4G 流行的场景这不是一个大问题。 而且如果发现这块真的是一个短板,那么可以考虑加入 API gateway 。
        34
    ideascf   2017-02-13 13:44:56 +08:00
    @Immortal 要立字据啊
        35
    Immortal   2017-02-13 13:45:43 +08:00
    @crashX 刚好想到这个问题,应该问题也在我分层不是很清晰.前期规划的问题.对于这个事情上我自己看来问题也很大,准备慢慢解藕
        36
    Immortal   2017-02-13 13:46:49 +08:00
    @ideascf 唉 工作环境没这么理想化呢,我也想有个文档,写代码的时候只要动手动眼别动口.没办法
        37
    jiangzhuo   2017-02-13 13:52:24 +08:00
    我给你讲个不是笑话的笑话——曾经有款手游,战斗动画都是服务端渲染然后以流媒体的形式传回给客户端的。
        38
    TangMonk   2017-02-13 13:53:32 +08:00
    @kulove 版本号这个我觉得不是很必要,如果有大版本变动,数据结构就会有不同。如果两个版本使用同一个数据库,那么数据就会错乱的。

    如果确实需要兼容老版本接口的话,还要单独做数据兼容处理。
        39
    TangMonk   2017-02-13 13:59:17 +08:00
    @TangMonk 如果是类似 AWS 那种给开发者提供接口的话,就有必要加上版本号。 如果是普通的应用场景,版本号不是很必要。
        40
    kulove   2017-02-13 14:02:09 +08:00
    @TangMonk #38 如果不传版本号的话就确定不了版本,如果是改变接口地址还不如传版本号方便,设计兼容新老版本的 API 我觉得是很有必要的,没有那个 APP 发布大版本后之前的版本就不能用的例子吧
        41
    kaka8wp   2017-02-13 14:07:11 +08:00
    对于给 app 的接口,工作上遇到的就是客户端同事觉得最好接口面向页面,不希望一个页面调用几次接口,我感觉是不是可以在服务端还是按照面向数据来做接口,给 app 包装出来一个调用多个面向数据的面向页面的接口。后面更新维护也稍微好弄点
        42
    TangMonk   2017-02-13 14:10:30 +08:00
    @kulove

    有时候兼容起来很困难,不得不再开一个数据库。
    如果是普通 app 的话,我觉得不如直接强制更新了。
    对于已经有大量的老用户的话,还是得做兼容。

    http://stackoverflow.com/questions/389169/best-practices-for-api-versioning
        43
    Eoss   2017-02-13 14:16:08 +08:00 via iPhone
    @jiangzhuo 说的是炉石吧。
        44
    Immortal   2017-02-13 14:19:30 +08:00
    @kaka8wp 比如我附加的说明?你看下是不是这个意思
        45
    kulove   2017-02-13 14:23:18 +08:00
    @TangMonk #42 兼容确实是问题,如果是企业内部使用倒还可以强制更新,如果对象是大众还真要仔细考虑考虑,能兼容尽量兼容
        46
    kaka8wp   2017-02-13 14:40:14 +08:00
    @Immortal 对的~我觉得这个挺合理的,后续维护的话对于 app 页面调整这种,只要修改那一个有数据逻辑的接口就好,而且减少影响其他引用相同的面向数据接口的地方。
    工作中几个项目都是轻量化客户端,基本上都是数据显示不做任何处理~我这样做之后同事关系明显好了~就是一有问题不管怎么样都先说是后端返回的数据问题。哈哈
        47
    Limius   2017-02-13 15:11:21 +08:00
    作为 PM 我跟技术团队完成项目时也遇到过这种事,你考虑到的是性能的问题,实际上我考虑到的是如果由服务端提供 API ,客户端只做展示功能,业务抗错能力会比较强,数据计算逻辑写死在客户端,如果上线后发现需要调整,这时你只能通过更新客户端版本来修正数据展示,而 appstore 的上线审批需要几天时间,对于我们 PM 来说这几天基本是不可忍受的,特别是互金行业,涉及到金额数据的展示这种是致命的,所以宁愿计算逻辑由服务端完成,毕竟随时可改,这是我从产品角度的一些看法,供你参考。
        48
    Limius   2017-02-13 15:14:13 +08:00
    @TangMonk 这个链接很好的回答了嘛
        49
    learnshare   2017-02-13 15:17:32 +08:00 via Android
    补充里的三层是合理的,不过一般项目都前两层合并到一起了。甚至划分不清楚,数据和业务逻辑部分融合到一起了,难以维护。

    实在有必要,就另搞一层后端,专门服务客户端。
        50
    bombless   2017-02-13 15:21:28 +08:00
    我们这边倾向于尽可能让服务器端做。
    其实我挺同意的,我们做 app 的让客户端节省点电量让手机续航更长一点挺好的。
    我自己是负责服务端这边的。
        51
    Immortal   2017-02-13 15:32:39 +08:00
    @Limius 嗯 这个问题之前没有很重视 的确很重要
        52
    Immortal   2017-02-13 15:33:05 +08:00
    @learnshare 是的 现在我就是只有两层 想慢慢分出来 被坑到了..
        53
    renshaojuncool   2017-02-13 16:27:24 +08:00
    我感觉应该看具体情况吧,我是做 iOS 的,一般数据处理是很希望放在服务端来做的,客户端在渲染页面之前,对请求到的数据做过度的处理,会造成反应缓慢,卡顿的感觉(当然也可以进行一些优化,做预处理),但是考虑到 APP 健壮性,还是放在服务端处理比较好,这样造成的结果就是,如果线上出现了某个问题,我会先查是否是自己的问题或者是数据返回的问题,一般后台背锅就比较多了(虽然客户端已经做了比较多的安全处理,但是某些数据还是不可避免的会发生),这种情况下,后台直接修改代码或数据,就可以立马结局,而如果放在客户端,就 iOS 而言,审核就够难受的了
        54
    Limius   2017-02-13 17:35:57 +08:00
    @renshaojuncool 我上面回答的正是这个意思~
        55
    sampeng   2017-02-13 18:00:54 +08:00
    设计到自己懒得去实现为止。就是设计 api 总有个一界限。过了界限,自己就要加班去实现。。。我个人觉得不用想太多,以加班为平衡点来是最实际的。什么?扩展性,放心好了。其他人看别人的 api 设计都是一坨屎
        56
    Aluhao   2017-02-13 20:46:54 +08:00 via iPhone
    能 App 本地处理的,就不需要去向服务器请求;
        57
    CFM880   2017-02-13 21:27:53 +08:00
    现在每次穿过的数据都要遍历一遍。。。。。
        58
    zwhu   2017-02-13 22:32:18 +08:00
    也许你们想要的是 graphql
        59
    mazyi   2017-02-14 00:05:53 +08:00
    写 app 应该也是有成熟的体系了,如果 app 是核心业务的话后台只是处理器而已, dirty work 自然多。

    这里和 app 的性质其实有很大的关系,如果涉及较多的交互那无可厚非数据得干净,如果更多的动态变化的展示那就自己处理数据。
        60
    Chyroc   2017-02-14 02:15:45 +08:00 via iPhone
    试试 graphql
        61
    lovebirdegg   2017-02-14 08:50:02 +08:00
    逻辑处理放在服务端比较好,放在客户端维护起来太不方便了。
        62
    wupher   2017-02-14 09:42:17 +08:00
    一般而言,数据和逻辑是放到服务端,展示层是客户端的事,这是大原则。

    在可能的基础上,尽量提高接口的友好程度,方便客户端拿到数据后能方便处理,这是原则 2 。

    流量是肯定要考虑的,我自己也做 iOS 客户端,他这么说肯定是瞎扯。现在弱网络,如地铁,火车、汽车等情况其实相较以前更常见了。本地在可能的情况下,都是要做 cache 的。

    理由 3 ,我倒觉得未必成立。其实,数据实际传输的时间消耗不一定高,往往是链接建立的耗时更高。所以一般建议,尽量一个请求搞定数据,而不要让客户端连续调用多个 http 请求来为一个界面加载数据。如果服务端只是将几个 http 请求包起来,统一做个门面,其实这事也不难。比客户端回调套回调好处理多了。
        63
    adoyle   2017-02-14 10:18:39 +08:00   ♥ 1
    只能协商。逻辑放在客户端或者服务端 (gateway) 里实现并没有绝对的定论,因为这都包含了业务逻辑。以固有逻辑来定论我觉得都是错误的,要根据具体场景、团队、业务逻辑来判断放哪实现**最为合适**。业务逻辑是难以根据平台区分的。协商会有几点考虑因素:

    1. 安全性。有些数据只能在服务端计算。
    2. 性能开销。根据不同场景,可以放在客户端,也可以放在服务端。
    3. 可复用性。业务逻辑实现在客户端,就难以复用了;但实现在服务端,又要考虑通用性。
    4. 人为因素。观点争执不下,沟通成本太高等等。

    我觉得解决这个问题的最好办法,不是讨论这块逻辑究竟该放哪里。因为每个新 feature 都得讨论一遍接口,会非常麻烦。
    而是应该由一个人去负责一个 feature 的完成,由同一个人完成前后端的代码,即所谓的全栈。这样的好处在于:

    1. 避免沟通交流上的争执。在编程领域,一个人干活往往比两个人效率更高。
    2. 只有经历过同样的场景,才会换位思考,知道对方的难点,才会互相体谅。
    3. 当一个人去实现,因为放哪做都是自己做,才更有可能去思考代码结构,真正考虑业务逻辑放哪实现**最为合适**。
    4. 当一个人去跨端,会培养全局意识,对于技术发展也是有好处的。

    你可能会觉得让前端来学服务端难度太大。这是有前提的,前提是你的项目架构要清晰可维护,新手进来能快速上手,当项目可维护性做得很好,有很好的结构,那么入门门槛就只在于语言了。对于学一门新语言,对稍微有点经验的开发者来说不算难事吧。待对方实现好代码后,你可以参与 code review ,把控项目质量。
        64
    barbery   2017-02-14 10:59:30 +08:00
    理论上,我觉得服务器的接口是尽可能的考虑到通用性,返回基础数据,由客户端根据自己的业务需要来自行处理然后渲染出来。这个在 web 端一直没什么问题,但是自从 IOS 和 Android 出来后情况又不一样了,考虑到发包的成本,基本上服务端都要包揽了所有的数据处理的逻辑,这么搞可以理解,但是如果出现不同的平台同一个页面不同的功能设计就很尴尬了,为了不同平台的处理逻辑,又要拆分出一个接口~
        65
    orvice   2017-02-14 23:12:33 +08:00
    大部分情况下都是因为客户端懒吧。。。
        66
    Immortal   2017-02-15 09:22:48 +08:00
    @orvice 看大家评论,也不完全是懒,也有很多无奈的地方.app 和 web 还是不太一样,ios 要过审什么的所以很多只能放服务端
        67
    orvice   2017-02-15 10:17:47 +08:00
    @Immortal 过审核我们是添加一个配置项目, ios 取到以后再 client 端关掉相关功能
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   611 人在线   最高记录 3821   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 23ms · UTC 21:21 · PVG 05:21 · LAX 13:21 · JFK 16:21
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1