mirror of
https://github.com/OMGeeky/tarpc.git
synced 2026-01-14 15:30:10 +01:00
-- Connection Limits The problem with having ConnectionFilter default-enabled is elaborated on in https://github.com/google/tarpc/issues/217. The gist of it is not all servers want a policy based on `SocketAddr`. This PR allows customizing the behavior of ConnectionFilter, at the cost of not having it enabled by default. However, enabling it is as simple as one line: incoming.max_channels_per_key(10, ip_addr) The second argument is a key function that takes the user-chosen transport and returns some hashable, equatable, cloneable key. In the above example, it returns an `IpAddr`. This also allows the `Transport` trait to have the addr fns removed, which means it has become simply an alias for `Stream + Sink`. -- Per-Channel Request Throttling With respect to Channel's throttling behavior, the same argument applies. There isn't a one size fits all solution to throttling requests, and the policy applied by tarpc is just one of potentially many solutions. As such, `Channel` is now a trait that offers a few combinators, one of which is throttling: channel.max_concurrent_requests(10).respond_with(serve(Server)) This functionality is also available on the existing `Handler` trait, which applies it to all incoming channels and can be used in tandem with connection limits: incoming .max_channels_per_key(10, ip_addr) .max_concurrent_requests_per_channel(10).respond_with(serve(Server)) -- Global Request Throttling I've entirely removed the overall request limit enforced across all channels. This functionality is easily gotten back via [`StreamExt::buffer_unordered`](https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.1/futures/stream/trait.StreamExt.html#method.buffer_unordered), with the difference being that the previous behavior allowed you to spawn channels onto different threads, whereas `buffer_unordered ` means the `Channels` are handled on a single thread (the per-request handlers are still spawned). Considering the existing options, I don't believe that the benefit provided by this functionality held its own.
61 lines
2.3 KiB
Rust
61 lines
2.3 KiB
Rust
// Copyright 2018 Google LLC
|
|
//
|
|
// Use of this source code is governed by an MIT-style
|
|
// license that can be found in the LICENSE file or at
|
|
// https://opensource.org/licenses/MIT.
|
|
|
|
//! Provides a request context that carries a deadline and trace context. This context is sent from
|
|
//! client to server and is used by the server to enforce response deadlines.
|
|
|
|
use std::time::{Duration, SystemTime};
|
|
use trace::{self, TraceId};
|
|
|
|
/// A request context that carries request-scoped information like deadlines and trace information.
|
|
/// It is sent from client to server and is used by the server to enforce response deadlines.
|
|
///
|
|
/// The context should not be stored directly in a server implementation, because the context will
|
|
/// be different for each request in scope.
|
|
#[derive(Clone, Copy, Debug)]
|
|
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
|
|
#[non_exhaustive]
|
|
pub struct Context {
|
|
/// When the client expects the request to be complete by. The server should cancel the request
|
|
/// if it is not complete by this time.
|
|
#[cfg_attr(
|
|
feature = "serde1",
|
|
serde(serialize_with = "crate::util::serde::serialize_epoch_secs")
|
|
)]
|
|
#[cfg_attr(
|
|
feature = "serde1",
|
|
serde(deserialize_with = "crate::util::serde::deserialize_epoch_secs")
|
|
)]
|
|
#[cfg_attr(feature = "serde1", serde(default = "ten_seconds_from_now"))]
|
|
pub deadline: SystemTime,
|
|
/// Uniquely identifies requests originating from the same source.
|
|
/// When a service handles a request by making requests itself, those requests should
|
|
/// include the same `trace_id` as that included on the original request. This way,
|
|
/// users can trace related actions across a distributed system.
|
|
pub trace_context: trace::Context,
|
|
}
|
|
|
|
#[cfg(feature = "serde1")]
|
|
fn ten_seconds_from_now() -> SystemTime {
|
|
return SystemTime::now() + Duration::from_secs(10);
|
|
}
|
|
|
|
/// Returns the context for the current request, or a default Context if no request is active.
|
|
// TODO: populate Context with request-scoped data, with default fallbacks.
|
|
pub fn current() -> Context {
|
|
Context {
|
|
deadline: SystemTime::now() + Duration::from_secs(10),
|
|
trace_context: trace::Context::new_root(),
|
|
}
|
|
}
|
|
|
|
impl Context {
|
|
/// Returns the ID of the request-scoped trace.
|
|
pub fn trace_id(&self) -> &TraceId {
|
|
&self.trace_context.trace_id
|
|
}
|
|
}
|