架构设计:如何实现一个高性能分布式 RPC 框架

2023-05-16

在前面的课程中,我们由浅入深地讲解了 Netty 的基础知识和实现原理,并对 Netty 的核心源码进行了剖析,相信你已经体会到了 Netty 的强大之处。本身学习一门技术是一个比较漫长的过程,恭喜你坚持了下来。纸上得来终觉浅,绝知此事要躬行。你是不是已经迫不及待想在项目中使用 Netty 了呢?接下来我会带着你完成一个相对完整的 RPC 框架原型,帮助你加深对 Netty 的理解,希望你能亲自动手跟我一起完成它。

我先来说说,为什么要选择 RPC 框架作为实战项目。RPC 框架是大型企业高频使用的一种中间件框架,用于解决分布式系统中服务之间的调用问题。RPC 框架设计很多重要的知识点,如线程模型、通信协议设计、同步/异步调用、负载均衡等,对于提高我们的技术综合能力有非常大的帮助。

我们实战课需要达到什么样的目标呢?市面上有较多出名的 RPC 框架,例如 Dubbo、Thrift、gRPC 等,RPC 框架本身是非常负责的,我们不可能面面俱到,而是抓住 RPC 框架的核心流程以及必备的组件,开发一个功能比较丰富的小型 RPC 框架。麻雀虽小,五脏俱全。

在正式开始 RPC 实战项目之前,我们先学习一下 RPC 的架构设计,这是项目前期规划非常重要的一步。

RPC 框架架构设计

RPC 又称远程过程调用(Remote Procedure Call),用于解决分布式系统中服务之间的调用问题。通俗地讲,就是开发者能够像调用本地方法一样调用远程的服务。下面我们通过一幅图来说说 RPC 框架的基本架构。

Lark20210101-221749.png

RPC 框架包含三个最重要的组件,分别是客户端、服务端和注册中心。在一次 RPC 调用流程中,这三个组件是这样交互的:

  • 服务端在启动后,会将它提供的服务列表发布到注册中心,客户端向注册中心订阅服务地址;
  • 客户端会通过本地代理模块 Proxy 调用服务端,Proxy 模块收到负责将方法、参数等数据转化成网络字节流;
  • 客户端从服务列表中选取其中一个的服务地址,并将数据通过网络发送给服务端;
  • 服务端接收到数据后进行解码,得到请求信息;
  • 服务端根据解码后的请求信息调用对应的服务,然后将调用结果返回给客户端。

虽然 RPC 调用流程很容易理解,但是实现一个完整的 RPC 框架设计到很多内容,例如服务注册与发现、通信协议与序列化、负载均衡、动态代理等,下面我们一一进行初步地讲解。

服务注册与发现

在分布式系统中,不同服务之间应该如何通信呢?传统的方式可以通过 HTTP 请求调用、保存服务端的服务列表等,这样做需要开发者主动感知到服务端暴露的信息,系统之间耦合严重。为了更好地将客户端和服务端解耦,以及实现服务优雅上线和下线,于是注册中心就出现了。

在 RPC 框架中,主要是使用注册中心来实现服务注册和发现的功能。服务端节点上线后自行向注册中心注册服务列表,节点下线时需要从注册中心将节点元数据信息移除。客户端向服务端发起调用时,自己负责从注册中心获取服务端的服务列表,然后在通过负载均衡算法选择其中一个服务节点进行调用。以上是最简单直接的服务端和客户端的发布和订阅模式,不需要再借助任何中间服务器,性能损耗也是最小的。

现在思考一个问题,服务在下线时需要从注册中心移除元数据,那么注册中心怎么才能感知到服务下线呢?我们最先想到的方法就是节点主动通知的实现方式,当节点需要下线时,向注册中心发送下线请求,让注册中心移除自己的元数据信息。但是如果节点异常退出,例如断网、进程崩溃等,那么注册中心将会一直残留异常节点的元数据,从而可能造成服务调用出现问题。

为了避免上述问题,实现服务优雅下线比较好的方式是采用主动通知 + 心跳检测的方案。除了主动通知注册中心下线外,还需要增加节点与注册中心的心跳检测功能,这个过程也叫作探活。心跳检测可以由节点或者注册中心负责,例如注册中心可以向服务节点每 60s 发送一次心跳包,如果 3 次心跳包都没有收到请求结果,可以任务该服务节点已经下线。

由此可见,采用注册中心的好处是可以解耦客户端和服务端之间错综复杂的关系,并且能够实现对服务的动态管理。服务配置可以支持动态修改,然后将更新后的配置推送到客户端和服务端,无须重启任何服务。

通信协议与序列化

既然 RPC 是远程调用,必然离不开网络通信协议。客户端在向服务端发起调用之前,需要考虑采用何种方式将调用信息进行编码,并传输到服务端。因为 RPC 框架对性能有非常高的要求,所以通信协议应该越简单越好,这样可以减少编解码的性能损耗。RPC 框架可以基于不同的协议实现,大部分主流 RPC 框架会选择 TCP、HTTP 协议,出名的 gRPC 框架使用的则是 HTTP2。TCP、HTTP、HTTP2 都是稳定可靠的,但其实使用 UDP 协议也是可以的,具体看业务使用的场景。成熟的 RCP 框架能够支持多种协议,例如阿里开源的 Dubbo 框架被很多互联网公司广泛使用,其中可插拔的协议支持是 Dubbo 的一大特色,这样不仅可以给开发者提供多种不同的选择,而且为接入异构系统提供了便利。

客户端和服务端在通信过程中需要传输哪些数据呢?这些数据又该如何编解码呢?如果采用 TCP 协议,你需要将调用的接口、方法、请求参数、调用属性等信息序列化成二进制字节流传递给服务提供方,服务端接收到数据后,再把二进制字节流反序列化得到调用信息,然后利用反射的原理调用对应方法,最后将返回结果、返回码、异常信息等返回给客户端。所谓序列化和反序列化就是将对象转换成二进制流以及将二进制流再转换成对象的过程。因为网络通信依赖于字节流,而且这些请求信息都是不确定的,所以一般会选用通用且高效的序列化算法。比较常用的序列化算法有 FastJson、Kryo、Hessian、Protobuf 等,这些第三方序列化算法都比 Java 原生的序列化操作都更加高效。Dubbo 支持多种序列化算法,并定义了 Serialization 接口规范,所有序列化算法扩展都必须实现该接口,其中默认使用的是 Hessian 序列化算法。

RPC 调用方式

成熟的 RPC 框架一般会提供四种调用方式,分别为同步 Sync异步 Future回调 Callback单向 Oneway。RPC 框架的性能和吞吐量与合理使用调用方式是息息相关的,下面我们逐一介绍下四种调用方式的实现原理。

Sync 同步调用。客户端线程发起 RPC 调用后,当前线程会一直阻塞,直至服务端返回结果或者处理超时异常。Sync 同步调用一般是 RPC 框架默认的调用方式,为了保证系统可用性,客户端设置合理的超时时间是非常重要的。虽说 Sync 是同步调用,但是客户端线程和服务端线程并不是同一个线程,实际在 RPC 框架内部还是异步处理的。Sync 同步调用的过程如下图所示。

1.png

  • Future 异步调用。客户端发起调用后不会再阻塞等待,而是拿到 RPC 框架返回的 Future 对象,调用结果会被服务端缓存,客户端自行决定后续何时获取返回结果。当客户端主动获取结果时,该过程是阻塞等待的。Future 异步调用过程如下图所示。

2.png

  • Callback 回调调用。如下图所示,客户端发起调用时,将 Callback 对象传递给 RPC 框架,无须同步等待返回结果,直接返回。当获取到服务端响应结果或者超时异常后,再执行用户注册的 Callback 回调。所以 Callback 接口一般包含 onResponse 和 onException 两个方法,分别对应成功返回和异常返回两种情况。

3.png

  • Oneway 单向调用。客户端发起请求之后直接返回,忽略返回结果。Oneway 方式是最简单的,具体调用过程如下图所示。

4.png

四种调用方式都各有优缺点,很难说异步方式一定会比同步方式效果好,在不用的业务场景可以按需选取更合适的调用方式。

线程模型

线程模型是 RPC 框架需要重点关注的部分,与我们之前介绍的 Netty Reactor 线程模型有什么区别和联系吗?

首先我们需要明确 I/O 线程和业务线程的区别,以 Dubbo 框架为例,Dubbo 使用 Netty 作为底层的网络通信框架,采用了我们熟悉的主从 Reactor 线程模型,其中 Boss 和 Worker 线程池就可以看作 I/O 线程。I/O 线程可以理解为主要负责处理网络数据,例如事件轮询、编解码、数据传输等。如果业务逻辑能够立即完成,也可以使用 I/O 线程进行处理,这样可以省去线程上下文切换的开销。如果业务逻辑耗时较多,例如包含查询数据库、复杂规则计算等耗时逻辑,那么 I/O 必须将这些请求分发到业务线程池中进行处理,以免阻塞 I/O 线程。

那么哪些请求需要在 I/O 线程中执行,哪些又需要在业务线程池中执行呢?Dubbo 框架的做法值得借鉴,它给用户提供了多种选择,它一共提供了 5 种分发策略,如下表格所示。

Lark20210101-221822.png

负载均衡

在分布式系统中,服务提供者和服务消费者都会有多台节点,如何保证服务提供者所有节点的负载均衡呢?客户端在发起调用之前,需要感知有多少服务端节点可用,然后从中选取一个进行调用。客户端需要拿到服务端节点的状态信息,并根据不同的策略实现负载均衡算法。负载均衡策略是影响 RPC 框架吞吐量很重要的一个因素,下面我们介绍几种最常用的负载均衡策略。

  • Round-Robin 轮询。Round-Robin 是最简单有效的负载均衡策略,并没有考虑服务端节点的实际负载水平,而是依次轮询服务端节点。
  • Weighted Round-Robin 权重轮询。对不同负载水平的服务端节点增加权重系数,这样可以通过权重系数降低性能较差或者配置较低的节点流量。权重系数可以根据服务端负载水平实时进行调整,使集群达到相对均衡的状态。
  • Least Connections 最少连接数。客户端根据服务端节点当前的连接数进行负载均衡,客户端会选择连接数最少的一台服务器进行调用。Least Connections 策略只是服务端其中一种维度,我们可以演化出最少请求数、CPU 利用率最低等其他维度的负载均衡方案。
  • Consistent Hash 一致性 Hash。目前主流推荐的负载均衡策略,Consistent Hash 是一种特殊的 Hash 算法,在服务端节点扩容或者下线时,尽可能保证客户端请求还是固定分配到同一台服务器节点。Consistent Hash 算法是采用哈希环来实现的,通过 Hash 函数将对象和服务器节点放置在哈希环上,一般来说服务器可以选择 IP + Port 进行 Hash,然后为对象选择对应的服务器节点,在哈希环中顺时针查找距离对象 Hash 值最近的服务器节点。

此外,负载均衡算法可以是多种多样的,客户端可以记录例如健康状态、连接数、内存、CPU、Load 等更加丰富的信息,根据综合因素进行更好地决策。

动态代理

RPC 框架怎么做到像调用本地接口一样调用远端服务呢?这必须依赖动态代理来实现。需要创建一个代理对象,在代理对象中完成数据报文编码,然后发起调用发送数据给服务提供方,以此屏蔽 RPC 框架的调用细节。因为代理类是在运行时生成的,所以代理类的生成速度、生成的字节码大小都会影响 RPC 框架整体的性能和资源消耗,所以需要慎重选择动态代理的实现方案。动态代理比较主流的实现方案有以下几种:JDK 动态代理、Cglib、Javassist、ASM、Byte Buddy,我们简单做一个对比和介绍。

  • JDK 动态代理。在运行时可以动态创建代理类,但是 JDK 动态代理的功能比较局限,代理对象必须实现一个接口,否则抛出异常。因为代理类会继承 Proxy 类,然而 Java 是不支持多重继承的,只能通过接口实现多态。JDK 动态代理所生成的代理类是接口的实现类,不能代理接口中不存在的方法。JDK 动态代理是通过反射调用的形式代理类中的方法,比直接调用肯定是性能要慢的。
  • Cglib 动态代理。Cglib 是基于 ASM 字节码生成框架实现的,通过字节码技术生成的代理类,所以代理类的类型是不受限制的。而且 Cglib 生成的代理类是继承于被代理类,所以可以提供更加灵活的功能。在代理方法方面,Cglib 是有优势的,它采用了 FastClass 机制,为代理类和被代理类各自创建一个 Class,这个 Class 会为代理类和被代理类的方法分配 index 索引,FastClass 就可以通过 index 直接定位要调用的方法,并直接调用,这是一种空间换时间的优化思路。
  • Javassist 和 ASM。二者都是 Java 字节码操作框架,使用起来难度较大,需要开发者对 Class 文件结构以及 JVM 都有所了解,但是它们都比反射的性能要高。Byte Buddy 也是一个字节码生成和操作的类库,Byte Buddy 功能强大,相比于 Javassist 和 ASM,Byte Buddy 提供了更加便捷的 API,用于创建和修改 Java 类,无须理解字节码的格式,而且 Byte Buddy 更加轻量,性能更好。

至此,我们已经对实现 RPC 框架的几个核心要点做了一个大致的介绍,关于通信协议、负载均衡、动态代理在 RPC 框架中如何实现,我们后面会有专门的实践课对其进行详细介绍,本节课我们先有个大概的印象即可。

总结

如果你可以完成上述 RPC 框架的核心功能,那么一个简易的 RPC 框架的 MVP 原型就完成了,这也是我们实践课的目标。当然实现一个高性能高可靠的 RPC 框架并不容易,需要考虑的问题远不止如此,例如异常重试、服务级别线程池隔离、熔断限流、集群容错、优雅下线等等,在实践课最后我会为你讲解 RPC 框架进阶的拓展内容。

转载于:架构设计

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

架构设计:如何实现一个高性能分布式 RPC 框架 的相关文章

  • 【Python学习教程】Python编程环境搭建

    文章目录 Windows安装Python xff08 图解 xff09 关于 IDLE Linux xff08 Ubuntu xff09 系统安装Python更新 Python 版本重新安装 Python1 下载源代码2 编译 小技巧 Ma
  • 【Python学习教程】Python变量类型和运算符

    文章目录 Python变量的定义和使用Python 变量的赋值Python 变量的使用Python 是弱类型的语言 Python整数类型 xff08 int xff09 详解关于 Python 2 x整数的不同进制1 十进制形式2 二进制形
  • 【Python学习教程】Python列表(list)、元组(tuple)、字典(dict)和集合(set)详解

    文章目录 什么是序列 xff0c Python序列详解 xff08 包括序列类型和常用操作 xff09 序列索引序列切片序列相加序列相乘检查元素是否包含在序列中和序列相关的内置函数 Python list列表详解Python创建列表1 使用
  • 手把手教用ROS做机器人控制(二)--加速度计与陀螺仪两种融合算法:mahony 互补滤波器算法与EKF算法

    对于加速计与陀螺仪融合 xff0c 介绍两种滤波算法 xff1a 他们的核心思想不太相同 xff0c 这两种方法现在也已经有了应用 xff0c 现在你可以发现互补滤波融合在无人机上 xff0c EKF我做过在平衡车上面 mathony主要思
  • 【Python学习教程】Python模块和包

    文章目录 什么是模块 xff0c Python模块化编程 xff08 入门必读 xff09 Python导入模块 xff0c Python import用法 xff08 超级详细 xff09 import 模块名 as 别名from 模块名
  • 【Python学习教程】Python字符串常用方法详解

    文章目录 Python字符串拼接 xff08 包含字符串拼接数字 xff09 Python字符串和数字的拼接str 和 repr 的区别 Python截取字符串 xff08 字符串切片 xff09 方法详解获取单个字符获取多个字符 xff0
  • 【Python学习教程】Python流程控制

    文章目录 Python if else条件语句详解if else 如何判断表达式是否成立 Python if else对缩进的要求不要忘记缩进缩进多少合适 xff1f 所有语句都要缩进同一代码块缩进量要相同不要随便缩进 Python if语
  • 【Python学习教程】Python函数和lambda表达式

    文章目录 Python函数 xff08 函数定义 函数调用 xff09 用法详解Python函数的定义Python函数的调用为函数提供说明文档 Python函数值传递和引用传递 xff08 包括形式参数和实际参数的区别 xff09 Pyth
  • 【Python学习教程】Python类和对象

    文章目录 什么是面向对象 xff0c Python面向对象 xff08 一切皆对象 xff09 面向对象相关术语 Python class xff1a 定义类 xff08 入门必读 xff09 Python类的定义 Python init
  • 最易学和最难学的编程语言Top 5

    文 白开水不加糖 出品 OSC开源社区 xff08 ID xff1a oschina2013 xff09 在线学习平台 Springboard 罗列了一个最容易学习和最难学的编程语言 Top 5 榜单 事实上 xff0c 问一个程序员最容易
  • 【Python学习教程】Python异常处理机制

    文章目录 什么是异常处理 xff0c Python常见异常类型 xff08 入门必读 xff09 Python语法错误Python运行时错误 Python异常处理机制到底有什么用 xff1f Python try except异常处理详解
  • 【NumPy教程】(快速入门版)

    文章目录 读者阅读条件 NumPy是什么NumPy使用需求NumPy应用场景 NumPy下载与安装Windows系统安装MacOSX系统安装Linux系统安装1 Ubuntu Debian2 Redhat CentOS NumPy ndar
  • Pillow(PIL)入门教程(非常详细)

    文章目录 相关资源 教程特点读者 amp 阅读条件 Pillow是什么Pillow版本支持Pillow库特点1 支持广泛的文件格式2 提供了丰富的功能3 配合GUI工具使用 Pillow的下载与安装pip包管理器安装二进制包安装Anacon
  • Tkinter教程

    文章目录 Tkinter教程 xff08 非常详细 xff09 教程特点阅读条件 GUI是什么GUI发展史GUI应用领域GUI的优势GUI开发工具 Tkinter是什么第一个Tkinter程序1 主窗口设置2 添加文本3 添加按钮4 独立运
  • 成功解决卡巴斯基6莫名其妙自动关闭的问题

    卡巴斯基6确实是个不错的杀毒工具 xff0c 但是安装好后 xff0c 会有个特别烦人的问题 xff0c 老是会提示错误 xff0c 然后自动关闭 xff0c 在网上查了一下 xff0c 终于找到了解决方案 解决步骤如下 xff1a 1 进
  • Tcl和Tk教程

    在Python Tkinter中 xff0c 重新了解到TCL和Tk 想起之前在做分子动力学模拟的时候 xff0c 有用到一个软件 xff0c 其命令行好像就是支持Tcl脚本 xff0c 当时对CS没那么了解 xff0c 所以也就没有深入了
  • Gromacs安装教程及一些思考

    写这篇博客目的当然不是只安装一下GROMAC xff0c 而是想借这个机会思考一下认知的问题 想起来刚上研究生的时候 xff0c 要在Linux服务器上安装这个软件 xff0c 当时费了好大劲 xff0c 各种求助师兄 xff0c 虽然安装
  • 如何高效地学习开源项目

    转载于 xff1a https time geekbang org column article 10022 你好 xff0c 我是华仔 今天这期 特别放送 xff0c 我想和你聊聊如何高效地学习开源项目 xff0c 一方面澄清开源项目学习
  • 52个数据可视化图表鉴赏

    文章目录 1 弧线图2 面积图3 箭头图4 条形图5 布林线指标6 箱线图7 气泡地图8 子弹图9 凹凸图10 日历图11 烛台图12 卡通图13 弦图14 分级统计图15 组合图表16 连接地图17 控制图18 南丁格尔玫瑰图19 交叉表
  • 【程序员学理财】不同产业的市场规模

    程序员学理财 不同产业的市场规模 先来了解一些常识 三大产业 第一产业主要指生产食材以及其它一些生物材料的产业 xff0c 包括种植业 林业 畜牧业 水产养殖业等直接以自然物为生产对象的产业 xff08 泛指农业 xff09 第二产业主要指

随机推荐

  • 【程序员学理财】有哪些普通人应该知道的经济学常识?

    文章目录 一 前言二 宏观经济学1 名词定义2 主要内容 三 微观经济学1 名词定义2 研究内容3 对比区别 四 降息降准是什么意思 xff1f 五 一些常用术语1 沉没成本2 边际成本 一 前言 每天我们都在跟 经济 打交道 xff0c
  • 【程序员学理财】汽车行业、手机行业简单了解

    汽车行业 本文章不是专业的解读 xff0c 只是为了让自己对汽车行业建立一个大体的认知 先简单看两个新闻 xff1a 2021年销量出炉 xff0c 中国车企卷翻了 才一年 xff0c 智能车就不再是新势力专利 xff01 当然上面这些是从
  • 【LeetCode刷题日记】1996. 游戏中弱角色的数量

    题目 你正在参加一个多角色游戏 xff0c 每个角色都有两个主要属性 xff1a 攻击 和 防御 给你一个二维整数数组 properties xff0c 其中 properties i 61 attacki defensei 表示游戏中第
  • LEETCODE 编程训练

    转载于 xff1a https coolshell cn articles 12052 html Leetcode这个网站上的题都是一些经典的公司用来面试应聘者的面试题 xff0c 很多人通过刷这些题来应聘一些喜欢面试算法的公司 xff0c
  • 【程序员学理财】零和博弈和对股市的一些了解

    一 零和博弈 零和博弈 xff08 zero sum game xff09 xff0c 又称零和游戏 xff0c 与非零和博弈相对 xff0c 是博弈论的一个概念 xff0c 属非合作博弈 它是指参与博弈的各方 xff0c 在严格竞争下 x
  • C++11新特性之十:enable_shared_from_this

    enable shared from this是一个模板类 xff0c 定义于头文件 lt memory gt xff0c 其原型为 xff1a template lt class T gt class enable shared from
  • 【程序员学理财】曼昆:经济学十大原理,你都了解吗?

    经济学十大原理是哈佛大学经济学教授格里高利 曼昆在其著作 经济学原理 中提出 xff0c 通俗易懂 xff0c 是很多高校经济学考研的指定参考书 很多人觉得经济学一听就是高大上 xff0c 非常深奥 xff0c 其实并不是的 xff0c 今
  • 2022年java学习路线总结

    直接放两个非常好的文章 xff0c 链接如下 xff1a 2021年Java后端开发学习路线 xff08 建议收藏 xff01 xff09 Java后端学习路线图 xff0c 你真的只需要这一张 xff01 最后放一段守护石的 xff1a
  • web服务器与浏览器之间的网络通信过程

    浏览器与web服务器的交互过程 1 浏览器与web服务器的通信原理概述 网络编程 xff08 一 xff09 浅析web服务器与浏览器的实现原理
  • Tomcat部署Web项目的几种方法

    tomcat 部署web项目的四种方法 Tomcat部署Web项目的3种方式
  • 心跳机制详解

    心跳机制 心跳机制详解 什么是TCP心跳机制
  • 学习Spring之前要先学习什么?

    转载于 xff1a https zhuanlan zhihu com p 64001753 开门见山 xff0c 先放结论 要开始学习Spring xff08 以IOC和Spring MVC为核心 xff09 xff0c 只需要做好以下准备
  • 【程序员学理财】有关fd的一些了解

    https www 163 com dy article GJK2KL600535EAS7 html https www fangdaijisuanqi com https www 163 com dy article GMUC9K5805
  • 【Java学习路线之JavaWeb】JSP教程

    文章目录 为什么要学习JSP xff1f 读者阅读条件 JSP到底是什么JSP的由来Servlet与JSP异同点JSP相对于Servlet的优点1 xff09 易于维护2 xff09 快速开发 xff1a 无需重新编译和部署3 xff09
  • 用了五年 VS Code ,我决定换成 JetBrains……

    作者 Jeremy Liu 译者 许学文 策划 闫园园 审校 王强 本文最初发布于 Blankly 上 xff0c 经原作者授权由 InfoQ 中文站翻译并分享 在编程中 xff0c VS Code 作为我的主 IDE 长达 5 年之久 在
  • 分布式、分布式系统、分布式计算、分布式存储

    用大白话聊聊分布式系统 什么是分布式系统 xff0c 如何学习分布式系统 分布式学习最佳实践 xff1a 从分布式系统的特征开始 xff08 附思维导图 xff09 分布式系统 分布式 到底什么是分布式系统 xff1f 你需要了解这些 ht
  • 第19章 操作系统设计的思想

    19 1 操作系统的概述 操作系统的设计是将方方面面的技术和设计有机的结合起来 xff0c 构建一个掌控计算机的巨无霸软件系统 各种各样的技术细节不一定相互兼容或者相得益彰 xff0c 甚至有些是相互矛盾的 xff0c 操作系统能把进程管理
  • 【Java学习路线之JavaWeb】Spring MVC框架入门教程

    文章目录 读者阅读条件 MVC设计模式简介JSP 43 JavaBeanServlet 43 JSP 43 JavaBeanMVC优缺点优点缺点 Spring MVC是什么Spring MVC优点 第一个Spring MVC程序1 创建We
  • 【Java学习路线之JavaWeb】Spring Cloud教程(非常详细)

    文章目录 读者阅读条件 微服务是什么微服务 xff0c 我们可以从字面上去理解 xff0c 即 微小的服务 xff0c 下面我们从 服务 和 微小 两个方面进行介绍 微服务架构微服务架构 vs 单体架构微服务的特点微服务框架Java 微服务
  • 架构设计:如何实现一个高性能分布式 RPC 框架

    在前面的课程中 xff0c 我们由浅入深地讲解了 Netty 的基础知识和实现原理 xff0c 并对 Netty 的核心源码进行了剖析 xff0c 相信你已经体会到了 Netty 的强大之处 本身学习一门技术是一个比较漫长的过程 xff0c