|
| 1 | +--- |
| 2 | +title: Remote Procedure Call in Java using gRPC |
| 3 | +shortTitle: gRPC in Java |
| 4 | +description: Remote Procedure Call in Java using gRPC communicating between 2 microservices product and cart application |
| 5 | +category: Data Transfer |
| 6 | +language: en |
| 7 | +tag: |
| 8 | +- Behavioral |
| 9 | +- Integration |
| 10 | +- Messaging |
| 11 | +- Client-Server |
| 12 | +- Data Transfer |
| 13 | +- Microservices |
| 14 | +- Remote Procedure Call |
| 15 | +- Remote Method Invocation |
| 16 | +--- |
| 17 | +# Remote Method Invocation / Remote Procedure Call |
| 18 | +Remote Method Invocation has various different aliases, Remote Procedure Call / Remote Method Invocation or RPC for short. Is a protocol |
| 19 | +that one program can use to request a service from a different program located in same or another computer in a network without having to understand network details. |
| 20 | + |
| 21 | +RMI can be implemented in various different languages and frameworks. Technologies like REST, gRPC and Thrift can be used for RMI. In this example we |
| 22 | +will be using gRPC to implement Remote Procedure Call in Java. |
| 23 | + |
| 24 | +## Terminologies |
| 25 | +- Client: The client is the application that sends a request to the server. |
| 26 | +- Server: The server is the application that receives the request from the client and sends a response back to the client. |
| 27 | +- Stub: The client-side proxy for the server. |
| 28 | +- Skeleton: The server-side proxy for the client. |
| 29 | +- Protocol: The set of rules that the client and server follow to communicate with each other. |
| 30 | +- Stream: The sequence of messages that are sent between the client and server, understand it as list of objects. |
| 31 | + |
| 32 | +## What is gRPC? |
| 33 | +[gRPC](https://grpc.io/docs/what-is-grpc/introduction/) is a high-performance, open-source and universal RPC framework. gRPC was developed by Google but is now open-source |
| 34 | +and is based on the HTTP/2 protocol. |
| 35 | + |
| 36 | +A gRPC client can call a method on a gRPC server similar to if it was calling a method on a local object. |
| 37 | +This allows client and server to communicate with each other by just using method calls. gRPC internally uses [protobuf](https://protobuf.dev/) to serialize the data for communication. |
| 38 | + |
| 39 | +## When to use gRPC? |
| 40 | +gRPC should be used when you need high performance communication between client and server. It is mostly used in micro-service architecture when one |
| 41 | +service needs to communicate with another service. |
| 42 | + |
| 43 | +For communication you need to define contract / interfaces denoting the method signature, data types and parameters along with return type. |
| 44 | +These methods can be called by client service just like a method call, when using gRPC, a gRPC service is created which will in-turn call the |
| 45 | +implementation of the RPC method in the server and return the response (if any). |
| 46 | + |
| 47 | +Start by creating a .proto file which should have all the methods and data types you need for communication between the services. |
| 48 | +When you compile your code `maven/gradle gRPC` plugin will in return create objects and interfaces which you need to implement / extend in your |
| 49 | +server side. The client will then call the method defined in .proto file using the generated stubs by gPRC. In return inside the server the |
| 50 | +implementation of the method will be called and the response will be sent back to the client. |
| 51 | + |
| 52 | +### In this example |
| 53 | +We will be using 2 different micro-services |
| 54 | +- product-service |
| 55 | +- cart-service |
| 56 | + |
| 57 | +Along with a shopping.proto file to define the contract between the services. |
| 58 | +- ShoppingService |
| 59 | + |
| 60 | +This is a basic e-commerce simulation. |
| 61 | + |
| 62 | +In this simple example the `product-service` has data related to products and is used a source of truth. The `cart-service` |
| 63 | +needs the product data that is available in `product-service`. Certain number of products in turn may be bought by a customer, |
| 64 | +inside the cart service at which point the product quantity needs to be decreased in `product-service`, hence the need for bidirectional |
| 65 | +communication from `product-service` -> `cart-service` and vice versa they both communicate via gRPC. |
| 66 | + |
| 67 | +- getAllProducts() - gets all the product from state in `product-service` and stores it in `cart-service` |
| 68 | +- reduceProductQuantity() - reduces the quantity of a product by `id` fetched by `getAllProducts` and stored in `cart-service` |
| 69 | + when the method is hit, it reduces the quantity of product with same `id` in `product-service` |
| 70 | + |
| 71 | +## How to implement gRPC in Java? |
| 72 | +### .proto file |
| 73 | +- Create a [.proto](https://protobuf.dev/programming-guides/proto2/) file [example](./proto/shopping.proto) defining the service and message contracts |
| 74 | +- Define service interfaces, method signatures and data types in your .proto file |
| 75 | +### At the server end |
| 76 | +- Add gRPC and protobuf dependencies in your `pom.xml` |
| 77 | +- Include gRPC and protobuf plugins in `mvn build plugins`, for it to generate interfaces from your `.proto` during compilation |
| 78 | +- Include the .proto file directory in mvn build plugins to generate the interfaces |
| 79 | +- Build the project via `mvn clean install` |
| 80 | +- gRPC will generate the stubs and skeletons for you |
| 81 | +- Implement the service logic for the generated methods of skeleton in your service classes |
| 82 | +- Start the gRPC server at server's side on a specific port and attach the gRPC Implementation service to it |
| 83 | +### At the client end |
| 84 | +- Add gRPC and protobuf dependencies in your `pom.xml` |
| 85 | +- Include gRPC and protobuf plugins in `mvn build plugins`, for it to generate interfaces from your `.proto` during compilation |
| 86 | +- Include the .proto file directory in mvn build plugins to generate the interfaces |
| 87 | +- Build the project via `mvn clean install` |
| 88 | +- gRPC will generate the stubs and skeletons for you |
| 89 | +- A stub will expose the available methods to be called by the client, call the methods you need on server via the stub |
| 90 | +- Create Channel with server's host and port at client's end to communicate between server and client |
| 91 | +- Start client, and you are good to go |
| 92 | + |
| 93 | +## gRPC in action |
| 94 | +### Product Service |
| 95 | +#### Service |
| 96 | +- ProductService - API Interface for Internal logic in `product-service` |
| 97 | +- ProductServiceImpl - Implementation of ProductService, saves product data in memory for simplicity, exposes getter(s) for the same. |
| 98 | + Houses Composition of ProductService to store state. |
| 99 | +- ProductServiceGrpcImpl - gRPC contract implementation, methods to retrieve all products and reduce quantity of a product. |
| 100 | +This file implements the logic that should be executed when gRPC methods are called |
| 101 | + |
| 102 | +#### Model |
| 103 | +- Product - Product POJO Model |
| 104 | +#### Mocks |
| 105 | +- ProductMocks - Mock data of Product for testing and state initialization. |
| 106 | + |
| 107 | +### Cart Service |
| 108 | +#### Service |
| 109 | +- CartService - API Interface for Internal logic in `cart-service`, |
| 110 | +- CartServiceImpl - Implementation of CartService, methods to call the stub to populate data in cart and reduce quantities. |
| 111 | + This file calls the gRPC method to communicate with `product-service`. |
| 112 | +#### Model |
| 113 | +- ProductInCart - Cut from Product POJO in `product-service` |
| 114 | + |
| 115 | +### proto |
| 116 | +Proto folder contains all the proto files which define contract for the services. |
| 117 | +proto files end with .proto and contain the types, methods and services that are to be used in gRPC communication. |
| 118 | + |
| 119 | +### Good practise |
| 120 | +- Keep types / method names in PascalCase in .proto file |
| 121 | + |
| 122 | +### How to run this project |
| 123 | +- Clone the project |
| 124 | +- navigate to 'remote-procedure-call' directory via |
| 125 | +```shell |
| 126 | +cd java-design-patterns/remote-procedure-call |
| 127 | +``` |
| 128 | +- build the project with, this will download dependencies, compile .proto to java interface and classes and create final jar |
| 129 | +```shell |
| 130 | +mvn clean install |
| 131 | +``` |
| 132 | +- Start the `product-service` before `cart-service` as `cart-service` depends on product-service |
| 133 | +```shell |
| 134 | +mvn exec:java -Dexec.mainClass="com.iluwatar.rpc.product.Main" -pl product-service |
| 135 | +``` |
| 136 | +- Start a new terminal session |
| 137 | +- navigate to 'remote-procedure-call' directory |
| 138 | +- Start the `cart-service` |
| 139 | +```shell |
| 140 | +mvn exec:java -Dexec.mainClass="com.iluwatar.rpc.cart.Main" -pl cart-service |
| 141 | +``` |
| 142 | +- `cart-service` on startup will hit a gRPC call to `product-service` to get all products and populate the cart. |
| 143 | +- `cart-service` will then reduce the quantity of a product in `product-service` when a product is bought. |
| 144 | +- `cart-service` will then shut-down gracefully. |
| 145 | +- all the operations will be logged in the console. |
| 146 | +- `product-service` will continue to run and can be used for further operations by running `cart-service` again. |
| 147 | +- To stop the services, press `ctrl+c` in the terminal. |
0 commit comments