前两天试了一下 blazor,在 server-side 模式的时候,使用了 SignalR 传输数据。这样可以做到在页面里调用数据的时候,就像调用本地函数一样,而不用自己处理 http 请求,感觉写起来很简单省事儿了。
后面就想到,为什么现在前端基本上都是基于 ajax 做数据刷新,为什么不能使用 rpc 的方式呢?这样的话,一套接口写好,前端后端都可以自动生成对应的函数接口,直接调用多简单?特别是对于很多个人项目来说,不需要手动处理各种 http 请求了,不是更方便吗?实际传输可以基于 ajax 也可以走 websocket,可以做成库帮我们处理,岂不是更省心省力了?
那么这种方式为什么没有推广呢?有什么非常致命的缺点吗?
|  |      1qW7bo2FbzbC0      2020-03-27 14:06:24 +08:00 求给个 SignalR 的入手文章,英文懒得看。是用来 替代 websocket 的吗 | 
|      2Mithril      2020-03-27 14:12:03 +08:00 SignalR 底层也是 HTTP 啊,只不过给你封装了一下而已。跟 Ajax 完全不是一个层面的东西。 不同的框架基本也都会封装自己的 HTTP 库的。 | 
|  |      3wysnylc      2020-03-27 14:12:36 +08:00 笑死我了哈哈哈哈 | 
|      4eslizn      2020-03-27 14:13:46 +08:00 rpc 和 ajax 是一种东西么? | 
|  |      5jugelizi      2020-03-27 14:19:12 +08:00 via iPhone 说了这么多 你就不能谷歌一下这两个区别吗 | 
|      6unifier OP @eslizn 当然不是一种东西了。我只是在说在前端使用这两种方式的区别啊,可能我说的有点歧义,我是想说目前手动请求 url 和使用 rpc,为什么不使用 rpc 呢?接口明确还有预定义的 stub 可以调用 | 
|  |      8rrfeng      2020-03-27 14:30:28 +08:00 如果你知道,你就不会问出这个问题。 | 
|  |      10toma77      2020-03-27 14:36:38 +08:00 我司后端有些微服务用了 grpc 我前端用 go 使用的时候没啥问题,但最近有些项目用了 react 的 ssr,在 node 里使用很容易内存暴增,蛋儿疼。。 | 
|      11sailei      2020-03-27 14:48:19 +08:00 浏览器应该不支持吧 | 
|      12unifier OP @sailei 可以的,有些 rpc 基于 http,可以这么搞。像楼上提到的 grpc,已经有专门的 grpc-web 的库做这个了。 | 
|      13sanggao      2020-03-27 14:55:31 +08:00 感觉楼主就是来搞笑的,可能没做过什么项目 | 
|      14sailei      2020-03-27 14:58:18 +08:00 @zacharyjia  那是用 nginx 等代理工具 转成 http 协议了! | 
|  |      15rrfeng      2020-03-27 14:58:26 +08:00 ajax = Asynchronous JavaScript and XML (“应用层”) rpc = Remote procedure call (“传输层”) ajax over rpc 可以吗?当然可以。 | 
|  |      17otakustay      2020-03-27 15:01:35 +08:00  6 按楼主的意思是,他希望以“调用一个远程方法”的形式去理解一个一次远程的调用,而不是 URL+数据的组合 我觉得这个说法非常合理,是很严谨的工程论断,楼上说搞笑的还是省省 前端即便去用“方法”的粒度做远程调用的封装,往往也是人工做的,比如把各种 API 包装成函数,我想这里一个很大的原因在于服务发现,第一前端对服务发现这个事没有很好的理解和掌控力,第二服务发现本身是影响启动速度的,而前端并不是后端服务那种一次启动跑几天几个月的,前端对启动速度的要求是毫秒级的,没什么时间给服务发现去耽搁 | 
|      18unifier OP @rrfeng 如果你说的 应用层和传输层 是指网络的五层架构里的应用层和传输层的话,那我觉得你的理解才是错的。rpc 可以基于 tcp,可以基于 http 等,它再怎么低也不能低成一个跟 tcp 和 udp 同层的传输层协议去。 | 
|  |      19rrfeng      2020-03-27 15:09:53 +08:00  1 @zacharyjia  没看见打了引号吗? ajax 意思是『可以异步请求数据然后更新页面上的内容』,至于你怎么请求数据,你可以调用 http 或者 rpc 甚至等待键盘输入,那不是 ajax 描述的事情。 上面笑得都是笑你基本概念没搞清楚。ajax 和 rpc 半毛钱关系都没有,怎么替代? | 
|  |      20rrfeng      2020-03-27 15:11:10 +08:00 你把 ajax 和 ajax+http 搞混了。 | 
|  |      21lhx2008      2020-03-27 15:15:36 +08:00 我不是前端,理论上没什么问题,RPC 本质是 stub 的封装,所以前端应该也是可以实现的,至于是 TCP 还是 HTTP 和 RPC 又没啥关系 | 
|      22unifier OP | 
|      23sailei      2020-03-27 15:17:25 +08:00 | 
|      24sailei      2020-03-27 15:20:44 +08:00 可以简单理解为 http2  base64 压缩版 | 
|  |      25cxh116      2020-03-27 15:25:35 +08:00 Ajax 只是异步的发送 HTTP 请求的一种技术. 而 RP 是 Remote Procedure Call(远程过程调用)的简称. Ajax 发送的 HTTP 请求就是 RPC 的一种,因为 HTTP 请求参数相当于远程调用的方法参数,而请求返回相当于远程方法的返回. 只是不像正规的 rpc 协议那么规范而已. 为什么不用 RPC 协议?感觉 JSON 一把梭省事. | 
|  |      26BasIrs      2020-03-27 15:25:52 +08:00 前端为什么基本上都使用 AJAX 请求,而不使用 RPC ? | 
|  |      27woodensail      2020-03-27 15:26:44 +08:00 因为 ajax 也能做到你所说的把 api 封装成函数。事实上现在一般大型项目已经不可能在 url 到处飞了。基本上都是在 api 层封装为函数。业务层直接调用函数就行。 | 
|  |      28chinvo      2020-03-27 15:28:59 +08:00 AJAX 是 JS 通过浏览器发请求的方式 RPC 是远程过程调用 RPC 需要发请求, 在浏览器中, 可以是通过 AJAX, 也可以通过 websocket, 还可以通过 webrtc | 
|  |      29jin5354      2020-03-27 15:29:39 +08:00 可能意义不大,因为对前端来说无论是 rpc 还是 ajax 都是要查接口协议然后调用,rpc 无非是封装了一层,如果能把 ts 引入带来接口类型补全能省点事 | 
|      30unifier OP @woodensail 但是这个封装是手动的吧,rpc 一般都可以通过代码生成器自动实现,不是更简单吗? | 
|  |      31rrfeng      2020-03-27 15:36:07 +08:00 所以这个问题就回归到了 http 和 rpc 的优缺点上。 http 参数灵活,rpc 调用方便,但是更新麻烦。 非常多的需要服务端数据的 js sdk 封装好了,直接调用方法,你可以认为这就是个 rpc client 的封装,over http 的。 | 
|  |      32liuxey      2020-03-27 15:41:55 +08:00 基础不牢 地动山摇 | 
|      33Jooooooooo      2020-03-27 15:43:31 +08:00 http 就是 rpc 你用 http 的时候把负载均衡, 节点注册发现啥的一搞就是一个 rpc 框架 | 
|  |      34woodensail      2020-03-27 15:44:10 +08:00 @zacharyjia  我能理解你的意思,早年间我也也用过.net 的技术,.net 的开发确实是前后端高度整合,感觉不像是在开发一个网站而是开发一个本地应用程序。 但实际上这只是组件还高度封装带来的错觉。事实上如果你用一些商用的企业服务开发框架,也能做到类似的体验,说白了,复杂的逻辑都只是被人封装了而已,不是不存在。而且这种封装还会带来前后端高度耦合的副作用。 所以现在前端更倾向于自己封装 api,反正一个接口就一行,也不麻烦。 | 
|  |      35Soar360      2020-03-27 15:44:11 +08:00 | 
|  |      36ysmood      2020-03-27 15:52:17 +08:00  1 引用一个标准 rest 库不就可以不手动写了吗? http with url 本身就是一种 rpc 啊,ajax 符合一切 rpc 要完成的事,只不过 function name 现在是 url path name 了,params 换成 query 或者 post body 了,http 的 status 返回码也是有标准错误定义。哪个都很符合 rpc 要完成的事。 所以从问题出发,如果你发现生写 ajax 处理很麻烦,就写个库或者引用别人的轮子将这个步骤抽象掉,问题解决。这个跟 rpc 没有太大关系。rpc 很古老了,对于前端来说也一点不新鲜。 rpc 是在 http 之前就有了,当计算机性能带宽不再是通信瓶颈后,人们选择牺牲性能和带宽来增加协议的可读性,这样你会发现 http debug 只需要截获他的包用文本编辑器就能读懂,这样就衍生了一大批友好的 http 开发和调试工具,这也是 http 能普及的总要原因,而像 grpc 的数据包你是没法人肉读写的,代理更是没法简单根据数据内容优化路由或者缓存。 各有各的好处,没有完美,只在于取舍而已。如今分布式的流行又让 rpc 的一些想法火起来了而已。 | 
|  |      37ysmood      2020-03-27 16:04:44 +08:00 顺便附上个我  4 年前写的库,和一般 rpc 库不同的是你可以一次调用多个函数组合而不用每次都把数据拉到本地处理,相当于你发送了一个脚本到远端去运行,而且这个脚本是安全可控难以注入攻击的: https://github.com/ysmood/nisper | 
|  |      38AV1      2020-03-27 16:13:16 +08:00 现在的人都把 AJAX 当作 XMLHttpRequest 的代名词了呢,也许是 jQuery 巨大影响带来的误解。 | 
|  |      39mazyi PRO 多看点书啊 前后端分久必合?合久必分?这都是作为一个技术人员应该有的基础思考吧?不然就只能说自己是一个接口仔。 | 
|  |      43otakustay      2020-03-27 16:26:59 +08:00 @zacharyjia 现在也有一些自动生成调用代码的工具,我记得阿里搞了一套,我们这边是在扩展 yapi 的能力让它来生成 工程做大了,这些事肯定提上台面的,在我看来“大部分人不用”就是因为“大部分工程不够大” | 
|  |      44yaphets666      2020-03-27 16:30:23 +08:00 RPC 是一种描述 AJAX 也是一种描述 都不是具体的技术 在某种程度上甚至可以认为他们是同一种东西 | 
|      46sanggao      2020-03-27 16:40:53 +08:00  3 本来懒得再喷了!但还是要喷了,我发现 V2 论坛上特别多的幼稚甚至近乎“弱智”的技术问题,虽然是一本正经的发帖,但是技术了解度跟脉脉 [非广告] 简直一个天上一个地下,可能脉脉用户更多的是一线互联网公司的员工。 ( 1 )首先能做跟要不要做完全是两回事,特别是对于企业级商业项目,根本不是你玩个个人博客站点那样 ( 2 ) rpc 能调用服务端接口这没问题,但是不代表能做项目,服务端同学都知道,暴露给前端的一个 http 接口,可能内部调用了几百个别的服务端接口,难道你前端调用的时候要一个个去组合吗?后端的逻辑你是否十分十分清楚?还有你前端调用成功了前 N 个接口,但是调用失败了其中一个接口,数据一致性、幂等性,回滚,关键节点日志难道你前端做的了吗?? ( 3 )前几年前后端还未分离,例如 java jsp 和 php 前后混编,那时候前后连 rpc 调用都不用,哪种方式有这样的性能高?那为什么又前后分离呢?? ( 4 )现在的确有前端(安卓 APP )用 Grpc 调用服务端接口,你问问哪个不是做的想死的心的都有了?? 项目做到最后加一点需求都加不上去,game over (5) 求求你,不要总是世人皆醉你独醒了,业界的趟过无数坑总结出来的胜过你的凭空想象! | 
|  |      47rioshikelong121      2020-03-27 16:48:25 +08:00 》 特别是对于很多个人项目来说,不需要手动处理各种 http 请求了,不是更方便吗 存在良好封装的工具函数的情况下,我觉得处理 http 请求没什么太多的开销吧。 我倒是觉得 “前端后端都可以自动生成对应的函数接口,直接 rpc 调用” 也会带来额外的问题。 到时候也会需要引入聚合层 /BFF 这样的中间层的。 | 
|  |      48jugelizi      2020-03-27 16:49:23 +08:00 via iPhone | 
|  |      49tabris17      2020-03-27 16:51:58 +08:00 这是个好问题,你为什么不问问神奇的浏览器? | 
|  |      50otakustay      2020-03-27 16:59:06 +08:00 哦对了,要说前端的 RPC,我觉得 GraphQL 是个差不多的东西了,前端一定会往这个方向发展的 | 
|  |      51LostPrayers      2020-03-27 18:25:44 +08:00 等你多年以后再回来看看自己发了什么东西吧 | 
|  |      52richard1122      2020-03-27 22:16:09 +08:00 这根本就是两个层次的事情,就跟问 人为什么要喝水而不是买锅 | 
|  |      53bnm965321      2020-03-27 22:54:48 +08:00 听起来像是 GraphQL Subscription 不过楼主说的 RPC based on HTTP/2 我是不认同的 | 
|      54xiaojie668329      2020-03-28 00:50:24 +08:00 via iPhone Google 有开源了 grpc-web 的,应该还不是十分成熟。默认基于 http2 好像。 | 
|  |      55keelii      2020-03-28 09:53:21 +08:00 楼主所说的「前端」实际上指代的是客户端,客户端和服务器之间虽然可以实现 RPC 调用,但是在传统的 web 应用方面通常不会这么做。我认为有两点原因: 1. 模式不通用:前端和后端要进行 RPC 通信必须要有一个通用的协议吧,而且是最好要基于 HTTP 的对吧。*传统*的前端不具备 socket 能力,甚至连二进制数据处理的能力都没有(高级浏览器除外),而且你还只能把客户端当成调用方,客户端并不具备提供服务的能力(除非浏览器层面支持额外功能)。 2. 高并发问题:如果不基于 HTTP 实现上也逃不了 socket 吧,那么你就要面临高并发的问题,服务器能建立的 socket 链接数和客户端的链接数量完全不在一个层级上 如果要实现,其实也不难。打开 telegram 的网页版,telegram 实现的点对点消息发送我猜测就是一种客户端和服务器之间的 RPC 调用,本质上讲他还是 http 请求,或者是基于 socket 的某种通信。 | 
|      56puilu      2020-03-28 13:26:11 +08:00 没听说过,看来不是个好东西 | 
|      57syzh      2021-04-06 10:30:25 +08:00 | 
|  |      58xmsz      2021-10-05 18:45:08 +08:00 只能说以前受限于用户环境兼容,包括现在也是 实现对接 grpc 本身很简单,就是基于 http/2 传输 但是基础环境跑不起来,还得考虑降级等操作,那这部分肯定费时费力 那么就需要大厂来搞和实现 所以需要一点时间慢慢来,这就和短视频和网络关系一样,你网络没升级,短视频肯定不行 | 
|  |      59chaleaochexist      2023-02-04 23:35:26 +08:00 @otakustay  感谢大佬, 所有回答数你最靠谱. 收获很多. 歪楼请教另一个问题: 为什么服务和服务内部通信要用 RPC(GRPC)? GRPC 为什么流行? 对比 HTTP2 有什么优势? 无论跨语言还是效率我觉得都站不住脚. SDK? 也无法理解. 谢谢. |