Anthropic은 ConnectRPC에 대한 Rust 지원을 구축합니다.
hackernews
|
|
📦 오픈소스
#anthropic
#connectrpc
#rust
#tower
#프로토콜
#하드웨어/반도체
원문 출처: hackernews · Genesis Park에서 요약 및 분석
요약
안스로픽(Anthropic)은 ConnectRPC 프로토콜을 구현한 Rust 라이브러리인 'connectrpc'를 출시했다. 이 라이브러리는 HTTP 기반 RPC와 protobuf 메시지 지원을 제공하며, Tower::Service 런타임을 기반으로 Axum 및 Hyper와 같은 프레임워크와의 호환성을 보장한다. 또한 protoc 플러그인과 빌드 시 통합 기능을 포함하여 코드 생성과 클라이언트 연결 풀링을 지원한다.
본문
A Tower-based Rust implementation of the ConnectRPC protocol, providing HTTP-based RPC with protobuf messages in either binary or JSON form. connectrpc provides: connectrpc — A Tower-based runtime library implementing the Connect protocolprotoc-gen-connect-rust — Aprotoc plugin that generates service traits, clients, and message typesconnectrpc-build —build.rs integration for generating code at build time The runtime is built on tower::Service , making it framework-agnostic. It integrates with any tower-compatible HTTP framework including Axum, Hyper, and others. // greet.proto syntax = "proto3"; package greet.v1; service GreetService { rpc Greet(GreetRequest) returns (GreetResponse); } message GreetRequest { string name = 1; } message GreetResponse { string greeting = 1; } Two workflows are supported. Both produce the same runtime API; pick the one that fits your build pipeline. Runs two codegen plugins (protoc-gen-buffa for message types, protoc-gen-connect-rust for service stubs) and protoc-gen-buffa-packaging twice to assemble the mod.rs module tree for each output directory. The codegen plugins are invoked per-file; only the packaging plugin needs strategy: all . # buf.gen.yaml version: v2 plugins: - local: protoc-gen-buffa out: src/generated/buffa opt: [views=true, json=true] - local: protoc-gen-buffa-packaging out: src/generated/buffa strategy: all - local: protoc-gen-connect-rust out: src/generated/connect opt: [buffa_module=crate::proto] - local: protoc-gen-buffa-packaging out: src/generated/connect strategy: all opt: [filter=services] // src/lib.rs #[path = "generated/buffa/mod.rs"] pub mod proto; #[path = "generated/connect/mod.rs"] pub mod connect; buffa_module=crate::proto tells the service-stub generator where you mounted the buffa output. For a method input type greet.v1.GreetRequest it emits crate::proto::greet::v1::GreetRequest - the crate::proto root you named, then the proto package as nested modules, then the type. The second packaging invocation uses filter=services so the connect tree's mod.rs only include! s files that actually have service stubs in them. Changing the mount point requires regenerating. The underlying option is extern_path=.=crate::proto - same format the Buf Schema Registry uses when generating Cargo SDKs.buffa_module=X is shorthand for the. catch-all case. Unified output: message types and service stubs in one file per proto, assembled via a single include! . No plugin binaries required at build time. [build-dependencies] connectrpc-build = "0.2" // build.rs fn main() { connectrpc_build::Config::new() .files(&["proto/greet.proto"]) .includes(&["proto/"]) .include_file("_connectrpc.rs") .compile() .unwrap(); } // lib.rs include!(concat!(env!("OUT_DIR"), "/_connectrpc.rs")); use connectrpc::{Router, ConnectRpcService, Context, ConnectError}; use buffa::OwnedView; use std::sync::Arc; struct MyGreetService; impl GreetService for MyGreetService { async fn greet( &self, ctx: Context, request: OwnedView>, ) -> Result { // `request` derefs to the view — string fields are borrowed `&str` // directly from the request buffer (zero-copy). let response = GreetResponse { greeting: format!("Hello, {}!", request.name), ..Default::default() }; Ok((response, ctx)) } } use axum::{Router, routing::get}; use connectrpc::Router as ConnectRouter; use std::sync::Arc; let service = Arc::new(MyGreetService); let connect = service.register(ConnectRouter::new()); let app = Router::new() .route("/health", get(|| async { "OK" })) .fallback_service(connect.into_axum_service()); let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?; axum::serve(listener, app).await?; For simple cases, enable the server feature for a built-in hyper server: use connectrpc::{Router, Server}; use std::sync::Arc; let service = Arc::new(MyGreetService); let router = service.register(Router::new()); Server::new(router).serve("127.0.0.1:8080".parse()?).await?; Enable the client feature for HTTP client support with connection pooling: use connectrpc::client::{HttpClient, ClientConfig}; let http = HttpClient::plaintext(); // cleartext http:// only; use with_tls() for https:// let config = ClientConfig::new("http://localhost:8080".parse()?); let client = GreetServiceClient::new(http, config); let response = client.greet(GreetRequest { name: "World".into(), }).await?; Generated clients expose both a no-options convenience method and a _with_options variant for per-call control (timeout, headers, max message size, compression override): use connectrpc::client::CallOptions; use std::time::Duration; // Per-call timeout let response = client.greet_with_options( GreetRequest { name: "World".into() }, CallOptions::default().with_timeout(Duration::from_secs(5)), ).await?; For options you want on every call (e.g. auth headers, a default timeout), set them on ClientConfig instead — the no-options method picks them up automatically: let config = ClientConfig::new("http://localhost:8080".parse()?) .default_timeout(Duration:
Genesis Park 편집팀이 AI를 활용하여 작성한 분석입니다. 원문은 출처 링크를 통해 확인할 수 있습니다.
공유