Cloudflare Workers 与 Containers 现在可以通过 Spectrum 接收入站 TCP 连接,并将套接字直接转发给 Durable Objects 或 Containers。这个变化扩展了 Workers 的网络边界:除了处理传统 HTTP 请求,开发者还可以承载需要长连接、双向数据流和二进制协议的服务,包括全双工 gRPC 应用。
与此同时,Workers 可以完成 gRPC 到 gRPC-Web 的自动转换。这意味着浏览器客户端、边缘逻辑和后端 gRPC 服务之间可以减少一层专门维护的协议转换代理。
从 HTTP 请求处理走向套接字转发
传统 Worker 的核心抽象是一次 HTTP 请求对应一次 fetch() 调用。它适合 API 网关、缓存、鉴权和内容改写,但原始 TCP 服务的连接模型不同:
- 连接可能持续数分钟甚至更久;
- 客户端和服务端可以同时发送数据;
- 协议不一定以 HTTP 请求和响应为边界;
- 服务端可能需要保存连接状态和会话上下文。
新的入站 TCP 能力通过 Spectrum 接收外部连接,再把套接字交给 Durable Objects 或 Containers。两类运行目标适合不同的工作负载:
- Durable Objects 适合按房间、设备、租户或会话组织有状态连接,并利用单实例协调语义管理状态。
- Containers 适合运行已有的 gRPC 服务、原生二进制程序,或者依赖完整操作系统进程模型的应用。
这并不意味着所有 HTTP API 都应该迁移到 TCP。普通 REST API、短请求和缓存友好的读取接口,继续使用 HTTP Worker 往往更简单。入站 TCP 的价值主要体现在已有协议兼容、长连接和双向流式处理上。
gRPC 为什么是直接受益者
gRPC 基于明确的服务定义生成客户端和服务端代码,并支持一元调用、服务端流、客户端流和双向流。此前,把完整的 gRPC 服务放到边缘链路中,通常需要处理 HTTP/2、长连接以及浏览器不直接支持标准 gRPC 客户端等问题。
Workers 与 Containers 支持全双工 gRPC 后,客户端和服务端可以在同一个调用中持续交换消息。适合这一模型的场景包括:
- 实时遥测与设备指令;
- 持续输出的 AI 推理或任务进度;
- 多人协作事件流;
- 内部服务之间的低延迟 RPC;
- 将现有 gRPC 服务迁移到更靠近用户的位置。
自动 gRPC-to-gRPC-Web 转换则面向浏览器兼容性。浏览器可以使用 gRPC-Web 客户端,而 Worker 负责与后端 gRPC 服务衔接。这样可以减少单独部署 Envoy 等转换层的需求,但上线前仍应验证元数据、状态码、流式模式和超时行为是否符合客户端预期。
可以这样实践:准备一个双向流 gRPC 服务
下面是一个可在本地运行、之后再改造成 Container 工作负载的最小 Python 示例。Cloudflare 的具体路由、Spectrum 配置和绑定名称应以账户中可用的产品配置为准;这里不假设尚未由来源说明的部署字段。
创建 chat.proto:
syntax = "proto3";
package edgechat;
service ChatService {
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
message ChatMessage {
string sender = 1;
string text = 2;
}
安装依赖并生成 Python 代码:
python -m venv .venv
. .venv/bin/activate
python -m pip install grpcio grpcio-tools
python -m grpc_tools.protoc \
-I. \
--python_out=. \
--grpc_python_out=. \
chat.proto
创建 server.py:
from concurrent import futures
import grpc
import chat_pb2
import chat_pb2_grpc
class ChatService(chat_pb2_grpc.ChatServiceServicer):
def Chat(self, request_iterator, context):
for message in request_iterator:
yield chat_pb2.ChatMessage(
sender="edge-server",
text=f"received from {message.sender}: {message.text}",
)
def serve() -> None:
server = grpc.server(futures.ThreadPoolExecutor(max_workers=8))
chat_pb2_grpc.add_ChatServiceServicer_to_server(ChatService(), server)
server.add_insecure_port("0.0.0.0:50051")
server.start()
print("gRPC server listening on 0.0.0.0:50051")
server.wait_for_termination()
if __name__ == "__main__":
serve()
再创建 client.py,验证客户端和服务端可以在一个 RPC 中交换多条消息:
import grpc
import chat_pb2
import chat_pb2_grpc
def outgoing_messages():
for text in ("hello", "streaming", "goodbye"):
yield chat_pb2.ChatMessage(sender="local-client", text=text)
with grpc.insecure_channel("localhost:50051") as channel:
client = chat_pb2_grpc.ChatServiceStub(channel)
for reply in client.Chat(outgoing_messages()):
print(f"{reply.sender}: {reply.text}")
分别启动服务端和客户端:
# 终端 1
. .venv/bin/activate
python server.py
# 终端 2
. .venv/bin/activate
python client.py
预期输出类似:
edge-server: received from local-client: hello
edge-server: received from local-client: streaming
edge-server: received from local-client: goodbye
容器化时,可以使用下面的 Dockerfile。部署到 Cloudflare Containers 后,再通过实际可用的 Spectrum 入站 TCP 配置把外部端口转发到容器的 50051 端口。
FROM python:3.12-slim
WORKDIR /app
COPY chat.proto server.py ./
RUN pip install --no-cache-dir grpcio grpcio-tools \
&& python -m grpc_tools.protoc \
-I. \
--python_out=. \
--grpc_python_out=. \
chat.proto
EXPOSE 50051
CMD ["python", "server.py"]
本地构建和测试:
docker build -t edge-grpc-demo .
docker run --rm -p 50051:50051 edge-grpc-demo
生产环境不应直接照搬示例中的明文连接。应在 Spectrum 和服务端链路中确认 TLS 终止方式、客户端认证以及容器内部端口是否需要加密。
浏览器接入时的边界
gRPC-Web 转换能缩短浏览器到 gRPC 服务的路径,但它不是应用层设计的替代品。接入前需要检查几个问题:
- 浏览器客户端使用的调用模式是否受支持,尤其是双向流行为;
- Worker 转换前后是否完整保留认证元数据;
- gRPC 状态码和错误详情能否被前端正确解析;
- 长连接的空闲超时、最大持续时间和重连策略;
- 单条消息、整个流以及容器实例的资源上限;
- 客户端断开后,服务端是否及时取消后台任务。
对于公开服务,还应在边缘执行身份验证、限流和连接数控制。TCP 连接比短 HTTP 请求占用资源更久,只限制每秒新建连接并不足够,还要限制每个租户的并发连接和流量。
上线前的选择清单
可以按工作负载决定运行位置:需要协调房间、设备或会话状态时,优先评估 Durable Objects;需要复用现有 gRPC 二进制、语言运行时或系统依赖时,Containers 通常更自然。若服务仍是无状态短请求,则没有必要仅为了使用新能力而改成 TCP。
上线前至少完成以下验证:
- 用真实客户端测试一元调用和实际采用的流式调用;
- 验证 TLS、认证元数据和 gRPC 状态码;
- 对断线、重连、半关闭和服务端取消执行故障测试;
- 测量长连接数量、消息吞吐、内存和实例扩缩容行为;
- 为连接时长、并发连接数和单租户流量设置上限;
- 确认 gRPC-Web 客户端所需的流式语义能够成立。
入站 TCP 让 Workers、Durable Objects 和 Containers 不再局限于请求响应式 HTTP 工作负载。真正的工程收益不只是“能打开一个端口”,而是可以把状态协调、协议转换和现有 gRPC 服务放进同一条边缘链路,同时保留对长连接资源和安全边界的明确控制。