gRPC 实战篇:从零打造库存管理系统

说一个好消息,C++那些事开源项目4w star了!

开源项目地址:https://github.com/Light-City/CPlusPlusThings

网站:可以点击阅读原文

或者:

https://light-city.github.io/stories_things/

9f3842320c4f7739259c273691790566.png

gRPC 实战篇:从零打造库存管理系统

目录

  • 一、项目背景

  • 二、如何设计 Protobuf

    • 核心代码 (inventory.proto)

  • 三、如何编写 CMake 构建 gRPC

    • CMakeLists.txt(精简版)

  • 四、如何实现库存管理系统

    • 1. 初始化数据

    • 2. 添加商品 (AddProduct)

    • 3. 更新库存 (UpdateQuantity)

    • 4. 创建订单 (CreateOrder)

  • 五、后续还能做什么

  • 六、运行!

最近有小伙伴留言想学习后端开发,尤其是 gRPC 这样前沿的技术。趁着这个机会,我们更新一篇实战教程,带你从设计到实现,打造一个高效的库存管理系统。目标很明确:

  • 如何设计 Protobuf:定义清晰的服务和数据结构

  • 如何编写 CMake 构建 gRPC:快速编译项目

  • 如何实现库存管理系统:核心功能落地

  • 后续还能做什么:扩展你的创意

准备好了吗?让我们动手开干!

演示Demo:

  • 启动服务

  • 客户端连接

执行一些操作,比如:展示库存,添加商品等。

注:懒人版,完整代码已更新至星球。

3d1bafa5ddb6a4d2d19e11f871ade8e9.png

8ff6b981fb814f8deb1bf13616025466.png

78d25380ab93a3e726ad66ff7c633cd0.png

7965fda17e98a4a3cac52e642ad99e06.png

一、项目背景

gRPC 是 Google 推出的高性能 RPC 框架,基于 HTTP/2 和 Protocol Buffers(Protobuf),特别适合微服务和分布式系统。我们将用它实现一个库存管理系统,支持添加商品、查询库存等功能,有了这些功能是不是一个典型的电商项目出来了,哈哈。项目结构如下:

├── main.cpp
└── src
    ├── client/client.cpp
    ├── proto/inventory.proto
    └── server
        ├── inventory_service_impl.cpp
        ├── inventory_service_impl.h
        └── server.cpp

二、如何设计 Protobuf

Protobuf 是 gRPC 的核心,负责定义服务接口和数据结构。设计时要简洁、明确,并考虑扩展性。

核心代码 (inventory.proto)

根据功能来设计:比如需要包含:添加新商品、更新库存、获取detail、列出哪些商品、创建订单等,那么就可以设计出这些rpc。

// 库存管理服务
service InventoryService {
  // 添加新商品
  rpc AddProduct(Product) returns (Product);

  // 更新库存数量
  rpc UpdateQuantity(UpdateQuantityRequest) returns (UpdateQuantityResponse);

  // 获取商品信息
  rpc GetProduct(ProductQuery) returns (Product);

  // 列出商品
  rpc ListProducts(ProductQuery) returns (ProductList);

  // 创建订单
  rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse);

  // 获取订单信息
  rpc GetOrder(OrderQuery) returns (Order);
}

三、如何编写 CMake 构建 gRPC

CMake 是跨平台的构建工具,我们用它来编译 Protobuf 和 gRPC 代码。以下是核心配置:

CMakeLists.txt(精简版)

cmake_minimum_required(VERSION 3.10)
project(InventorySystem)

# 设置 C++17
set(CMAKE_CXX_STANDARD 17)

# 查找 gRPC 和 Protobuf
find_package(Protobuf REQUIRED)
find_package(gRPC CONFIG REQUIRED)

# Protobuf 文件
set(PROTO_FILE "src/proto/inventory.proto")
set(GENERATED_DIR "${CMAKE_BINARY_DIR}/generated")
file(MAKE_DIRECTORY ${GENERATED_DIR})

# 生成代码
set(PROTO_SRC "${GENERATED_DIR}/inventory.pb.cc")
set(GRPC_SRC "${GENERATED_DIR}/inventory.grpc.pb.cc")
add_custom_command(
    OUTPUT ${PROTO_SRC} ${GRPC_SRC}
    COMMAND ${Protobuf_PROTOC_EXECUTABLE}
    ARGS --grpc_out=${GENERATED_DIR} --cpp_out=${GENERATED_DIR}
         -I src/proto --plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
         ${PROTO_FILE}
    DEPENDS ${PROTO_FILE}
)

# 编译服务器
add_executable(server
    ${PROTO_SRC} ${GRPC_SRC}
    src/server/server.cpp
    src/server/inventory_service_impl.cpp
)
target_link_libraries(server gRPC::grpc++ protobuf::libprotobuf)

# 编译客户端
add_executable(client
    ${PROTO_SRC} ${GRPC_SRC}
    src/client/client.cpp
)
target_link_libraries(client gRPC::grpc++ protobuf::libprotobuf)

关键点

  • 用 add_custom_command 生成 Protobuf 和 gRPC 代码。

  • 链接 gRPC::grpc++ 和 protobuf::libprotobuf 库。

  • 分开编译 server 和 client

运行 cmake .. && make,即可生成 server 和 client 可执行文件。

四、如何实现库存管理系统

1. 初始化数据

InventoryServiceImpl::InventoryServiceImpl() : next_product_id_(1), next_order_id_(1) {
    inventory::Product p1;
    p1.set_id(next_product_id_++);  // 自增ID
    p1.set_name("笔记本电脑");
    p1.set_price(5999.99);
    p1.set_quantity(50);
    products_[p1.id()] = p1;  // 存入 map
}

要点:用 map 存储商品,初始化样例数据。

2. 添加商品 (AddProduct)

grpc::Status InventoryServiceImpl::AddProduct(grpc::ServerContext* context,
                                             const inventory::Product* request,
                                             inventory::Product* response) {
    std::lock_guard<std::mutex> lock(mutex_);
    inventory::Product new_product;
    new_product.set_id(next_product_id_++);
    new_product.set_name(request->name());
    new_product.set_price(request->price());
    new_product.set_quantity(request->quantity());
    products_[new_product.id()] = new_product;
    *response = new_product;
    return grpc::Status::OK;
}

要点:线程安全添加商品,返回新商品信息。

3. 更新库存 (UpdateQuantity)

grpc::Status InventoryServiceImpl::UpdateQuantity(grpc::ServerContext* context,
                                                 const inventory::UpdateQuantityRequest* request,
                                                 inventory::UpdateQuantityResponse* response) {
    std::lock_guard<std::mutex> lock(mutex_);
    int32_t product_id = request->product_id();
    if (products_.find(product_id) == products_.end()) {
        response->set_success(false);
        return grpc::Status::OK;
    }
    inventory::Product& product = products_[product_id];
    int32_t new_quantity = product.quantity() + request->quantity_change();
    if (new_quantity < 0) {
        response->set_success(false);
        return grpc::Status::OK;
    }
    product.set_quantity(new_quantity);
    response->set_success(true);
    response->set_new_quantity(new_quantity);
    return grpc::Status::OK;
}

要点:检查库存是否足够,更新并返回结果。

4. 创建订单 (CreateOrder)

grpc::Status InventoryServiceImpl::CreateOrder(grpc::ServerContext* context,
                                              const inventory::CreateOrderRequest* request,
                                              inventory::CreateOrderResponse* response) {
    std::lock_guard<std::mutex> lock(mutex_);
    inventory::Order order;
    order.set_order_id(next_order_id_++);
    order.set_customer_id(request->customer_id());
    double total_price = 0.0;
    for (constauto& item : request->items()) {
        int32_t product_id = item.product_id();
        int32_t quantity = item.quantity();
        if (products_[product_id].quantity() < quantity) {
            response->set_success(false);
            return grpc::Status::OK;
        }
        total_price += products_[product_id].price() * quantity;
        products_[product_id].set_quantity(products_[product_id].quantity() - quantity);
    }
    order.set_total_price(total_price);
    orders_[order.order_id()] = order;
    response->set_success(true);
    *response->mutable_order() = order;
    return grpc::Status::OK;
}

要点:检查库存,计算总价,创建订单并更新库存。

完整实现(包括查询功能等)请加入“星球”查看!

五、后续还能做什么

这个项目只是起点,你可以尝试:

  1. 数据库集成:用 MySQL 或 Redis 替换 map,实现持久化。

  2. 订单管理:扩展 Protobuf,添加订单服务。

  3. 认证授权:集成 gRPC 的 TLS 或 token 认证。

  4. 监控系统:添加日志和库存预警功能。

  5. 多语言支持:用 Python 或 Java 写客户端。

六、运行!

  1. 安装依赖:gRPC、Protobuf、CMake。

  2. 编译运行:

    mkdir build && cd build
    cmake .. && make
    ./server  # 启动服务器
    ./client  # 启动客户端

本节完

(完)


热度更新,手把手实现工业级线程池

学习更多干货,欢迎关注转发!

图片

图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值