RESTful API 与 gRPC
RESTful API 原理
RESTful API 是一种基于 HTTP 协议的架构风格,用于构建分布式系统中的网络应用程序。它通过一组规则和约束来定义客户端和服务器之间的交互方式,使得系统更加简洁、可扩展和易于理解。RESTful API 的设计原则包括:
-
无状态性:每个请求都必须包含理解请求所必需的所有信息,服务器不保存任何客户端的上下文信息。
-
统一接口:通过一组固定的接口(如 GET、POST、PUT、DELETE)来操作资源。
-
资源的表述:资源通过 URI(Uniform Resource Identifier)来标识,并且可以通过请求返回资源的表述(如 JSON、XML)。
-
分层系统:客户端和服务器之间可以有中间层,如缓存、负载均衡等。
-
按需代码:服务器可以向客户端发送可执行代码,如 JavaScript,以扩展客户端的功能。
HTTP 方法
RESTful API 通常使用以下 HTTP 方法来操作资源:
-
GET:用于获取资源。
-
POST:用于创建资源。
-
PUT:用于更新资源。
-
DELETE:用于删除资源。
-
PATCH:用于部分更新资源。
资源标识
资源通过 URI 来标识,通常包括路径和查询参数。例如,假设有一个 IoT 设备管理系统的 API,可以使用以下 URI 来标识设备:
-
GET /devices
:获取所有设备。 -
GET /devices/{device_id}
:获取指定设备的详细信息。 -
POST /devices
:创建新设备。 -
PUT /devices/{device_id}
:更新指定设备的信息。 -
DELETE /devices/{device_id}
:删除指定设备。
响应状态码
HTTP 状态码用于表示请求的处理结果,常见的状态码包括:
-
200 OK:成功响应。
-
201 Created:资源创建成功。
-
204 No Content:成功响应,但无内容返回。
-
400 Bad Request:请求无效。
-
401 Unauthorized:请求未授权。
-
403 Forbidden:请求被禁止。
-
404 Not Found:资源未找到。
-
500 Internal Server Error:服务器内部错误。
内容协商
内容协商是指客户端和服务器之间协商资源的表示形式。客户端可以通过 Accept
头来指定希望接收的媒体类型,服务器通过 Content-Type
头来指定响应的媒体类型。例如:
GET /devices/123 HTTP/1.1
Host: example.com
Accept: application/json
服务器响应:
HTTP/1.1 200 OK
Content-Type: application/json
{
"device_id": "123",
"name": "Device 123",
"status": "online",
"last_seen": "2023-01-01T00:00:00Z"
}
示例:创建一个简单的 RESTful API
假设我们使用 Flask 框架来创建一个简单的 RESTful API,用于管理 IoT 设备。
首先,安装 Flask:
pip install Flask
然后,创建一个 Flask 应用:
# app.py
from flask import Flask, request, jsonify
app = Flask(__name__)
# 模拟设备数据
devices = {
"123": {"name": "Device 123", "status": "online", "last_seen": "2023-01-01T00:00:00Z"},
"456": {"name": "Device 456", "status": "offline", "last_seen": "2023-01-02T12:00:00Z"}
}
@app.route('/devices', methods=['GET'])
def get_devices():
return jsonify(list(devices.values()))
@app.route('/devices/<device_id>', methods=['GET'])
def get_device(device_id):
if device_id in devices:
return jsonify(devices[device_id])
else:
return jsonify({"error": "Device not found"}), 404
@app.route('/devices', methods=['POST'])
def create_device():
data = request.get_json()
if not data or 'name' not in data:
return jsonify({"error": "Invalid request"}), 400
device_id = str(len(devices) + 1)
devices[device_id] = {
"name": data['name'],
"status": "online",
"last_seen": "2023-01-01T00:00:00Z"
}
return jsonify({"device_id": device_id, "message": "Device created"}), 201
@app.route('/devices/<device_id>', methods=['PUT'])
def update_device(device_id):
data = request.get_json()
if device_id not in devices:
return jsonify({"error": "Device not found"}), 404
if not data or 'name' not in data:
return jsonify({"error": "Invalid request"}), 400
devices[device_id]['name'] = data['name']
devices[device_id]['status'] = data.get('status', 'online')
devices[device_id]['last_seen'] = data.get('last_seen', '2023-01-01T00:00:00Z')
return jsonify({"message": "Device updated"})
@app.route('/devices/<device_id>', methods=['DELETE'])
def delete_device(device_id):
if device_id in devices:
del devices[device_id]
return jsonify({"message": "Device deleted"})
else:
return jsonify({"error": "Device not found"}), 404
if __name__ == '__main__':
app.run(debug=True)
运行 Flask 应用:
python app.py
测试 API
可以使用 curl
或 Postman 来测试这个 API。
- 获取所有设备:
curl -X GET http://127.0.0.1:5000/devices
- 获取指定设备:
curl -X GET http://127.0.0.1:5000/devices/123
- 创建设备:
curl -X POST http://127.0.0.1:5000/devices -H "Content-Type: application/json" -d '{"name": "New Device"}'
- 更新设备:
curl -X PUT http://127.0.0.1:5000/devices/123 -H "Content-Type: application/json" -d '{"name": "Updated Device", "status": "offline"}'
- 删除设备:
curl -X DELETE http://127.0.0.1:5000/devices/123
gRPC 原理
gRPC(gRPC Remote Procedure Call)是一种高性能、开源和通用的 RPC 框架,由 Google 开发。它基于 HTTP/2 协议,并使用 Protocol Buffers 作为接口定义语言(IDL)和数据交换格式。gRPC 支持多种语言,包括 Python、Java、C++、Go、Ruby 等,使得不同语言的客户端和服务器可以方便地进行通信。
协议缓冲区(Protocol Buffers)
Protocol Buffers 是一种语言中立、平台中立的结构化数据序列化方法。它用于定义服务接口和消息格式,生成客户端和服务器的代码。Protocol Buffers 的定义文件通常以 .proto
为扩展名。
服务定义
在 .proto
文件中定义服务接口和消息格式。例如,定义一个 IoT 设备管理服务:
// device.proto
syntax = "proto3";
package device;
service DeviceManager {
rpc GetDevice (DeviceRequest) returns (DeviceResponse);
rpc CreateDevice (DeviceRequest) returns (DeviceResponse);
rpc UpdateDevice (DeviceRequest) returns (DeviceResponse);
rpc DeleteDevice (DeviceRequest) returns (DeviceResponse);
rpc ListDevices (ListDevicesRequest) returns (ListDevicesResponse);
}
message DeviceRequest {
string device_id = 1;
string name = 2;
string status = 3;
string last_seen = 4;
}
message DeviceResponse {
string device_id = 1;
string name = 2;
string status = 3;
string last_seen = 4;
string message = 5;
}
message ListDevicesRequest {}
message ListDevicesResponse {
repeated DeviceResponse devices = 1;
}
生成代码
使用 protoc
编译器生成客户端和服务器的代码。假设我们使用 Python 作为开发语言:
pip install grpcio grpcio-tools
生成 Python 代码:
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. device.proto
生成的文件包括 device_pb2.py
和 device_pb2_grpc.py
。
服务器端实现
在服务器端实现服务接口。创建一个 server.py
文件:
# server.py
from concurrent import futures
import grpc
import time
import datetime
import device_pb2
import device_pb2_grpc
# 模拟设备数据
devices = {
"123": {"name": "Device 123", "status": "online", "last_seen": "2023-01-01T00:00:00Z"},
"456": {"name": "Device 456", "status": "offline", "last_seen": "2023-01-02T12:00:00Z"}
}
class DeviceManagerServicer(device_pb2_grpc.DeviceManagerServicer):
def GetDevice(self, request, context):
if request.device_id not in devices:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details("Device not found")
return device_pb2.DeviceResponse()
device = devices[request.device_id]
return device_pb2.DeviceResponse(
device_id=request.device_id,
name=device['name'],
status=device['status'],
last_seen=device['last_seen']
)
def CreateDevice(self, request, context):
if not request.name:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Invalid request")
return device_pb2.DeviceResponse()
device_id = str(len(devices) + 1)
devices[device_id] = {
"name": request.name,
"status": request.status or "online",
"last_seen": request.last_seen or datetime.datetime.utcnow().isoformat() + "Z"
}
return device_pb2.DeviceResponse(
device_id=device_id,
name=devices[device_id]['name'],
status=devices[device_id]['status'],
last_seen=devices[device_id]['last_seen'],
message="Device created"
)
def UpdateDevice(self, request, context):
if request.device_id not in devices:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details("Device not found")
return device_pb2.DeviceResponse()
if not request.name:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Invalid request")
return device_pb2.DeviceResponse()
device = devices[request.device_id]
device['name'] = request.name
device['status'] = request.status or device['status']
device['last_seen'] = request.last_seen or device['last_seen']
return device_pb2.DeviceResponse(
device_id=request.device_id,
name=device['name'],
status=device['status'],
last_seen=device['last_seen'],
message="Device updated"
)
def DeleteDevice(self, request, context):
if request.device_id in devices:
del devices[request.device_id]
return device_pb2.DeviceResponse(message="Device deleted")
else:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details("Device not found")
return device_pb2.DeviceResponse()
def ListDevices(self, request, context):
device_responses = []
for device_id, device in devices.items():
device_responses.append(device_pb2.DeviceResponse(
device_id=device_id,
name=device['name'],
status=device['status'],
last_seen=device['last_seen']
))
return device_pb2.ListDevicesResponse(devices=device_responses)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
device_pb2_grpc.add_DeviceManagerServicer_to_server(DeviceManagerServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
print("Server started on port 50051")
try:
while True:
time.sleep(86400)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
客户端实现
在客户端实现调用服务的方法。创建一个 client.py
文件:
# client.py
import grpc
import device_pb2
import device_pb2_grpc
def get_device(stub, device_id):
response = stub.GetDevice(device_pb2.DeviceRequest(device_id=device_id))
print(f"Device: {response.device_id}, Name: {response.name}, Status: {response.status}, Last Seen: {response.last_seen}")
def create_device(stub, name, status=None, last_seen=None):
response = stub.CreateDevice(device_pb2.DeviceRequest(name=name, status=status, last_seen=last_seen))
print(f"Device created: {response.device_id}, Name: {response.name}, Status: {response.status}, Last Seen: {response.last_seen}")
def update_device(stub, device_id, name, status=None, last_seen=None):
response = stub.UpdateDevice(device_pb2.DeviceRequest(device_id=device_id, name=name, status=status, last_seen=last_seen))
print(f"Device updated: {response.device_id}, Name: {response.name}, Status: {response.status}, Last Seen: {response.last_seen}")
def delete_device(stub, device_id):
response = stub.DeleteDevice(device_pb2.DeviceRequest(device_id=device_id))
print(f"Device deleted: {response.device_id}")
def list_devices(stub):
response = stub.ListDevices(device_pb2.ListDevicesRequest())
for device in response.devices:
print(f"Device: {device.device_id}, Name: {device.name}, Status: {device.status}, Last Seen: {device.last_seen}")
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = device_pb2_grpc.DeviceManagerStub(channel)
print("1. Get device")
print("2. Create device")
print("3. Update device")
print("4. Delete device")
print("5. List devices")
choice = input("Choose an option: ")
if choice == "1":
device_id = input("Enter device ID: ")
get_device(stub, device_id)
elif choice == "2":
name = input("Enter device name: ")
status = input("Enter device status (optional): ")
last_seen = input("Enter last seen time (optional): ")
create_device(stub, name, status, last_seen)
elif choice == "3":
device_id = input("Enter device ID: ")
name = input("Enter device name: ")
status = input("Enter device status (optional): ")
last_seen = input("Enter last seen time (optional): ")
update_device(stub, device_id, name, status, last_seen)
elif choice == "4":
device_id = input("Enter device ID: ")
delete_device(stub, device_id)
elif choice == "5":
list_devices(stub)
else:
print("Invalid choice")
if __name__ == '__main__':
run()
运行和测试
首先运行服务器:
python server.py
然后运行客户端:
python client.py
根据提示选择操作,例如:
- 获取指定设备:
Choose an option: 1
Enter device ID: 123
Device: 123, Name: Device 123, Status: online, Last Seen: 2023-01-01T00:00:00Z
- 创建设备:
Choose an option: 2
Enter device name: New Device
Enter device status (optional): online
Enter last seen time (optional): 2023-01-03T00:00:00Z
Device created: 3, Name: New Device, Status: online, Last Seen: 2023-01-03T00:00:00Z
- 更新设备:
Choose an option: 3
Enter device ID: 123
Enter device name: Updated Device 123
Enter device status (optional): offline
Enter last seen time (optional): 2023-01-04T00:00:00Z
Device updated: 123, Name: Updated Device 123, Status: offline, Last Seen: 2023-01-04T00:00:00Z
- 删除设备:
Choose an option: 4
Enter device ID: 123
Device deleted: 123
- 获取所有设备:
Choose an option: 5
Device: 456, Name: Device 456, Status: offline, Last Seen: 2023-01-02T12:00:00Z
Device: 3, Name: New Device, Status: online, Last Seen: 2023-01-03T00:00:00Z
RESTful API 与 gRPC 的对比
性能
-
RESTful API:基于 HTTP/1.1,性能相对较低,尤其是在大流量和高并发的场景下。HTTP/1.1 协议在每次请求时需要建立和关闭连接,这在高并发情况下会导致较大的性能开销。
-
gRPC:基于 HTTP/2,支持多路复用和二进制编码,性能更高,适合大流量和高并发的场景。HTTP/2 的多路复用特性允许在一个连接上同时处理多个请求,减少了连接的建立和关闭开销。此外,gRPC 使用 Protocol Buffers 作为数据交换格式,二进制编码相比 JSON 或 XML 更紧凑、更高效。
协议
-
RESTful API:使用 HTTP 协议,请求和响应数据通常以 JSON 或 XML 格式表示。HTTP 协议广泛支持,易于理解和调试,适合浏览器和移动应用等客户端。
-
gRPC:使用 HTTP/2 协议,并且数据交换格式为 Protocol Buffers。HTTP/2 提供了更多的高级特性,如流控制、头部压缩和服务器推送,使得 gRPC 在网络传输上更加高效。Protocol Buffers 是一种高效的序列化格式,支持多种编程语言,使得跨语言通信更加方便。
通信方式
-
RESTful API:通常使用请求/响应模式,客户端发送 HTTP 请求到服务器,服务器处理请求并返回响应。这种模式简单直观,适用于大多数 Web 应用。
-
gRPC:支持请求/响应模式、双向流、客户端流和服务器流等多种通信方式。双向流允许客户端和服务器同时发送和接收消息,适用于实时通信和流式数据处理场景。
数据格式
-
RESTful API:数据通常以 JSON 或 XML 格式表示,这些格式易于阅读和调试,但相对冗长且解析效率较低。
-
gRPC:使用 Protocol Buffers 作为数据交换格式,这种格式紧凑且解析效率高,但需要生成代码,对开发者来说学习曲线略高。
安全性
-
RESTful API:通常使用 HTTPS 来保证安全性,支持多种认证方式,如 Basic Auth、OAuth、JWT 等。安全性方面相对成熟,易于实现。
-
gRPC:同样支持 HTTPS,但更倾向于使用 gRPC 的内置认证机制,如 SSL/TLS 证书和 gRPC 认证插件。gRPC 的流控制和头部压缩等特性也有助于提高安全性。
适用场景
-
RESTful API:适用于简单的 Web 应用和移动应用,尤其是当客户端和服务器之间的交互相对简单且请求响应模式足够时。
-
gRPC:适用于需要高性能、低延迟和复杂通信模式的场景,如微服务架构、实时数据流和跨语言通信。
示例:使用 gRPC 和 RESTful API 管理 IoT 设备
RESTful API 示例
我们已经使用 Flask 创建了一个简单的 RESTful API 用于管理 IoT 设备。以下是 Flask 应用的代码:
# app.py
from flask import Flask, request, jsonify
app = Flask(__name__)
# 模拟设备数据
devices = {
"123": {"name": "Device 123", "status": "online", "last_seen": "2023-01-01T00:00:00Z"},
"456": {"name": "Device 456", "status": "offline", "last_seen": "2023-01-02T12:00:00Z"}
}
@app.route('/devices', methods=['GET'])
def get_devices():
return jsonify(list(devices.values()))
@app.route('/devices/<device_id>', methods=['GET'])
def get_device(device_id):
if device_id in devices:
return jsonify(devices[device_id])
else:
return jsonify({"error": "Device not found"}), 404
@app.route('/devices', methods=['POST'])
def create_device():
data = request.get_json()
if not data or 'name' not in data:
return jsonify({"error": "Invalid request"}), 400
device_id = str(len(devices) + 1)
devices[device_id] = {
"name": data['name'],
"status": "online",
"last_seen": "2023-01-01T00:00:00Z"
}
return jsonify({"device_id": device_id, "message": "Device created"}), 201
@app.route('/devices/<device_id>', methods=['PUT'])
def update_device(device_id):
data = request.get_json()
if device_id not in devices:
return jsonify({"error": "Device not found"}), 404
if not data or 'name' not in data:
return jsonify({"error": "Invalid request"}), 400
devices[device_id]['name'] = data['name']
devices[device_id]['status'] = data.get('status', 'online')
devices[device_id]['last_seen'] = data.get('last_seen', '2023-01-01T00:00:00Z')
return jsonify({"message": "Device updated"})
@app.route('/devices/<device_id>', methods=['DELETE'])
def delete_device(device_id):
if device_id in devices:
del devices[device_id]
return jsonify({"message": "Device deleted"})
else:
return jsonify({"error": "Device not found"}), 404
if __name__ == '__main__':
app.run(debug=True)
gRPC 示例
我们已经使用 gRPC 创建了一个简单的服务,用于管理 IoT 设备。以下是服务器端和客户端的代码:
服务器端实现
# server.py
from concurrent import futures
import grpc
import time
import datetime
import device_pb2
import device_pb2_grpc
# 模拟设备数据
devices = {
"123": {"name": "Device 123", "status": "online", "last_seen": "2023-01-01T00:00:00Z"},
"456": {"name": "Device 456", "status": "offline", "last_seen": "2023-01-02T12:00:00Z"}
}
class DeviceManagerServicer(device_pb2_grpc.DeviceManagerServicer):
def GetDevice(self, request, context):
if request.device_id not in devices:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details("Device not found")
return device_pb2.DeviceResponse()
device = devices[request.device_id]
return device_pb2.DeviceResponse(
device_id=request.device_id,
name=device['name'],
status=device['status'],
last_seen=device['last_seen']
)
def CreateDevice(self, request, context):
if not request.name:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Invalid request")
return device_pb2.DeviceResponse()
device_id = str(len(devices) + 1)
devices[device_id] = {
"name": request.name,
"status": request.status or "online",
"last_seen": request.last_seen or datetime.datetime.utcnow().isoformat() + "Z"
}
return device_pb2.DeviceResponse(
device_id=device_id,
name=devices[device_id]['name'],
status=devices[device_id]['status'],
last_seen=devices[device_id]['last_seen'],
message="Device created"
)
def UpdateDevice(self, request, context):
if request.device_id not in devices:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details("Device not found")
return device_pb2.DeviceResponse()
if not request.name:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Invalid request")
return device_pb2.DeviceResponse()
device = devices[request.device_id]
device['name'] = request.name
device['status'] = request.status or device['status']
device['last_seen'] = request.last_seen or device['last_seen']
return device_pb2.DeviceResponse(
device_id=request.device_id,
name=device['name'],
status=device['status'],
last_seen=device['last_seen'],
message="Device updated"
)
def DeleteDevice(self, request, context):
if request.device_id in devices:
del devices[request.device_id]
return device_pb2.DeviceResponse(message="Device deleted")
else:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details("Device not found")
return device_pb2.DeviceResponse()
def ListDevices(self, request, context):
device_responses = []
for device_id, device in devices.items():
device_responses.append(device_pb2.DeviceResponse(
device_id=device_id,
name=device['name'],
status=device['status'],
last_seen=device['last_seen']
))
return device_pb2.ListDevicesResponse(devices=device_responses)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
device_pb2_grpc.add_DeviceManagerServicer_to_server(DeviceManagerServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
print("Server started on port 50051")
try:
while True:
time.sleep(86400)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
客户端实现
# client.py
import grpc
import device_pb2
import device_pb2_grpc
def get_device(stub, device_id):
response = stub.GetDevice(device_pb2.DeviceRequest(device_id=device_id))
print(f"Device: {response.device_id}, Name: {response.name}, Status: {response.status}, Last Seen: {response.last_seen}")
def create_device(stub, name, status=None, last_seen=None):
response = stub.CreateDevice(device_pb2.DeviceRequest(name=name, status=status, last_seen=last_seen))
print(f"Device created: {response.device_id}, Name: {response.name}, Status: {response.status}, Last Seen: {response.last_seen}")
def update_device(stub, device_id, name, status=None, last_seen=None):
response = stub.UpdateDevice(device_pb2.DeviceRequest(device_id=device_id, name=name, status=status, last_seen=last_seen))
print(f"Device updated: {response.device_id}, Name: {response.name}, Status: {response.status}, Last Seen: {response.last_seen}")
def delete_device(stub, device_id):
response = stub.DeleteDevice(device_pb2.DeviceRequest(device_id=device_id))
print(f"Device deleted: {response.device_id}")
def list_devices(stub):
response = stub.ListDevices(device_pb2.ListDevicesRequest())
for device in response.devices:
print(f"Device: {device.device_id}, Name: {device.name}, Status: {device.status}, Last Seen: {device.last_seen}")
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = device_pb2_grpc.DeviceManagerStub(channel)
print("1. Get device")
print("2. Create device")
print("3. Update device")
print("4. Delete device")
print("5. List devices")
choice = input("Choose an option: ")
if choice == "1":
device_id = input("Enter device ID: ")
get_device(stub, device_id)
elif choice == "2":
name = input("Enter device name: ")
status = input("Enter device status (optional): ")
last_seen = input("Enter last seen time (optional): ")
create_device(stub, name, status, last_seen)
elif choice == "3":
device_id = input("Enter device ID: ")
name = input("Enter device name: ")
status = input("Enter device status (optional): ")
last_seen = input("Enter last seen time (optional): ")
update_device(stub, device_id, name, status, last_seen)
elif choice == "4":
device_id = input("Enter device ID: ")
delete_device(stub, device_id)
elif choice == "5":
list_devices(stub)
else:
print("Invalid choice")
if __name__ == '__main__':
run()
运行和测试
首先运行 gRPC 服务器:
python server.py
然后运行 gRPC 客户端:
python client.py
根据提示选择操作,例如:
- 获取指定设备:
Choose an option: 1
Enter device ID: 123
Device: 123, Name: Device 123, Status: online, Last Seen: 2023-01-01T00:00:00Z
- 创建设备:
Choose an option: 2
Enter device name: New Device
Enter device status (optional): online
Enter last seen time (optional): 2023-01-03T00:00:00Z
Device created: 3, Name: New Device, Status: online, Last Seen: 2023-01-03T00:00:00Z
- 更新设备:
Choose an option: 3
Enter device ID: 123
Enter device name: Updated Device 123
Enter device status (optional): offline
Enter last seen time (optional): 2023-01-04T00:00:00Z
Device updated: 123, Name: Updated Device 123, Status: offline, Last Seen: 2023-01-04T00:00:00Z
- 删除设备:
Choose an option: 4
Enter device ID: 123
Device deleted: 123
- 获取所有设备:
Choose an option: 5
Device: 456, Name: Device 456, Status: offline, Last Seen: 2023-01-02T12:00:00Z
Device: 3, Name: New Device, Status: online, Last Seen: 2023-01-03T00:00:00Z
总结
-
RESTful API:适用于简单的 Web 应用和移动应用,易于理解和调试,但性能和扩展性相对较低。
-
gRPC:适用于高性能、低延迟和复杂通信模式的场景,如微服务架构和实时数据流,但学习曲线较高,需要生成代码。
选择合适的 API 技术取决于具体的应用需求。在需要高性能和复杂通信模式的情况下,gRPC 是一个更好的选择。而在简单的 Web 应用和移动应用中,RESTful API 仍然是一种非常流行和实用的解决方案。
标签:status,name,gRPC,IoT,devices,device,二次开发,seen,id From: https://blog.csdn.net/chenlz2007/article/details/143027302