微服务调用为什么用RPC框架,http不更简单吗?

HTTP 是网络协议,而RPC 可以看做是一种编程模式或实现方案。

RPC 通常包含传输协议和序列化协议,单说传输协议,RPC 可以建立在 TCP 协议之上(比如 Dubbo),也可以建立在 HTTP 协议之上(比如 gRPC);如果是基于数据形式分类,RPC 又可以分成基于二进制、XML 和 JSON 三种;

而现在非常流行的开源 RPC 框架,比如Dubbo 和 gRPC 分别出身于阿里和谷歌,它们更多地是封装了服务注册发现、负载均衡、链路跟踪等功能,可以理解为,RPC 框架是对服务更高级的封装。

如果把一个http server容器上封装一层服务发现和函数代理调用,那它就已经可以做一个rpc框架了。

良好的rpc调用是面向服务的封装,针对服务的可用性和效率等都做了优化。单纯使用http调用则缺少了这些特性。

而两者其实各有千秋,在性能方面,RPC肯定是占优势的,但至于这种优势有多大意义,涉及到的情况就很多了,比如并发,数据量等等。而其他一些方面,比如安全性,开发成本,适用性等方面,可能http优势更大。

RPC,远程过程调用,通过网络从远程计算机程序上请求服务。浏览器请求 web 服务完成可以理解为就是 RPC 调用,现在你搞清楚了吗?RPC 是概念名词,http 是数据传输协议,这两者是不同的。我们来看看市面上的一些 RPC 框架

  1. gRPC,支持的传输协议 http/2
  2. dubbo,支持的传输协议 Dubbo,http 等

接下来顺便讲下 RPC 框架一般会有的功能

  1. 服务注册,微服务启动起来后,肯定要告诉下服务注册中心,本服务已经启动起来
  2. 服务发现,通过服务注册中心拿到所有启动起来的服务的服务地址
  3. 客户端负载均衡,我现在通过服务注册中心拿到一组服务地址了,总得选择一个,那么应该选择哪个?这时候就需要依赖于负载均衡算法了
  4. 传输协议,数据传输前自然是要序列化,然后通过客户端与服务端都支持的协议进行交流,协议可以是自研的协议,也可以是 http 协议

RPC 框架的设计自然不止我讲的这些,但是作为了解其实已经足够了

首先微服务也有用http的,现在流行的feign,底层就是http,也是我们经常提到的restful编程方式。

Rpc在国内最具有代表的是dubbo,底层可以选择netty进行通讯,速度肯定是比http快的。

但是微服务不是一个简单的调用,涉及到很多方面,比如容错,高并发,熔断,事务等等。普通的http代码是无法解决这些问题的。一般需要很多组件来配合,比如feign就要配合robbin,hystrix等来配合,dubbo也需要zookeeper来配合。

所以这两者在我们的开发中,都很常见。

RPC:Remote Procedure Call,中文意思就是远程过程调用。

那么我们先看看题目中的问题,其实,这个问题本身就是有问题的!

01. 既然有 HTTP ,为什么还要用 RPC ?

HTTP 和 RPC 并不是两个并行的概念,虽然很多书或文章,都介绍 HTTP 和 RPC 是在“应用层”,但实际上可以把应用层细分成多层,RPC 的所处的位置是高于 HTTP 的;HTTP 是网络协议,而RPC 可以看做是一种编程模式或实现方案;

RPC 通常包含传输协议和序列化协议,单说传输协议,RPC 可以建立在 TCP 协议之上(比如 Dubbo),也可以建立在 HTTP 协议之上(比如 gRPC);如果是基于数据形式分类,RPC 又可以分成基于二进制、XML 和 JSON 三种;

而现在非常流行的开源 RPC 框架,比如上文中提到的Dubbo 和 gRPC 分别出身于阿里和谷歌,它们更多地是封装了服务注册发现、负载均衡、链路跟踪等功能,也可以这么理解,RPC 框架是对服务更高级的封装。

02. RPC VS Restful 风格的 API

如果非要比较的话,可以比较 RPC 和 Restful 风格的 API。

  • RPC:面向过程,也就是要做一件什么事情,只发送 GET 和 POST 请求;GET 用来查询信息,其他情况下一律用 POST;请求参数是动词。

  • RESTful:面向资源,这里的资源可以是一段文字、一个文件、一张图片,总之是一个具体的存在,可以使用 GET、POST、DELETE、PUT 请求,对应了增删查改的操作;请求参数是名词。

比如按照id 查找用户:

  • 如果是 RPC 风格的 url 应该是这样的:GET /queryUser?userid=xxx;

  • 而 RESTful 风格通常是这样的:GET /user/{userid}

03. 究竟选择哪一个?

RPC 特别适用于是分布式环境;它让客户端进行远程调用时,可以像调用本地方法一样方便;RPC 框架屏蔽了很多底层的细节,开发人员不需要关注这些细节,比如序列化和反序列化、网络传输协议;一些功能强大的 RPC 框架还提供了连接池管理、负载均衡、故障转移、超时管理、上下文管理器、异步回调、收发包队列、工作线程等功能。

RPC 和 Restful 风格的 API,如果非要争出来个第一第二,那么也要结合具体的使用场景,选择更适合的那个。

如果是偏向内部的 API,提供的 API 很难进行资源的抽象,没有规范的 API 的设计,性能要求更高,这些情况下更适合使用 RPC ;如果偏向外部 API,需要有更为规范的 API 设计,并且 API 天生是以资源为维度展开的,这时候可以选择 Restful 风格的 API。

我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。

RPC名称是远程服务调用。这里面实际是没有限制一定会是tcp,也可以是http或者其他基于tcp协议的服务。

远程服务调用,有多种 ,http的接口调用,基于http的webservice,java中的rmi 实际都算是rpc。为什么都向长连接改动。是因为技术性能的要求越来越高,必然带来这样的发展趋势。

http接口,简单通用,但是调用放需要编写大量的代码去解析返回结果,并且http性能并不高效,除了header的问题之外,早期的http还不能多路复用。

webservice实际上是http协议之上的封装,它更多是为了解决http接口调用需要编写大量客户端解析参数代码产生的,它能帮助少写代码,但无法改善http的性能。

java的rmi 典型的就是ejb 现在新的java程序员可能都没听过这玩意,这也是基于长连接实现,基于java的序列化。它能够解决客户端参数解析的问题,也能多路复用socket 但是ejb本身的复杂性以及java序列化低效的问题导致它也是被放弃,并且它是不能跨语言的。

现在的rpc框架大多都是基于socket长连接,自定义协议实现。采用的序列化方式也会比较高效和跨语言。比如grpc 采用protobuf做序列化,采用http2做传输协议。

从某种意义上来讲,http接口也能算是rpc调用,只是需要更具开发工作量以及性能指标做技术抉择。

学习编程是不是要多敲代码?

我没学过编程,也很想学习编程,因此看到此问题也想问各位高手一起讨论

我理解的编程,应是一个创作过程。当然这过程是根据创作作品的难易来确定时间周期与工作量。

敲代码应是创作过程的一种体现。就算写一篇小说,码字是一个写作过程的体现。

因此我理解的学编程的重点应是创作作品的架构搭建与逻辑疏理。就象一部电影,一部小说,架构及呈现逻辑才是能否产出好作品的关键。

因此,我理解敲代码只是编程中最基础的部分。当然,多敲代码对熟悉编程应有帮助,但不是其的重点。

行外汉胡言乱语,不知是否有这点逻辑,望指正

学习编程自然是需要多写代码的

这应该不光是编程吧,我们学任何东西都是一样的。我如果要学习设计,那一定是经常勾勾画画,CoreDraw、Photoshop那一定是经常用,把很多常用的快捷键都记住,最后融会贯通。如果不经常联系使用,那估计画直线都不一定能画好。

编程自然也是一样,因为语言本身其实并没有什么太大的难度,但是将语言编程一种工具,中间的过程并不是看看书,冥想一下就可以实现的。

作为一个程序员,其实我们在编程过程中用到最多的功能就是Debug。因为一个函数,可能包括是几百行甚至上千行代码,人的大脑是有极限的,你很难100%的确定几百上千行代码执行的过程中,你的大脑计算结果和程序的计算结果就是一模一样的。

所以,我们在编程的过程中,还有大量的时间是用来发现问题并解决问题。当我们发现问题,解决问题的过程中,我们又会学习到很多的经验和知识,未来我们再次面对类似的问题时,我们就能够很好的避免出现同样的错误。

而这个过程,一定是在不停的写代码,不停的Debug,不停的思考过程中所带来的成果。如果我们只是去看书,只是去在大脑里模拟书上的内容,其实是无法系统化的对程序进行了解的。换一种说法,现在让我们去写一篇论文,那么我们一定是先整理出大纲,然后在根据大纲补充内容,而补充内容的过程中我们也需要去尝试,去翻阅一些书籍。就算论文写出来了,后面也会有各种修改和补充,基本没有一步到位的论文。

如果现在,让我们不去写,也没有练习,只是通过“想”,就勾勒出一篇论文,这不是人力所能达到的范畴。所以,多写代码可以说是程序员成长最最基本的。

当然,如果仅仅是不停的写代码,也并不是就正确

学习一定不是一个闷头自己干自己的过程,很多的知识、很多的学习方法其实前人都已经总结出来了。写代码是通过实践和其他人的知识转化成为自己的一个过程,或者说是自己发现和印证自己理论的一个过程。

所以,我们在写代码之前,还需要多去看别人的优秀代码,然后通过读懂别人的代码,然后模仿别人的代码,最终实现自己能够写出这样的代码。

我也简单分析一下我个人曾经的学习经验吧:

就拿我以前学“领域驱动设计”时的情况来举例吧。我最开始是在一些技术讨论的QQ群里面第一次了解到的领域驱动设计,也就是DDD。当时我对于DDD还什么都不懂,于是对这种架构模式产生了浓厚的兴趣。

首先,我去了一些在线的知识库,了解了一些DDD的基本概念;

然后,在京东上买了两本书,《领域驱动设计模式、原理与实践》和《实现领域驱动设计 》。显示较快速的读了一下这两本书,不需要说记住这些知识,只是做一个大概的了解;

接着,就去开源社区里面去找别人的源代码,我当时看了好几个,其中一个是汤雪华的Enode,还有一些外国人的sampleCQRS之类的。自然看的时候,又会遇到一些疑问,汤雪华的开源项目是有一个QQ讨论群的,所以大家可以在里面提问和探讨。而一些开源项目就没有这么方便,那么遇到问题时,就可以把之前买的书找出来,对照知识点自己理解一下;

最后,自然就是自己动手写代码了。我个人会选择先模仿,就是看别人的代码,理解一下,在自己去写。写的过程中思考,如果是我,我能怎么去优化或者封装一下。最后,当自己基本理解透彻以后,就完全按照自己的思想写一个小东东出来。

所以,我学习的方法基本就是先了解知识域,然后在写代码的过程中慢慢学习,慢慢提高。写代码的过程是必不可少的,而且可以说是花时间最多的,因为很多知识点,不自己动手做一下,很难能够理解为什么?