找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4310

积分

1

好友

590

主题
发表于 3 天前 | 查看: 14| 回复: 0

停更了一段时间,最近决定还是把之前的系列更新完,毕竟做事不能半途而废。

如果你对前面的内容有些模糊了,建议先温习一下,因为接下来我们要一起深入探讨一个非常核心的技术话题。

【前言】

  • 拒绝做 CRUD Boy,为什么你需要学习造轮子?

【理论篇】

【实战篇】

--- 正文开始 ---

万事从最简单的『Hello World』开始,我们今天也从一个经典的示例出发,一步步推演出 RPC(远程过程调用)的核心思想。

本地方法调用

熟悉 Java 技术栈的朋友对 MVC 架构模式肯定不陌生。MVC 是典型的分层设计,将应用分为视图层(V)、控制层(C)和模型层(M)。Spring MVC 正是这一思想的优秀实现。

接下来,我们用 Spring MVC 写一个最简单的 Hello World 示例:

首先,使用 @RestController 注解定义一个控制器。然后,通过 @Autowired 注解将依赖的 bean 注入进来。这样,我们就可以在 hello 方法中轻松调用 HelloService 提供的方法。

@RestController
public class HelloController {
    @Autowired
    private HelloService helloService;

    @GetMapping("/hello/{name}")
    public String hello(@PathVariable String name) {
        // 本地方法调用
        return helloService.sayHello(name);
    }
}

HelloService 类则提供了一个简单的 sayHello 方法。

@Service
public class HelloService {
    public String sayHello(String name) {
        return "hello " + name;
    }
}

HelloControllerHelloService 部署在同一个进程(JVM)中时,hello 方法里调用 HelloService.sayHello() 的行为,就属于典型的本地方法调用

本地方法调用理解起来很简单,但在实际的企业级应用场景中,许多通用服务(如用户中心、订单服务)会独立部署在不同的进程中。如果当前进程需要调用另一个进程提供的服务,这就涉及到远程调用了。

RPC 远程方法调用

让我们用一个商城系统的例子来理解这个演变过程。在业务发展初期,用户量不大,架构往往比较简单。一个单体服务可能包含了用户、购物车、库存、订单等多个功能模块。根据负载,这个服务会被部署1到多个实例(进程),每个实例处理完整的请求,模块间的调用都在进程内完成,这就是本地方法调用。

随着业务推广,用户量激增,单体服务变得日益臃肿,架构开始无法支撑业务发展。这时,架构师通常会选择进行服务拆分,将之前的功能模块独立成一个个微服务

引入微服务后,新的问题随之而来:之前功能模块间的本地调用,现在变成了跨进程的调用。这该怎么办?答案就是引入 RPC 框架。

理解了引入 RPC 的背景,我们再回到之前的代码示例。现在假设 HelloService 由另一个独立的进程来提供,我们的代码该怎么写?

首先,@Autowired 注解肯定不能用了,因为它只在当前 Spring 应用上下文中寻找并注入 bean。那么 Spring 有没有提供注入其他进程服务的注解呢?答案是没有。

既然没有,我们就自己造一个。假设我们创建一个名为 @ServiceReference 的注解,期望它能自动将远程服务的 bean 代理对象注入进来,这样我们就能像调用本地方法一样,无缝地调用远程服务。

思路清晰了,代码可以这样写:

@RestController
public class HelloController {
   // 期望这个注解可以将远程服务 bean 的代理对象自动注入进来
    @ServiceReference
    private HelloService helloService;

    @GetMapping("/hello/{name}")
    public String hello(@PathVariable String name) {
        // 像调用本地方法那样简单调用远程服务
        return helloService.sayHello(name);
    }
}

可以看到,这段代码与本地调用的版本极其相似,仅仅是换了一个注解,使用起来非常便捷。从服务调用关系的角度来看,这段代码扮演了客户端(服务消费者)的角色。有了客户端,我们再来构思服务端怎么写。

服务端的 @Service 注解也不再适用,我们需要创造另一个注解,比如叫 @ServiceExpose。这个注解的作用是将本服务的某个方法暴露出去,使其能够被远程客户端调用。

服务端代码可能长这样:

// 期望通过这个注解将本服务的方法暴露出去
@ServiceExpose
public class HelloService {
    public String sayHello(String name) {
        return "hello " + name;
    }
}

代码似乎写完了?别高兴得太早。当你尝试编译时,会发现根本通不过!原因很简单:我们刚才设想的 @ServiceReference@ServiceExpose 这两个自定义注解,根本还没有定义和实现呢。

这正是 RPC 框架要解决的核心问题之一:如何通过简单的注解配置,让远程调用变得像本地调用一样透明。在接下来的内容中,我们将一步步动手实现 RPC 框架所需的关键组件,包括这些自定义注解。好戏,才刚刚开始。

对这类深入底层、动手实践的内容感兴趣?欢迎来 云栈社区 交流讨论,这里聚集了许多热爱钻研的开发者,共同学习和成长。




上一篇:Java自定义注解实践指南:从零到一构建RPC框架核心
下一篇:开发者使用GitHub Copilot的反思:AI辅助编码的效率陷阱与认知依赖
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-10 13:36 , Processed in 0.565429 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表