Setting the Scene: Our Restaurant Management System
Imagine we're building a complete restaurant management system with different parts that need to talk to each other:
- A Menu Service that manages all the food items, prices, and availability
- An Order Service that handles customer orders
- A Business Service that manages restaurant information like hours and locations
- A Delivery Service that coordinates food delivery
Each service is like a different department in a restaurant, and they all need to work together seamlessly. This is what's called a "microservices architecture" - breaking a big system into smaller, specialized pieces.
The big question is: How do these services communicate with each other? That's where gRPC comes in!
Project Structure π
To understand how everything fits together, let's take a look at our project structure:
menu-swift-menu-service/
βββ app/
β βββ grpc/
β β βββ protos/ # Protocol definitions
β β β βββ menu.proto # Our contract file
β β βββ generated/ # Auto-generated code
β β β βββ menu_pb2.py
β β β βββ menu_pb2_grpc.py
β β βββ services/ # Service implementations
β β β βββ menu_service.py
β β βββ server.py # gRPC server class
β βββ models/ # Database models
β β βββ menu.py
β βββ scripts/ # Entry point scripts
β β βββ grpc_client.py # Test client
β β βββ grpc_server.py # Standalone server
β βββ services/ # Business logic services
β β βββ image_service.py
β βββ tests/ # Test utilities
β β βββ grpc/
β β βββ create_test_menu.py
β βββ grpc_server.py # FastAPI + gRPC integration
β βββ rest_server.py # REST API server
βββ requirements.txt
This structure follows best practices for organizing a Python gRPC project, with clear separation of concerns and proper file organization.
1. menu.proto - The Rule Book π
This is like writing down all the rules for a game before you start playing.
message Menu {
string id = 1;
string name = 2;
string description = 3;
double price = 4;
// ...
}
service MenuService {
// GetMenu retrieves a specific menu item by its ID
rpc GetMenu(MenuRequest) returns (Menu);
// ListMenus retrieves all available menu items
rpc ListMenus(google.protobuf.Empty) returns (MenuList);
// ...
}
What it does:
- Defines what a "menu item" looks like (it has an id, name, price, etc.)
- Lists what actions we can do (get one menu, list all menus, etc.)
Think of it as: The blueprint for your LEGO set. It shows all the pieces and how they fit together.
2. menu_pb2.py and menu_pb2_grpc.py - The Auto-Generated Code π€
These files are made by a computer program that reads the rule book.
class MenuServiceStub(object):
"""MenuService provides operations for managing restaurant menu items"""
def __init__(self, channel):
self.GetMenu = channel.unary_unary(...)
self.ListMenus = channel.unary_unary(...)
What they do:
- Turn the rules into actual code that computers understand
- Create helper tools for sending and receiving messages
Think of them as: Translators that help your programs talk to each other in the same language.
3. menu_service.py - The Restaurant Kitchen π¨βπ³
This is where all the real work happens.
def ListMenus(self, request, context):
try:
result = self.crud.read(model_name=Menu)
menus = result["items"]
return menu_pb2.MenuList(items=[self._to_proto_menu(menu) for menu in menus])
except HTTPException as e:
context.set_details(f"{e.status_code}: {e.detail}")
return menu_pb2.MenuList()
What it does:
- Gets menu items from the database when asked
- Creates new menu items when told to
- Updates or deletes menu items
Think of it as: The chef who actually cooks the food when someone orders it.
4. grpc_server.py - The Restaurant Building π’
This file starts up the restaurant and gets it ready for customers.
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
session = Session(engine)
menu_pb2_grpc.add_MenuServiceServicer_to_server(
MenuServiceServicer(session), server)
server.add_insecure_port('[::]:50051')
server.start()
print("gRPC Server started on port 50051")
What it does:
- Opens the restaurant doors (starts a server)
- Tells the chef to get ready (connects to the menu service)
- Waits for customers (listens on port 50051)
Think of it as: Opening the restaurant for business each morning.
5. grpc_client.py - The Test Customer π§βπ¦±
This file acts like a customer walking into the restaurant to test if everything works.
def run():
channel = grpc.insecure_channel("localhost:50051")
stub = menu_pb2_grpc.MenuServiceStub(channel)
response = stub.ListMenus(Empty())
print("Menus received:")
What it does:
- Connects to the restaurant (server)
- Asks for the menu (calls ListMenus)
- Prints out what it gets back
Think of it as: A food critic visiting to check if the restaurant is good.
How It All Works Together π
- First, you write down the rules (menu.proto)
- Then you use a special tool to create helper code:
python -m grpc_tools.protoc -I./app/grpc/protos --python_out=./app/grpc/generated --grpc_python_out=./app/grpc/generated ./app/grpc/protos/menu.proto
- You write the actual kitchen code (menu_service.py)
- You open the restaurant (grpc_server.py)
- A test customer visits (grpc_client.py)
Real-World Example: Taking an Order
Here's what happens when a customer places an order in our restaurant app:
- Customer taps "Order" for a Spicy Chicken Burger on their phone
- Order Service needs to check if this menu item is available
- Order Service calls Menu Service using gRPC:
Order Service: "Hey Menu Service, is the Spicy Chicken Burger available?"
Menu Service: "Yes, we have 15 portions left!"
Order Service: "Great, I'll place an order for 2 burgers."
- Menu Service updates the database: Reduces available portions from 15 to 13
- Order Service creates the order: Sends it to the kitchen for preparation
Why Is This Important for Our Restaurant App? π
In our complete restaurant management system:
- The Menu Service knows all about food items
- The Order Service needs to know what food is available
- The Business Service manages restaurant info
- The Delivery Service needs to know order details
Using gRPC, they can all talk to each other super fast and without confusion, which means:
- Customers always see accurate menu information
- The kitchen never gets orders for items that are sold out
- Delivery drivers get precise order details
It's like having perfect communication between all staff in a busy restaurant - that's the power of gRPC in our microservices system!
Running Our Restaurant for Real
To see this in action, we:
Create some test menu items:
python -m app.tests.grpc.create_test_menu
Start our Menu Service:
python -m app.scripts.grpc_server
Test it with a client:
python -m app.scripts.grpc_client
And just like that, we have a high-performance communication system that helps our entire restaurant management system work together smoothly!
For larger systems, we can also integrate gRPC with our REST API:
python -m app.grpc_server
This starts both the REST API and gRPC server together, giving us the best of both worlds!
Top comments (0)