RPC与REST
RPC与REST
- 访问远程服务
- 1远程服务调用(Remote Procedure Call,RPC):RPC 解决什么问题?如何解决的?为什么要那样解决?
- 1.1 先解决两个进程间如何交换数据的问题,也就是进程间通信(Inter-Process Communication,IPC)。可以考虑的办法有以下几种:
- 1.2 通信的成本
- 1.3 三个基本问题
- 1.4 统一的 RPC 与 分裂的 RPC
- 2 REST 设计风格
- 2.1 理解 REST
- 2.2 RESTful 的系统
访问远程服务
远程服务将计算机的工作范围从单机扩展到网络,从本地延伸至远程,是构建分布式系统的首要基础。
而远程服务又不仅仅是为了分布式系统服务的,在网络时代,浏览器、移动设备、桌面应用和服务端的程序,普遍都有与其他设备交互的需求,所以今天很难找到没有开发过远程服务的人,但是没有正确理解远程服务的coder比比皆是。
1远程服务调用(Remote Procedure Call,RPC):RPC 解决什么问题?如何解决的?为什么要那样解决?
进程间通信:尽管今天的大多数RPC 已经不再追求这个目标了,但无可否认,在最初的时候,这是先要解决的:让调用远程方法和本地方法一样。
1.1 先解决两个进程间如何交换数据的问题,也就是进程间通信(Inter-Process Communication,IPC)。可以考虑的办法有以下几种:
- 管道或具名管道:管道类似于两个进程间的桥梁,可通过管道在进程间传递 少量的字符流或字节流。普通管道只用于有亲缘关系的进程(由一个进程启动的另外一个进程)间通信。具名管道拜托了普通管道没有名字的限制,除具有普通管道的所有功能外,它还允许无亲缘关系进程间的通信。管道典型的应用就是命令行中的 | 操作符,如:
ps -ef | grep java
ps 与 grep 都有独立的进程,以上命令就是将ps 的标准输出链接到grep 的标准输入上。 - 信号(signal):用于通知目标进程有某事发生,除了用于进程间通信外,进程还可以发送信号给进程自身。信号的典型命令就是 kill 命令:
kill -9 pid
- 信号量(Semaphore):信号量用于两个进程间同步协作手段,它相当于操作系统提供的一个特殊变量,程序可以在上面进行 wait() notify() 操作。
- 消息队列:以上三种方式只适合传递少量信息,消息队列用于进程间数据量较多的通信。进程可以向队列添加消息,被赋予读权限的进程可以消费消息,MQ 克服了信号承载量小,管道只能用于无格式字节流以及缓冲区大小受限的缺点,但实时性相对受限。
- 共享内存(Shared Memory) :允许多个进程访问同一块公共的内存空间,这是效率最高的进程间通信方式。当一块进程被多进程共享时,各个进程往往会与其他通信机制,如信号量结合使用。
- 套接字接口(Socket):消息队列和共享内存只适合于单机多进程间的通信,套接字接口是更为普适的进程间通信机制,可用于不同机器之间的进程通信。套接字(socket)当仅限于本机进程间通信时,套接字接口是优化过的,不会经过网络协议栈,不需要打包拆包、计算校验和等,只是简单的将应用层数据从一个进程拷贝到另一个进程。这种进程间通信叫 IPC Socket。
1.2 通信的成本
IPC Socket 不仅适用于本地相同机器间不同进程间的通信,由于 Socket 网络栈的统一接口,它也理所应当的能支持基于网络的跨机器进程间通信。这么做有一个看起来无比诱人的好处,由于 Socket 是各个操作系统都有提供的标准接口,完全有可能把远程方法调用的通信细节隐藏在操作系统底层,从应用层面商看来可以做到远程调用与本地的进程间通信在编码上完全一致。事实上,在原始分布式时代的确是这么用的,但这种透明的调用形式却反问滥用以至于显著降低了分布式系统的性能。
所以,对 RPC 提出一系列的疑问:
- 两个进程间通信,谁作为客户端,谁作为服务端?
- 怎样进行异常处理,如何让调用者获知?
- 服务端出现多线程竞争后改怎么办?
- 如何提高网络利用的效率?比如连接是否可以被多个请求复用以减少开销,是否支持多播?
- 参数、返回值如何表示?应该有怎样的字节序?
- 如何保证网络的可靠性?
- 发送的请求服务端收不到回复怎么办?
…
这里的中心观点是:本地调用与远程调用当做一样处理,这是犯了方向性的错误。
Sun 公司的一众大佬们总结了通过网络记性分布式运算的八宗罪:
- 网路是可靠的,安全的,同质化的;(这是三点)
- 延迟是不存在的;
- 带宽是无限的;
- 拓扑结构是一成不变的;
- 总会有一个管理员;
- 不必考虑传输成本。
以上八大问题潜台词就是说如果远程服务调用要弄透明化的话,就必须为这些罪过埋单(就是RPC不能透明化)。这算是给 RPC 是否能等同于 IPC 正式定下了一个具有公信力的结论。至此,RPC 应该是一种高层次的或者说语言层次的特征,而不是像 IPC 那样,是低层次的货系统层次的特征成为工业界、学术界的主流观点。
RPC 的定义:远程服务调用是指位于互不重合的内存地址空间中的两个程序,在语言层面上,以同步的方式使用有限带宽的信道来传输程序控制信息。
1.3 三个基本问题
RPC 协议无外乎变着花样使用各种手段来解决以下三个基本问题:
- 如何表示数据:这里的数据包含了传递给方法的参数,以及方法执行后的返回值。不同进程间数据读取问题。且 RPC 完全可能绵连交互双方各自使用不同程序语言的情况:即使是用了相同语言的 RPC 协议,在不同硬件指令集、不同OS下,同样的数据类型也完全可能有不一样的表现细节,如数据宽度、字节差异等。有效的做法是:将交互双方所涉及的数据转换为某种事先约定好的中立数据流格式来进行传输,将数据流转换回不同语言中对应的数据类型来进行使用,就是序列化与反序列化。每种 RPC 协议都要有对应的序列化协议,如 gRPC Protocol Buffers,其他众多轻量级 RPC 的 JSON Serialization。
- 如何传输数据:指如何通过网路,在两个服务的 Endpoint 间相互操作、交换数据。这里的“交换数据”通常指的是应用层协议,实际传输一般是基于标准的 TCP、UDP 等标准的传输层协议来完成的。两个服务交互不只是扔个序列化数据就行,还需有异常、超时、安全、认证、授权、事务等,这些都可能是双方需交换的。这类数据叫:Wire Protocol。常见的有:Java RMI 的 JRMP,Web Service 的 SOAP,如果要求足够简单,双方都是 HTTP Endpoint,就可直接使用 HTTP 协议(如 JSON-RPC)。
- 如何确定方法:这在本地方法调用中不是太大问题,编译器会根据语言规范,将调用的方法签名转换为进程空间中子过程入口位置的指针。不过一旦要考虑不同语言,事情又麻烦起来,每门语言的方法前面可能不同,所以“如何表示同一个方法”,“找到对应的方法”还是得弄个跨语言的统一标准。这个标准非常简单,如直接给程序的每个方法都规定一个唯一的、在任何机器上都绝不重复的编号,直接找对应方法。这是当初DCE 的解决方案,就是 UUID,虽然此后DCE 还是弄了一套语言无关的接口描述语言(Interface Description Language,IDL),但 UUID 却广为流传。用于表示方法的协议:Web Service 的 WSDL,JSON-RPC 的JSON-WSP。
1.4 统一的 RPC 与 分裂的 RPC
刚开始的时候,大家总是尝试 RPC 可以解决所有分布式问题,如刚开始的时候既要支持面向对象,又要支持多种语言,功能还齐全。但是没有一家成功的,简单、普适、高性能这三点,似乎真的难以同时满足。所以现在的 RPC 仍处于百家争鸣的时代,大家都不再去追求大而全的“完美”,而是有自己的针对性作为主要的发展方向。如:
- 面向对象发展的 RMI等;
- 朝着性能发展的,如 gRPC 和 Thrift,决定 RPC 性能的主要两个因素:序列化效率和信息密度。序列化效率指输出结果容量小,速度快,效率自然高;信息密度则取决于协议中有效负载(Payload)所占总传输数据的比例大小,使用传输协议的层次越高,信息密度越低,SOAP 使用XML拙劣的性能表现就是前车之鉴。gRPC 和 Thrift 都有自己优秀的专有序列化器,而传输协议方面,gRPC 是基于 HTTP/2 的,支持多路复用和 Header 压缩,Thrift 则直接基于传输层的 TCP 协议来实现,省去了额外应用层协议的开销。
- 朝着简化发展:代表为 JSON-RPC,要说功能最强、速度最快的 RPC 可能会很有争议,但选功能弱的、速度慢的,JSON-RPC 肯定会在候选人之一。牺牲了功能和效率,换来的是协议的简单轻便,接口与格式都更为通用,尤其适合用于 Web 浏览器这类一般不会有额外协议支持、额外客户端支持的应用场合。
到了最近几年,RPC 框架有明显的朝着更高层次(不仅负责调用远程服务,还要管理远程服务)与插件化方向发展的趋势,不再追求独立地解决 RPC 的全部三个问题(表示数据、传递数据、表示方法),而是将一部分功能设计成扩展点,让用户自己去选择。框架聚焦于提供核心的、更高层次的能力,如提供负载均衡、服务注册、可观察性等方面的支持。这一类框架的代表有 Facebook 的 Thrift 和阿里的 Dubbo。尤其是断更多年后重启的 Dubbo 表现得更为明显,它默认有自己的传输协议(Dubbo协议),同时也支持其他协议;默认采用 Hessian2 作为序列化器,如果你有 JSON 需求,可以替换为 Fastjson,如你对性能有更高的追求,可以替换为 Kryo、Protocol Buffers 等效率更好的序列化器,如果你不想依赖其他组件库,直接使用 JDK 自带的序列化器也是可以的。
开发一个分布式系统,是不是一定要用 RPC 呢?
2 REST 设计风格
很多人会拿 REST 与 RPC 互相比较,其实,REST 无论是在思想上、概念上,还是适用范围上,与 RPC 都不尽相同,充其量只能算有些相似,但本质上并不是同一类型的东西。
2.1 理解 REST
个人会有好恶偏爱,但计算机科学是务实的,有了RPC还会提出REST,有了面向过程编程还能产生面向资源编程,后者总会有些前者没有的闪光点,我们先理解 REST,在谈论评价它。
比较容易理解 REST 思想的途径是先理解什么是 HTTP,再配合一些实际例子来进行类比,你会发现REST(Representational State Transfer)实际是 HTT(Hypertext Transfer)的进一步抽象,两者就如同接口与实现类的关系一般。
Hypertext 超文本一词已被普遍接受,它指的是能够进行分支判断和差异响应的文本,相应地,超媒体指的是能够进行分支判断和差异响应的图形、电影和声音(也包括文本)的复合体。就是指文字可以点击、可以出发脚本等。
下面从“超文本”或“超媒体”的含义来理解 REST 中的相关概念:
-
资源(Resource)比如你在阅读的一篇文章,其内容本身就是资源;
-
表征(Representation)当你通过电脑浏览阅读此文章时,浏览器向服务端发出请求“我需要这个资源的HTML 格式”,服务端向浏览器返回的这个 HTML 就是表征,或者是文本的 PDF、Markdown等都是,即表现形式。
-
状态(State)当你读完了这篇文章,想看后面是什么内容时,你想服务器发送“下一篇文章”的请求,但服务端不知道下一篇是哪一篇,就得根据你现在的上下文信息来判断,以来的就是状态;
-
转移(Transfer)无论状态是由服务端还是客户端来提供,“取下一篇文章”这个行为必然只能由服务端来提供,服务端通过某种形式,把当前文章转变为下一篇,这就叫“表征状态转移”。
-
统一接口(Uniform Interface)前面提到的下一篇的点击跳转,这是一种让表征状态发生转移的方式,但是 URI 的含义是统一资源标识符,是一个名词,如何表达出“转移”的含义的呢?答案是 HTTP 协议中已经提前约定好了一套“统一接口”,它包括:GET、HEAD POST PUT DELETE TRACE OPTIONS七种基本操作,任何一个支持 HTTP协议的服务器都会遵守这套规定,对特定的 URI 采取这些操作,服务器就会触发相应的表征状态转移的动作。
-
超文本驱动(Hypertext Driven)任何网站的导航(状态转移)行为都不可能是预置于浏览器代码之中,而是由服务器发出的请求响应信息(超文本)来驱动的。
-
自描述信息 消息的类型以及应如何处理这条消息。如 Content-Type:application/json;charset=utf-8
2.2 RESTful 的系统
理解了上面的概念,我们就可以开始讨论面向资源的呢编程思想与几个具体的软件架构设计原则了。一套完整的、完全满足 REST 风格的系统应满足以下六大原则:
- 服务端与客户端分离(Client-Server)将用户界面所关注的逻辑和数据存储所关注的逻辑分离开来,有助于提高用户界面的跨平台的可移植性。
- 无状态(Stateless)无状态是 REST 的一条核心原则,部分开发者在做接口规划时,觉得 REST 风格的服务怎么设计都感觉别怒,很有可能的一种原因是在服务端持有着比较重的状态。应由客户端承担状态维护职责,但目前大多数系统都达不到这个要求。
- 可缓存(Cacheability)无状态服务虽然提升了系统的可见性、可靠性和可伸缩性,但降低了系统的网络性。“降低网络性”是指某个功能如果使用有状态的设计只需一次(或少量)请求即可完成,而无状态的得多次。为了缓解这个矛盾,REST 希望软件系统能入万维网一样,允许客户端和中间的通讯传递者(如代理)将部分服务端的应答缓存起来。
- 分层系统(Layered System)这里的分层并不是表示层、服务层、持久层这种,而是客户端一般不用知道是否直接连接到了最终的服务器,或中间服务器。中间服务器可以通过负载均衡和共享缓存的机制提高系统的可扩展性,这样也便于缓存、伸缩和安全策略的部署。该原则的典型应用是内容分发网络。如我们浏览某个网站,并不是直接访问源服务器,而是访问了某个 CDN 服务器。
- 统一接口(Uniform Interface)这是 REST 的另一条核心原则,REST 希望开发者面向资源编程,希望软件系统设计的重点放在抽象系统该有哪些资源上,而不是抽象系统该有哪些行为上。这条原则可以类比计算机中对文件管理的操作来理解,管理文件的操作是可数的,而且对所有文件都是固定的,统一的。如果面向资源来设计系统,同样会有类似的操作特征,所有这些操作都借用了HTTP协议中固有的操作命令来完成。因为面向资源编程的抽象程度更高。想要在架构设计中合理恰当的利用统一接口,系统应能做到每次请求中都包含资源的ID,所有操作均通过资源ID 来进行;建议每个资源都是自描述的消息;建议通过超文本来驱动应用状态的转移。
- 按需代码(Code-On-Demand)可选原则。
本节开篇提出的 REST 与 RPC 在思想上的差异?
REST 的基本思想是面向资源来抽象问题,它与此前流行的面向过程的编程在抽象主体上有本质区别。在 REST 提出以前,人们设计分布式系统的唯一方案就只有 RPC,开发者是围绕着“远程方法”去设计两个系统交互的,这样做的坏处不仅是“如何在不同系统间表示一个方法”、“如何获得接口能够提供的方法清单”都成了需要专门协议去解决的问题,更在于服务的每个方法都是独立的,服务者必须熟悉每个方法才能使用,而REST抽象为了几类
相关文章:

RPC与REST
RPC与REST 访问远程服务1远程服务调用(Remote Procedure Call,RPC):RPC 解决什么问题?如何解决的?为什么要那样解决?1.1 先解决两个进程间如何交换数据的问题,也就是进程间通信&…...

计数排序的实现
原理 对一个数组进行遍历,再创建一个count数组 每找到一个值则在count数组中对应的位置加一,再在count数组中找到数字上方的count值,count值为几,则打印几次数组中的值. 开空间 相对映射 排序的实现 void CountSort(int* a, i…...

【Qt】QTableWidget设置可以选择多行多列,并能复制选择的内容到剪贴板
比如有一个 QTableWidget*m_tbwQuery m_tbwQuery->installEventFilter(this); //进行事件过滤处理//设置可以选择多行多列 m_tbwQuery->setSelectionMode(QAbstractItemView::MultiSelection); m_tbwQuery->setSelectionBehavior(QAbstractItemView::SelectItems); …...

跨越界限的温柔坚守
跨越界限的温柔坚守 —— 郑乃馨与男友的甜蜜抉择在这个光怪陆离、瞬息万变的娱乐圈里,每一段恋情像是夜空中划过的流星,璀璨短暂。然而,当“郑乃馨与男友甜蜜约会”的消息再次跃入公众视野,它不仅仅是一段简单的爱情故事…...

Vue3 对于内嵌Iframe组件进行缓存
1:应用场景 对于系统内所有内嵌iframe 的页面均通过同一个路由/iframe, 在router.query内传入不同src 参数,在同一组件内显示iframe 内嵌页面,对这些页面分别进行缓存。主要是通过v-show 控制显示隐藏从而达到iframe 缓存逻辑 2:…...

L04_MySQL知识图谱
这些知识点你都掌握了吗?大家可以对着问题看下自己掌握程度如何?对于没掌握的知识点,大家自行网上搜索,都会有对应答案,本文不做知识点详细说明,只做简要文字或图示引导。 1 基础 1.1内部组件结构 1.2 数据…...

什么是CNN,它和传统机器学习有什么区别
CNN,全称为卷积神经网络(Convolutional Neural Networks),是一种专门用于处理具有网格结构数据(如图像、视频)的深度学习模型。它由多个卷积层、池化层、全连接层等组成,通过卷积运算和池化操作…...

游戏开发面试题3
unity如何判断子弹射击到敌人,如果子弹特别快怎么办 使用物理学碰撞检测。使用Unity的物理组件,如Rigidbody和Collider,将子弹和敌人都设置为有一定的物理碰撞属性,当子弹碰到敌人的时候,就会触发OnCollisionEnter()事…...

postman请求访问:认证失败,无法访问系统资源
1、使用postman时,没有传入相应的token,就会出现这种情况,此时需要把token放进去 发现问题: { "msg": "请求访问:/getInfo,认证失败,无法访问系统资源", "code": 401 } 1…...

Apache Seata新特性支持 -- undo_log压缩
本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 Apache Seata新特性支持 – undo_log压缩 Seata新特性支持 – undo_log压缩 现状 & 痛点…...

Java中的软件架构重构与升级策略
Java中的软件架构重构与升级策略 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 重构与升级的背景和意义 软件架构在应用开发中起着至关重要的作用。随着技术…...

设置Docker中时区不生效的问题
项目中使用docker-compose,并通过以下方式设置了时区 environment:- SET_CONTAINER_TIMEZONEtrue- CONTAINER_TIMEZONEAsia/Shanghai 但是并没有正确生效,网上有很多博客都在推荐这个做法,另外一种是使用标准环境标量 -TZAsia/Shangehai …...

LeetCode436:寻找右区间
题目链接:436. 寻找右区间 - 力扣(LeetCode) class Solution { public:vector<int> findRightInterval(vector<vector<int>>& intervals) {vector<pair<int, int>> startIntervals;int n intervals.size…...

前端JS特效第22集:html5音乐旋律自定义交互特效
html5音乐旋律自定义交互特效,先来看看效果: 部分核心的代码如下(全部代码在文章末尾): <!DOCTYPE html> <html lang"en" > <head> <meta charset"UTF-8"> <title>ChimeTime™</title…...

pyrender 离线渲染包安装教程
pyrender 离线渲染包安装教程 安装 安装 官方安装教程:https://pyrender.readthedocs.io/en/latest/install/index.html#installmesa 首先 pip install pyrenderclang6.0安装 下载地址:https://releases.llvm.org/download.html#6.0.0 注意下好是叫:clangllvm-6…...

XSS平台的搭建
第一步:安装MySQL 数据库 因为xss平台涉及到使用mysql 数据库,在安装之前,先使用docker 安装mysql 数据库。 docker run --name mysqlserver -e MYSQL_ROOT_PASSWORD123 -d -i -p 3309:3306 mysql:5.6 第二步:安装xssplatform…...

【持续集成_03课_Jenkins生成Allure报告及Sonar静态扫描】
1、 一、构建之后的配置 1、安装allure插件 安装好之后,可以在这里搜到已经安装的 2、配置allure的allure-commandline 正常配置,是要么在工具里配置,要么在系统里配置 allure-commandline是在工具里进行配置 两种方式进行配置 1ÿ…...

PageHelper分页查询遇到的小问题
如果我们是这样子直接查询 pagehelper会拼接导我们的sql语句之后 这样子我们搜索出来的list,就是里面参杂了PageHelper的东西 所以我们可以直接转成我们的Page类型 但是如果我们搜索出来的是List<Blog>,我有些信息不想返回给前端,所以…...

【Python】组合数据类型:序列,列表,元组,字典,集合
个人主页:【😊个人主页】 系列专栏:【❤️Python】 文章目录 前言组合数据类型序列类型序列常见的操作符列表列表操作len()append()insert()remove()index()sort()reverse()count() 元组三种序列类型的区别 集合类型四种操作符集合setfrozens…...

algorithm算法库学习之——不修改序列的操作
algorithm此头文件是算法库的一部分。本篇介绍不修改序列的操作函数。 不修改序列的操作 all_ofany_ofnone_of (C11)(C11)(C11) 检查谓词是否对范围中所有、任一或无元素为 true (函数模板) for_each 应用函数到范围中的元素 (函数模板) for_each_n (C17) 应用一个函数对象到序…...

idea创建的maven项目pom文件引入的坐标报红原因
如下所示 我们在引入某些依赖坐标的时候,即使点击了右上角的mavne刷新之后还是报红。 其实这是正常现象,实际上是我们的本地仓库当中没有这些依赖坐标,而idea就会通过报红来标记这些依赖来说明在我们的本地仓库是不存在的。 那有的同学就会…...

Python面试题:Python 中的生成器(generator)是什么?有什么优点?
在Python中,生成器(generator)是一种特殊的迭代器,使用yield关键字生成值,可以逐个生成序列中的值,而不需要一次性将所有值加载到内存中。生成器函数在定义时使用def关键字,并包含一个或多个yie…...

Go语言--复合类型之map、结构体
map Go 语言中的 map(映射、字典)是一种内置的数据结构,它是一个无序的 key-value 对的集合,比如以身份证号作为唯一键来标识一个人的信息。 格式 map [keyType]valueType 在一个 map 里所有的键都是唯一的,而且必须是支持和!操作符的类型…...

Stable Diffusion图像的脸部细节控制——采样器全解析
文章目录 艺术地掌控人物形象好易智算原因分析为什么在使用Stable Diffusion生成全身图像时,脸部细节往往不够精细? 解决策略 局部重绘采样器总结 艺术地掌控人物形象 在运用Stable Diffusion这一功能强大的AI绘图工具时,我们往往会发现自己…...

CurrentHashMap巧妙利用位运算获取数组指定下标元素
先来了解一下数组对象在堆中的存储形式【数组长度,数组元素类型信息等】 【存放元素对象的空间】 Ma 基础信息实例数据内存填充Mark Word,ClassPointer,数组长度第一个元素第二个元素固定的填充内容 所以我们想要获取某个下标的元素首先要获取这个元素的起始位置…...

实现antd designable平台的组件拖拽功能
平台:designable设计器 github:designable 目录 1 背景2 技术栈3 组件拖拽和放置3.1 类型定义3.2 拖拽3.3 放置 1 背景 由于业务需求,我们需要实现designable平台的一个简易版的组件拖拽功能。 #mermaid-svg-QrxSDGe9YyGG3LbQ {font-family:…...

计算机网络-IP组播基础
一、概述 在前面的学习交换机和路由协议,二层通信是数据链路层间通信,在同一个广播域间通过源MAC地址和目的MAC地址进行通信,当两台主机第一次通信由于不清楚目的MAC地址需要进行广播泛洪,目的主机回复自身MAC地址,然后…...

Git删除了文件拉取时失败
本地删除了一些文件,远端的另一个提交修改了被删除的文件,vs里拉取时提示未处理的提交,无法继续操作,git gui里显示很多unstaged change的项 解决办法: 1、用git bash的git rm --cached filename或 git rm -r --cached…...

【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(十二)-管道、环境变量、常用命令
大致介绍了一下管道、环境变量、一些常用的基本命令,可以当作学习笔记收藏学习一下!!! 文章目录 前言 一、管道 二、环境变量 1.概念 2.查看 3.修改 4.常用环境变量 三、系统状况 总结 前言 大致介绍了一下管道、环境变量、一些常…...

Spring Boot与Apache Kafka Streams的集成
Spring Boot与Apache Kafka Streams的集成 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 一、Apache Kafka Streams简介 Apache Kafka Streams是一个用于构…...