Apache Fory 团队很高兴宣布 1.3.0 版本正式发布。本版本包含来自 3 位贡献者的 8 个 PR,并继续改进各支持语言的跨语言运行时。请访问 Install 页面 获取各平台安装方式。
发布亮点
- Python gRPC 代码生成现在默认使用
grpc.aioAsyncIO API;同步grpcio输出仍可通过--grpc-python-mode=sync显式启用。 - Dart 加入生成式 gRPC service 支持:
foryc --dart_out=... --grpc现在会生成package:grpcclient、service base、method descriptor,以及基于 Fory 的 payload 序列化逻辑。 - Compiler gRPC 文档在多个语言上进一步细化,包括更清晰的生成 service 依赖和传输行为说明。
- 运行时继续增强安全性,加入远端 schema metadata 限制,并修复 Java aligned-varint 与 type-checker cache 相关问题。
Python Async gRPC 模式
Python gRPC 生成现在默认面向 AsyncIO。生成的 companion 使用 grpc.aio:servicer base 暴露 async def 方法,stub 搭配 grpc.aio.Channel 使用,streaming RPC 使用 async iterable。这让生成代码更适合现代 Python async service,同时仍保留既有 gRPC 支持中的 Fory-backed request/response 编码方式。
默认 async companion 生成命令如下:
foryc service.fdl --python_out=./generated/python --grpc
对于简单 unary service,生成代码对应的 async server 形态如下:
import asyncio
import grpc.aio
import demo_greeter
import demo_greeter_grpc
class Greeter(demo_greeter_grpc.GreeterServicer):
async def say_hello(self, request, context):
return demo_greeter.HelloReply(reply=f"Hello, {request.name}")
async def serve():
server = grpc.aio.server()
demo_greeter_grpc.add_servicer(Greeter(), server)
server.add_insecure_port("[::]:50051")
await server.start()
await server.wait_for_termination()
asyncio.run(serve())
Client 使用 grpc.aio channel,并 await 生成的 stub 方法:
import grpc
import grpc.aio
import demo_greeter
import demo_greeter_grpc
credentials = grpc.ssl_channel_credentials()
async with grpc.aio.secure_channel("api.example.com:443", credentials) as channel:
stub = demo_greeter_grpc.GreeterStub(channel)
reply = await stub.say_hello(demo_greeter.HelloRequest(name="Fory"))
已有同步应用仍可显式请求 sync companion:
foryc service.fdl --python_out=./generated/python --grpc --grpc-python-mode=sync
Sync 模式保持相同的生成 public name 和 <module>_grpc.py 文件名,但应用使用 grpc.server(...)、标准 grpc.Channel 实例,以及普通 def servicer 方法。
Dart gRPC 代码生成
Fory 1.3.0 为包含 service 定义的 schema 增加 Dart gRPC service 生成。Service 定义可以来自 Fory IDL、protobuf IDL 或 FlatBuffers rpc_service。生成代码使用标准 grpc-dart API 来处理 client、service base、method descriptor、call option、deadline、取消、metadata 和 status code;每个 request/response 对象则使用 Fory 序列化,而不是 protobuf message bytes。
在 Dart 应用中,除 Fory package 外,还需要加入 grpc 和 build_runner:
dependencies:
fory: ^1.3.0
grpc: ^4.0.0
dev_dependencies:
build_runner: ^2.4.0
生成 Dart model 和 gRPC companion:
foryc service.fdl --dart_out=./lib/generated --grpc
dart run build_runner build --delete-conflicting-outputs
对于 demo.greeter package,generator 会输出 model 文件、由 build_runner 生成的 serializer part,以及包含 GreeterServiceBase 和 GreeterClient 的 <stem>_grpc.dart companion。生成的 client 和 service base 会在首次使用时自动安装该 schema 的 Fory module,因此 service 实现不需要为生成的 message type 单独手动注册。
Unary Dart server 使用 grpc-dart 的 Server 和生成的 service base:
import 'dart:io';
import 'package:grpc/grpc.dart';
import 'demo/greeter/greeter.dart';
import 'demo/greeter/greeter_grpc.dart';
class GreeterService extends GreeterServiceBase {
Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
return HelloReply()..reply = 'Hello, ${request.name}';
}
}
Future<void> main() async {
final server = Server.create(services: [GreeterService()]);
await server.serve(address: InternetAddress.loopbackIPv4, port: 50051);
}
生成的 Dart client 使用标准 ClientChannel,并返回 grpc-dart 调用类型:
import 'package:grpc/grpc.dart';
import 'demo/greeter/greeter.dart';
import 'demo/greeter/greeter_grpc.dart';
final channel = ClientChannel(
'localhost',
port: 50051,
options: const ChannelOptions(credentials: ChannelCredentials.insecure()),
);
final client = GreeterClient(channel);
final reply = await client.sayHello(HelloRequest()..name = 'Fory');
await channel.shutdown();
Dart 生成支持 unary、server-streaming、client-streaming 和 bidirectional streaming 四种 RPC 形态,并遵循 grpc-dart 约定。
Features
- feat(python): add async grpc mode for python by @chaokunyang in https://github.com/apache/fory/pull/3768
- feat: limit remote schema metadata by @chaokunyang in https://github.com/apache/fory/pull/3770
- feat(compiler): add dart gRPC codegen by @yash-agarwa-l in https://github.com/apache/fory/pull/3723
Bug Fix
- fix(java): guard aligned varint unsafe read by @chaokunyang in https://github.com/apache/fory/pull/3772
- fix(java): cache accepted type checker classes by @chaokunyang in https://github.com/apache/fory/pull/3773
Other Improvements
- docs: refine gRPC support guides by @chaokunyang in https://github.com/apache/fory/pull/3767
- docs: add threat model + SECURITY.md/AGENTS.md discoverability by @potiuk in https://github.com/apache/fory/pull/3734
- chore(release): enforce OpenJDK 25 for JVM publishing by @chaokunyang in https://github.com/apache/fory/pull/3775
New Contributors
- @potiuk made their first contribution in https://github.com/apache/fory/pull/3734
Full Changelog: https://github.com/apache/fory/compare/v1.2.0...v1.3.0
