How to Build Transparent Remote Service Calls with Java RPC and Zookeeper

This article explains how large‑scale internet companies replace local service calls with remote procedure calls (RPC), covering Java dynamic proxies, message encoding, serialization, asynchronous response handling, and Zookeeper‑based service registration and discovery to achieve transparent, scalable service communication.

21CTO
21CTO
21CTO
How to Build Transparent Remote Service Calls with Java RPC and Zookeeper

During school we often write simple local services, but in large internet companies services are distributed across many machines, requiring remote calls and service publishing.

Remote Procedure Call (RPC) abstracts network communication so that a remote service can be invoked like a local one. The typical RPC flow includes client stub, server stub, message encoding/decoding, transport, and result handling.

Java achieves transparent remote calls using dynamic proxies. The proxy class implements InvocationHandler, packages method name, parameters, etc., sends them over the network, and returns the result.

public class RPCProxyClient implements java.lang.reflect.InvocationHandler{
    private Object obj;
    public RPCProxyClient(Object obj){ this.obj=obj; }
    public static Object getProxy(Object obj){
        return java.lang.reflect.Proxy.newProxyInstance(
            obj.getClass().getClassLoader(),
            obj.getClass().getInterfaces(),
            new RPCProxyClient(obj));
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        Object result = new Object();
        // ... communication logic ...
        return result;
    }
}

A test class obtains a proxy for the service interface and calls its method:

public class Test {
    public static void main(String[] args) {
        HelloWorldService helloWorldService = (HelloWorldService)RPCProxyClient.getProxy(HelloWorldService.class);
        helloWorldService.sayHello("test");
    }
}

The message format must contain interface name, method name, parameter types and values, timeout, and a unique requestID. Serialization (e.g., Protobuf, Thrift, Avro) converts the message to a binary stream for transport.

Transport can use BIO or NIO; most modern RPC frameworks rely on Netty. A requestID allows correlating asynchronous responses with the originating thread, using a ConcurrentHashMap of callbacks and synchronized wait/notify mechanisms.

public Object get() {
    synchronized (this) {
        while (!isDone) {
            wait();
        }
    }
}

Service registration and discovery are typically handled by Zookeeper. Providers register their IP and port under a path like /HelloWorldService/1.0.0/host:port. Consumers watch this path and automatically receive updates when instances are added or removed, achieving load balancing and high availability.

In summary, mastering RPC involves understanding proxy generation, message encoding, serialization, transport mechanisms, asynchronous response handling, and Zookeeper‑based service registry integration, which are essential skills for backend developers entering large‑scale internet companies.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaRPCservice discoveryserializationZooKeeperNettyDynamic Proxy
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.