ballerina 学习二十八 快速grpc 服务开发
ballerina 的grpc 开发模型,对于开发者来说简单了好多,不是schema first 的方式,而是我们
只要编写简单的ballerina service 就可以了,proto 文件是自动帮我们生成的,同时我们用这个
文件方便的生成各种客户端的代码
项目准备
- 项目结构
├── Ballerina.toml
├── grpc_service
│ └── order_mgt_service.bal
- grpc 代码
可以看出就是普通的ballerina service
import ballerina/grpc;
// gRPC service endpoint definition.
endpoint grpc:Listener listener {
host:"localhost",
port:9090
};
// Order management is done using an in memory map.
// Add sample orders to the 'orderMap' at startup.
map<orderInfo> ordersMap;
// Type definition for an order.
type orderInfo record {
string id;
string name;
string description;
};
// gRPC service.
@grpc:ServiceConfig
service orderMgt bind listener {
// gRPC method to find an order.
findOrder(endpoint caller, string orderId) {
string payload;
// Find the requested order from the map.
if (ordersMap.hasKey(orderId)) {
json orderDetails = check <json>ordersMap[orderId];
payload = orderDetails.toString();
} else {
payload = "Order : '" + orderId + "' cannot be found.";
}
// Send response to the caller.
_ = caller->send(payload);
_ = caller->complete();
}
// gRPC method to create a new Order.
addOrder(endpoint caller, orderInfo orderReq) {
// Add the new order to the map.
string orderId = orderReq.id;
ordersMap[orderReq.id] = orderReq;
// Create a response message.
string payload = "Status : Order created; OrderID : " + orderId;
// Send a response to the caller.
_ = caller->send(payload);
_ = caller->complete();
}
// gRPC method to update an existing Order.
updateOrder(endpoint caller, orderInfo updatedOrder) {
string payload;
// Find the order that needs to be updated.
string orderId = updatedOrder.id;
if (ordersMap.hasKey(orderId)) {
// Update the existing order.
ordersMap[orderId] = updatedOrder;
payload = "Order : '" + orderId + "' updated.";
} else {
payload = "Order : '" + orderId + "' cannot be found.";
}
// Send a response to the caller.
_ = caller->send(payload);
_ = caller->complete();
}
// gRPC method to delete an existing Order.
cancelOrder(endpoint caller, string orderId) {
string payload;
if (ordersMap.hasKey(orderId)) {
// Remove the requested order from the map.
_ = ordersMap.remove(orderId);
payload = "Order : '" + orderId + "' removed.";
} else {
payload = "Order : '" + orderId + "' cannot be found.";
}
// Send a response to the caller.
_ = caller->send(payload);
_ = caller->complete();
}
}
生成proto&&客户端代码
- proto生成
ballerina build grpc_service/
- 客户端代码
ballerina grpc --input target/grpc/orderMgt.proto --output grpc_client
- 修改生成的客户端代码
import ballerina/log;
import ballerina/grpc;
// This is client implementation for unary blocking scenario
public function main(string... args) {
// Client endpoint configuration
endpoint orderMgtBlockingClient orderMgtBlockingEp {
url:"http://localhost:9090"
};
// Create an order
log:printInfo("-----------------------Create a new order-----------------------");
orderInfo orderReq = {id:"100500", name:"XYZ", description:"Sample order."};
var addResponse = orderMgtBlockingEp->addOrder(orderReq);
match addResponse {
(string, grpc:Headers) payload => {
string result;
grpc:Headers resHeaders;
(result, resHeaders) = payload;
log:printInfo("Response - " + result + "\n");
}
error err => {
log:printError("Error from Connector: " + err.message + "\n");
}
}
// Update an order
log:printInfo("--------------------Update an existing order--------------------");
orderInfo updateReq = {id:"100500", name:"XYZ", description:"Updated."};
var updateResponse = orderMgtBlockingEp->updateOrder(updateReq);
match updateResponse {
(string, grpc:Headers) payload => {
string result;
grpc:Headers resHeaders;
(result, resHeaders) = payload;
log:printInfo("Response - " + result + "\n");
}
error err => {
log:printError("Error from Connector: " + err.message + "\n");
}
}
// Find an order
log:printInfo("---------------------Find an existing order---------------------");
var findResponse = orderMgtBlockingEp->findOrder("100500");
match findResponse {
(string, grpc:Headers) payload => {
string result;
grpc:Headers resHeaders;
(result, resHeaders) = payload;
log:printInfo("Response - " + result + "\n");
}
error err => {
log:printError("Error from Connector: " + err.message + "\n");
}
}
// Cancel an order
log:printInfo("-------------------------Cancel an order------------------------");
var cancelResponse = orderMgtBlockingEp->cancelOrder("100500");
match cancelResponse {
(string, grpc:Headers) payload => {
string result;
grpc:Headers resHeaders;
(result, resHeaders) = payload;
log:printInfo("Response - " + result + "\n");
}
error err => {
log:printError("Error from Connector: " + err.message + "\n");
}
}
}
运行&&测试
- 运行server
ballerina run grpc_service
- client 调用
ballerina run grpc_client
参考资料
https://ballerina.io/learn/by-guide/grpc-service/
https://github.com/ballerina-guides/grpc-service
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)