#conjure #client-server #async-client #service #async-http #interface

conjure-runtime

与Conjure生成的服务兼容的HTTP客户端

29个版本 (17个稳定版)

5.1.0 2024年7月1日
5.0.0-rc12024年5月24日
4.7.1 2024年5月6日
4.7.0 2023年8月18日
0.2.0 2020年2月13日

#26HTTP客户端

Download history 2000/week @ 2024-04-28 1865/week @ 2024-05-05 1559/week @ 2024-05-12 1668/week @ 2024-05-19 1305/week @ 2024-05-26 1818/week @ 2024-06-02 1760/week @ 2024-06-09 1459/week @ 2024-06-16 1154/week @ 2024-06-23 1684/week @ 2024-06-30 1318/week @ 2024-07-07 1493/week @ 2024-07-14 1678/week @ 2024-07-21 1758/week @ 2024-07-28 1689/week @ 2024-08-04 1521/week @ 2024-08-11

每月下载量6,750
2 个Crate中使用(通过 witchcraft-server

Apache-2.0

350KB
8K SLoC

Autorelease

Conjure Rust运行时

CircleCI

文档

conjure-runtime 是Rust编程语言的客户端HTTP框架。它可以与Conjure接口一起使用,也可以作为独立客户端。有关更多详细信息,请参阅该框架的文档。

许可证

本存储库在Apache 2.0许可证下提供。


lib.rs:

用于与Conjure服务器一起使用的HTTP客户端。

该crate提供异步和阻塞客户端,这些客户端可以用于Conjure生成的包装类型,也可以用于与非Conjure服务器一起使用。

配置

虽然可以通过编程方式构建conjure_runtime客户端,但更常见的做法是从服务的运行时重新加载配置文件反序列化配置。 ServicesConfig支持为多个下游服务配置,并允许进行全局和针对特定服务的配置覆盖。

services:
  auth-service:
    uris:
      - https://auth.my-network.com/auth-service
  cache-service:
    uris:
      - https://cache-1.my-network.com/cache-service
      - https://cache-2.my-network.com/cache-service
    request-timeout: 10s
# options set at this level will apply as defaults to all configured services
security:
  ca-file: var/security/ca.pem

使用refreshable crate,可以与ClientFactory类型一起使用,创建用于配置服务的实时更新客户端。

用法

首先构建原始Client

use conjure_runtime::{UserAgent, Agent, Client};
use conjure_runtime::config::SecurityConfig;
use std::path::PathBuf;

let client = Client::builder()
    .service("test-service")
    .user_agent(UserAgent::new(Agent::new("my-user-agent", "1.0.0")))
    .uri("https://url-to-server:1234/test-service".parse().unwrap())
    .security(
        SecurityConfig::builder()
            .ca_file(Some(PathBuf::from("path/to/ca_file.pem")))
            .build(),
    )
    .build()?;

然后可以使用该客户端与Conjure生成的服务接口一起使用

use conjure_codegen::example_types::another::TestServiceAsyncClient;
use conjure_http::client::AsyncService;
use conjure_object::BearerToken;

let client = TestServiceAsyncClient::new(client);

let auth = BearerToken::new("my_auth_token").unwrap();
let file_systems = client.get_file_systems(&auth).await?;

blocking::Client 的 API 是相同的,唯一的区别是你不能在方法上使用 .await

use conjure_codegen::example_types::another::TestServiceClient;
use conjure_http::client::Service;
use conjure_object::BearerToken;

let client = TestServiceClient::new(client);

let auth = BearerToken::new("my_auth_token").unwrap();
let file_systems = client.get_file_systems(&auth)?;

可以通过直接使用低级的 ClientAsyncClient 特性来使用客户端与非 Conjure API 进行通信。

行为

conjure_runtime 使用有见地的行为包装了 hyper HTTP 库,以更有效地在分布式系统中的服务之间进行通信。它广泛设计,以与 dialogue Java 库相一致,尽管它在各个方面都存在差异。

错误传播

服务器应该使用标准的 Conjure 错误格式将应用程序特定的错误传播给调用者。从服务器接收到的非 QoS(见下文)错误被视为致命错误。默认情况下,conjure_runtime 将返回一个 conjure_error::Error,它将生成通用的 500 内部服务器错误响应。其原因是包含由服务器发送的序列化 Conjure 错误信息的 RemoteError 对象。可以使用 [Builder::service_error()] 和 [ClientFactory::service_error()] 方法来更改此行为,以透明地传播从服务器接收到的错误。返回的 conjure_error::Error 将生成客户端从服务器接收到的相同响应。

调用跟踪

客户端通过使用传统的 X-B3-* HTTP 头部,通过 zipkin 包传播跟踪信息。它还创建覆盖请求处理各个阶段的本地跨度。

  • conjure-runtime:request
    • conjure-runtime:attempt
      • conjure-runtime: acquire-permit - 如果客户端 QoS 启用并且节点选择策略不是 Balanced,则此跨度覆盖获取并发限制许可所花费的时间。
      • conjure-runtime: balanced-node-selection - 如果节点选择策略是 Balanced,则此跨度覆盖选择节点的时间(如果客户端 QoS 启用,则还包括获取并发限制许可的时间)。
      • conjure-runtime: wait-for-headers - 此跨度发送到服务器,并持续到服务器发送响应头。
      • conjure-runtime: wait-for-body - 该跨度与响应体一起跟踪,直到 ResponseBody 对象被丢弃。它从 zipkin 跟踪器中“分离”出来,因此 conjure-runtime 外部创建的新跨度不会成为其父跨度,并且可以超出父 conjure-runtime 跨度的生命周期。如果在接收到头部之前发生 IO 错误,则不会创建它。
    • conjure-runtime: backoff-with-jitter - 如果请求被重试,这个跨度会跟踪尝试之间的等待时间。
    • conjure-runtime:attempt
      • ...

服务质量:重试、故障转移、节流和背压

客户端对某些 HTTP 错误进行特殊处理。服务器可以通过 429 Too Many Requests 或 503 Service Unavailable 状态代码来宣传过载状态。与其它 4xx 和 5xx 状态代码不同,这些响应不会导致请求失败。相反,conjure_runtime 会自行节流并重试请求。请求会以固定的次数重试,尝试之间的回退时间呈指数增长。如果 429 响应包含 Retry-After 头部,则使用其回退而不是默认值。IO 错误也会触发重试。

503 响应或 IO 错误还会导致该主机暂时进入“冷却”状态,因此除非没有其他选择,否则它不会被其他请求使用。

只有一些请求可以被重试。默认情况下,conjure_runtime 只会重试被识别为幂等的 HTTP 方法的请求 - GETPUTDELETEHEADTRACEOPTIONS。不可幂等的请求不能安全地重试,以避免如果请求最终被应用两次而出现意外行为的风险。可以使用 [Builder::idempotency()] 和 [ClientFactory::idempotency()] 方法来覆盖此行为,并让客户端假设所有或没有请求是幂等的。此外,具有流式请求体的请求只有在错误发生时身体尚未开始写入或已成功重置以进行另一次尝试时才能重试。

指标

客户端将指标记录到标准的 MetricRegistryconjure_runtime-特定的 HostMetricsRegistry

标准指标

  • client.response (channel-name: <channel_name>, service-name: <service_name>, endpoint: <endpoint>, status: <status>) - 记录每个端点的请求持续时间的Timer。注意,这个指标记录的用户感知请求包括任何回退/重试等。它只记录收到响应头的时间,而不是读取整个响应体的时间。《tt class="src-rs">status标签将根据响应状态码是2xx时为success,否则为failure(服务质量失败、内部服务器错误、IO错误等)。
  • tls.handshake (context: <service_name>, protocol: <protocol_version>, cipher: <cipher_name>) - 通过服务、TLS协议版本(例如TLSv1.3)和加密名称(例如TLS_CHACHA20_POLY1305_SHA256)标记的Meter,跟踪TLS握手的速率。
  • conjure-runtime.concurrencylimiter.max (service: <service_name>, hostIndex: <host_index>) - 报告当前允许向特定主机发出的并发请求数量的最大值的Gauge
  • conjure-runtime.concurrencylimiter.in-flight (service: <service_name>, hostIndex: <host_index>) - 报告当前正在向特定主机发出的请求数量的Gauge

主机指标

HostMetricsRegistry 包含正在由 conjure_runtime 客户端使用的每个服务的每个主机的指标。

依赖

约23–36MB
~658K SLoC