# RPC (Remote Procedure Call)

### **What is RPC?**

RPC (Remote Procedure Call) is a protocol that allows a program to execute a procedure (function) on a remote server as if it were a local function. This enables distributed computing where different services interact seamlessly over a network.

Unlike REST APIs, which are resource-based, RPC focuses on calling functions or procedures directly.

### **RPC Architecture and Workflow**

#### **Architecture Components**

1. **Client** – Initiates the RPC request.
2. **Stub (Client-Side Proxy)** – Encodes the request and sends it over the network.
3. **Transport Layer (Network)** – Transfers the request to the remote system.
4. **Stub (Server-Side Proxy)** – Decodes the request.
5. **Server** – Executes the requested procedure and returns the response.

### **RPC Workflow**

1. **Client calls a function**: A client calls a remote function just like a local one.
2. **Marshalling (Serialization)**: The client stub serializes parameters.
3. **Network Communication**: The request is sent over the network.
4. **Server Processing**:
   * Server stub receives the request.
   * It deserializes (unmarshalls) the parameters.
   * The actual function is executed.
5. **Response Transmission**:
   * The server stub serializes the response and sends it back.
   * The client stub receives and deserializes the response.
   * The client receives the result as if it were a local function call.

### **Example: RPC API in gRPC (Google RPC with Protocol Buffers)**

Let's build an RPC API using **gRPC** (a modern high-performance RPC framework developed by Google).

#### **1. Define the RPC Service (Protocol Buffers)**

We use **Protocol Buffers (protobuf)** to define the RPC methods and data structures.

```protobuf
// calculator.proto
syntax = "proto3";

service Calculator {
  rpc Add (AddRequest) returns (AddResponse);
}

message AddRequest {
  int32 a = 1;
  int32 b = 2;
}

message AddResponse {
  int32 result = 1;
}

```

#### **2. Generate gRPC Code**

After defining the `.proto` file, use the gRPC compiler (`protoc`) to generate client and server code in the desired programming language.

```sh
protoc --go_out=. --go-grpc_out=. calculator.proto

```

#### **3. Implement the Server (Go)**

The server implements the defined RPC methods.

```go
package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "path/to/generated/calculatorpb"
)

type server struct {
    pb.UnimplementedCalculatorServer
}

func (s *server) Add(ctx context.Context, req *pb.AddRequest) (*pb.AddResponse, error) {
    result := req.A + req.B
    return &pb.AddResponse{Result: result}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("Failed to listen: %v", err)
    }

    grpcServer := grpc.NewServer()
    pb.RegisterCalculatorServer(grpcServer, &server{})

    log.Println("gRPC server running on port 50051")
    if err := grpcServer.Serve(lis); err != nil {
        log.Fatalf("Failed to serve: %v", err)
    }
}

```

#### **4. Implement the Client (Go)**

The client makes an RPC call to the server.

```go
package main

import (
    "context"
    "log"
    "time"

    "google.golang.org/grpc"
    pb "path/to/generated/calculatorpb"
)

func main() {
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("Failed to connect: %v", err)
    }
    defer conn.Close()

    client := pb.NewCalculatorClient(conn)

    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    req := &pb.AddRequest{A: 10, B: 20}
    res, err := client.Add(ctx, req)
    if err != nil {
        log.Fatalf("Error calling Add: %v", err)
    }

    log.Printf("Addition Result: %d", res.Result)
}

```

### **Types of RPC**

1. **Synchronous RPC** – The client waits for a response before proceeding.
2. **Asynchronous RPC** – The client does not wait and continues execution, fetching the result later.
3. **Streaming RPC** – The client and server exchange multiple messages in a single RPC call (e.g., bidirectional streaming in gRPC).

### **Advantages of RPC**

* **Simplicity** – Calls appear as local function calls.
* **Performance** – More efficient than REST over HTTP (especially with gRPC).
* **Streaming Support** – Enables real-time communication.
* **Strongly Typed** – Enforces structured communication with Protocol Buffers.

### **Disadvantages of RPC**

* **Tightly Coupled** – Client and server need shared interfaces.
* **Complex Debugging** – More challenging than REST APIs.
* &#x20;**Language Constraints** – Requires language-specific bindings.

### **When to Use RPC?**

* **Microservices Communication**: Efficient for service-to-service calls.
* **Real-Time Applications**: Streaming capabilities make it ideal for real-time systems.
* **High-Performance Systems**: Faster and lightweight compared to REST.

### **Conclusion**

RPC APIs provide a powerful way to enable distributed computing with minimal overhead. Modern implementations like **gRPC** improve efficiency, making it a great choice for microservices and high-performance applications. 🚀


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.anandisheladiya.com/skills-and-experience/api/rpc-remote-procedure-call.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
