
Course Description and Instructor Introduction
Introduction to the Workflow of the RPC Framework
Introduction to Popular RPC Frameworks in the Market
Introduction to the RPC Framework Components Covered in This Course
Project Maven Dependencies – The RPC Framework in This Course Is Developed Based on Spring Boot
Developing the RPC Service Center: Using Netty Server as the service center to accept all RPC service registrations.
Developing the RPC Service Center: Using Netty Server as the service center to accept all RPC service registrations.
In Netty, there are two core types of handlers:
Inbound Handlers – process data coming in (e.g., when a client sends a request)
Outbound Handlers – process data going out (e.g., when the server sends a response)
These handlers are organized in a structure called the ChannelPipeline, which is a double-linked list of ChannelHandlers.
When receiving data from the client, Netty uses Inbound Handlers
When sending data back to the client, Netty uses Outbound Handlers
The Netty channel pipeline is a doubly linked list that supports insertion at both the head and the tail. When a message is received, the Inbound Handlers in the chain are executed in order; when a message is sent, the Outbound Handlers are executed in reverse order.
RPC services communicate with the service center via the Netty Client.
The message body object MessagePayload contains an internal field named payload, which is of type Object. It can be either an RpcRequest or an RpcResponse, depending on the message type.
Using the Builder Pattern to Construct the MessagePayload Object
Using the Builder Pattern to Construct the MessagePayload Object
Using the Builder Pattern to Construct the MessagePayload Object
If messages are to be transmitted in JSON format, the enums in the message body require special handling.
When a message is outbound, it needs to be encoded according to the custom-designed protocol.
When a message is inbound, it needs to be decoded according to the custom-designed protocol.
ByteBuf is Netty’s abstraction for a buffer of bytes. It provides an efficient and feature-rich alternative to java.nio.ByteBuffer.
It is used for:
Reading incoming network data.
Writing data to be sent over the network.
Encoding/decoding protocol messages.
Features:
Separates read and write operations — you don't need to manually flip like in ByteBuffer.
Can automatically expand capacity (if it's a dynamic buffer).
Works with Netty's buffer pooling mechanism to reduce GC overhead.
Supports slicing, duplication, and composite buffers without copying data.
Can allocate memory in heap or off-heap (direct memory).
The core InboundHandler of the service center is mainly responsible for message forwarding and client registration.
The RpcClient maintains a Netty Client, and once connected to the server, it is primarily responsible for two main tasks: (1) handling incoming RPC responses, and (2) sending out RPC requests.
The RPC service interfaces should be placed in a shared package that is depended upon by all clients providing or consuming RPC services.
Create a custom annotation and place it on the Spring Boot application class to automatically create an RpcClient instance and initiate the connection.
Leveraging the SmartInitializingSingleton interface in Spring Boot, once all singleton beans have been instantiated and initialized, the afterSingletonsInstantiated method is called to scan all RPC methods and extract their metadata for storage in a map.
Leveraging the SmartInitializingSingleton interface in Spring Boot, once all singleton beans have been instantiated and initialized, the afterSingletonsInstantiated method is called to scan all RPC methods and extract their metadata for storage in a map.
Create RpcMethodDescriptor to encapsulate the metadata of the Method.
Use breakpoints to demonstrate the scanning and identification process of RPC methods.
Implement ImportBeanDefinitionRegistrar to dynamically register RpcClient into the Spring container during the Bean Definition phase, and inject property values into RpcClient by manipulating its BeanDefinition.
Use breakpoints to demonstrate the registration process of the RpcClient.
Explain the AnnotationMetadata parameter in the method of ImportBeanDefinitionRegistrar.
Illustrate in detail the process of an RPC request from sending to handling using a diagram.
Generate proxy objects for RPC interfaces, internally encapsulating a series of processes including interface metadata extraction, message packaging, message sending, and blocking to wait for the result.
Leverage the features of CompletableFuture to block and wait for the result to be returned.
Implement the core inbound handler on the client side: RpcClientMessageHandler, which is mainly responsible for handling requests and responses.
Handle RPC requests: extract information from the request body, locate the corresponding RPC method, retrieve the method and execute it via reflection, then wrap the result into an RpcResponse and return it to the consumer.
Complete the entire request process by calling the complete method of CompletableFuture.
Start the service center using a custom annotation.
Once the client successfully connects to the registry center, it immediately sends a registration message. The message body carries the client ID, and upon receiving it, the server registers the client and binds it to the corresponding channel.
Use breakpoints to demonstrate the entire RPC request sending process.
Set a timeout for blocking wait; if the timeout is reached, an exception will be thrown.
Netty can trigger idle events by configuring IdleStateHandler, including read idle, write idle, and read-write idle events.
The registry center only monitors read idle events for each channel. Once the specified time is exceeded, an idle event is triggered, which can be captured and handled. The handling logic is to remove the information associated with the channel, as a triggered read idle event indicates that the connection is considered invalid.
The client only monitors write idle events: once the specified time is exceeded, it sends a heartbeat message to the server to complete the heartbeat detection process and keep the connection active.
If the connection is lost or fails, the client can use the NioEventLoopGroup thread to schedule a task and attempt to reconnect.
Scan all classes for private fields, identify those annotated with @AutoRemoteInjection, and create and inject proxy objects into them.
Summarize the Improvements Made to Proxy Object Implementation
Create a custom RemoteServiceFactoryBean by implementing Spring's FactoryBean interface to generate proxy objects using Spring's built-in mechanisms.
Explain the Characteristics of the FactoryBean Interface.
Use a custom implementation of BeanDefinitionRegistryPostProcessor to create RemoteServiceFactoryBean instances for all RPC interface references annotated with @AutoRemoteInjection. The constructor parameters are passed through the BeanDefinition configuration.
How to Set Constructor Arguments and Inject Values into Private Fields Using BeanDefinition.
Abstract the RpcClient by introducing two abstraction layers: an interface and an abstract class.
The RpcClient is only responsible for establishing connections and sending messages.
Implement service fallback by creating an implementation class for the proxied RPC interface. If an error or timeout occurs, the fallback implementation will be invoked.
Add a fallback class attribute to the startup annotation, allowing a fallback implementation to be specified when the annotation is used.
Ultimate Improvement Plan: Refactor the scanning mechanism by referencing the startup-based scanning approach used in popular frameworks, customize the scanning process, and create proxy objects in a way that aligns better with Spring Boot conventions.
Explain Spring’s class scanner ClassPathScanningCandidateComponentProvider and override its filter methods.
Create a custom RemoteServiceScanner by extending Spring’s core scanner ClassPathBeanDefinitionScanner. By defining a custom filter, it scans all RPC service interfaces annotated with a specific RPC annotation and completes the creation of proxy objects.
Use ImportBeanDefinitionRegistrar to obtain the base package of the startup class, and start scanning all sub-packages from there to identify all RPC interfaces that meet the criteria.
Kryo is a high-performance Java serialization framework that converts objects into compact binary byte streams for transmission or storage.
Replace JSON with Kryo as the message serialization format, and rewrite the encoder and decoder accordingly.
Are you tired of just using frameworks and libraries without knowing how they work inside?
This course teaches you how to build a real-world RPC framework from scratch, with a strong focus on advanced Spring Boot techniques. You won’t just use Spring Boot — you’ll learn how to extend its internal mechanisms to support dynamic proxy injection, custom annotation scanning, Bean lifecycle hooks, and more.
You’ll start by building a Netty-based communication core, defining your own protocol, encoder, and decoder. Then, you'll integrate high-performance serialization using Kryo to efficiently transmit objects across the network.
Where this course truly shines is in its Spring Boot integration:
Use ImportBeanDefinitionRegistrar to extract the startup class’s metadata and scan interfaces dynamically
Implement SmartInitializingSingleton to scan all available RPC service methods at runtime
Use BeanDefinitionRegistryPostProcessor and FactoryBean to register and inject proxy objects automatically
Design custom annotations that trigger client creation and connection logic on application startup
You'll also implement service discovery, heartbeat detection, connection management, and fallback support — everything a production-grade RPC system needs.
Every single line of code is written from scratch — no black boxes, no magic.
By the end of this course, you’ll have built a complete framework similar in architecture to Dubbo or OpenFeign — but every single line is handcrafted, explained, and deeply integrated with Spring Boot.