2018-09-07 20:35:25 +02:00
|
|
|
use std::cell::Cell;
|
|
|
|
use std::rc::Rc;
|
|
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
2018-09-07 20:42:22 +02:00
|
|
|
use std::{fmt, net};
|
2018-08-19 19:47:04 +02:00
|
|
|
|
2018-09-07 20:35:25 +02:00
|
|
|
use futures::task::AtomicTask;
|
|
|
|
use futures::{future, Async, Future, Poll};
|
2018-08-19 19:47:04 +02:00
|
|
|
use tokio_reactor::Handle;
|
|
|
|
use tokio_tcp::TcpStream;
|
2018-08-22 02:08:23 +02:00
|
|
|
|
2018-08-24 00:42:34 +02:00
|
|
|
use super::{NewService, Service};
|
2018-08-19 19:47:04 +02:00
|
|
|
|
|
|
|
pub(crate) type BoxedServerService = Box<
|
|
|
|
Service<
|
|
|
|
Request = net::TcpStream,
|
|
|
|
Response = (),
|
|
|
|
Error = (),
|
|
|
|
Future = Box<Future<Item = (), Error = ()>>,
|
|
|
|
>,
|
|
|
|
>;
|
|
|
|
|
2018-09-07 20:35:25 +02:00
|
|
|
const MAX_CONNS: AtomicUsize = AtomicUsize::new(25600);
|
|
|
|
|
|
|
|
/// Sets the maximum per-worker number of concurrent connections.
|
|
|
|
///
|
|
|
|
/// All socket listeners will stop accepting connections when this limit is
|
|
|
|
/// reached for each worker.
|
|
|
|
///
|
|
|
|
/// By default max connections is set to a 25k per worker.
|
|
|
|
pub fn max_concurrent_connections(num: usize) {
|
|
|
|
MAX_CONNS.store(num, Ordering::Relaxed);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn num_connections() -> usize {
|
|
|
|
MAX_CONNS_COUNTER.with(|counter| counter.total())
|
|
|
|
}
|
|
|
|
|
|
|
|
thread_local! {
|
|
|
|
static MAX_CONNS_COUNTER: Counter = Counter::new(MAX_CONNS.load(Ordering::Relaxed));
|
|
|
|
}
|
|
|
|
|
2018-08-19 19:47:04 +02:00
|
|
|
pub(crate) struct ServerService<T> {
|
2018-09-07 20:35:25 +02:00
|
|
|
service: T,
|
|
|
|
counter: Counter,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> ServerService<T> {
|
|
|
|
fn new(service: T) -> Self {
|
|
|
|
MAX_CONNS_COUNTER.with(|counter| ServerService {
|
|
|
|
service,
|
|
|
|
counter: counter.clone(),
|
|
|
|
})
|
|
|
|
}
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Service for ServerService<T>
|
|
|
|
where
|
|
|
|
T: Service<Request = TcpStream, Response = ()>,
|
|
|
|
T::Future: 'static,
|
|
|
|
T::Error: fmt::Display + 'static,
|
|
|
|
{
|
|
|
|
type Request = net::TcpStream;
|
|
|
|
type Response = ();
|
|
|
|
type Error = ();
|
|
|
|
type Future = Box<Future<Item = (), Error = ()>>;
|
|
|
|
|
|
|
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
2018-09-07 20:35:25 +02:00
|
|
|
if self.counter.check() {
|
|
|
|
self.service.poll_ready().map_err(|_| ())
|
|
|
|
} else {
|
|
|
|
Ok(Async::NotReady)
|
|
|
|
}
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn call(&mut self, stream: net::TcpStream) -> Self::Future {
|
|
|
|
let stream = TcpStream::from_std(stream, &Handle::default()).map_err(|e| {
|
|
|
|
error!("Can not convert to an async tcp stream: {}", e);
|
|
|
|
});
|
|
|
|
|
|
|
|
if let Ok(stream) = stream {
|
2018-09-07 20:35:25 +02:00
|
|
|
let guard = self.counter.get();
|
|
|
|
|
|
|
|
Box::new(
|
|
|
|
self.service
|
|
|
|
.call(stream)
|
|
|
|
.map_err(|_| ())
|
|
|
|
.map(move |_| drop(guard)),
|
|
|
|
)
|
2018-08-19 19:47:04 +02:00
|
|
|
} else {
|
|
|
|
Box::new(future::err(()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-24 00:42:34 +02:00
|
|
|
pub(crate) struct ServerNewService<F, T>
|
|
|
|
where
|
|
|
|
F: Fn() -> T + Send + Clone,
|
|
|
|
{
|
2018-08-23 22:16:14 +02:00
|
|
|
inner: F,
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
|
2018-08-24 00:42:34 +02:00
|
|
|
impl<F, T> ServerNewService<F, T>
|
2018-08-19 19:47:04 +02:00
|
|
|
where
|
2018-08-23 22:16:14 +02:00
|
|
|
F: Fn() -> T + Send + Clone + 'static,
|
2018-09-07 20:42:22 +02:00
|
|
|
T: NewService<Request = TcpStream, Response = (), InitError = ()> + 'static,
|
2018-08-19 19:47:04 +02:00
|
|
|
T::Service: 'static,
|
|
|
|
T::Future: 'static,
|
|
|
|
T::Error: fmt::Display,
|
|
|
|
{
|
2018-08-24 00:42:34 +02:00
|
|
|
pub(crate) fn create(inner: F) -> Box<ServerServiceFactory + Send> {
|
2018-09-07 20:35:25 +02:00
|
|
|
Box::new(Self { inner })
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-24 00:42:34 +02:00
|
|
|
pub trait ServerServiceFactory {
|
|
|
|
fn clone_factory(&self) -> Box<ServerServiceFactory + Send>;
|
2018-08-19 19:47:04 +02:00
|
|
|
|
|
|
|
fn create(&self) -> Box<Future<Item = BoxedServerService, Error = ()>>;
|
|
|
|
}
|
|
|
|
|
2018-08-24 00:42:34 +02:00
|
|
|
impl<F, T> ServerServiceFactory for ServerNewService<F, T>
|
2018-08-19 19:47:04 +02:00
|
|
|
where
|
2018-08-23 22:16:14 +02:00
|
|
|
F: Fn() -> T + Send + Clone + 'static,
|
2018-09-07 20:42:22 +02:00
|
|
|
T: NewService<Request = TcpStream, Response = (), InitError = ()> + 'static,
|
2018-08-19 19:47:04 +02:00
|
|
|
T::Service: 'static,
|
|
|
|
T::Future: 'static,
|
|
|
|
T::Error: fmt::Display,
|
|
|
|
{
|
2018-08-24 00:42:34 +02:00
|
|
|
fn clone_factory(&self) -> Box<ServerServiceFactory + Send> {
|
2018-08-19 19:47:04 +02:00
|
|
|
Box::new(Self {
|
|
|
|
inner: self.inner.clone(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create(&self) -> Box<Future<Item = BoxedServerService, Error = ()>> {
|
2018-08-22 02:08:23 +02:00
|
|
|
Box::new(
|
2018-08-23 22:16:14 +02:00
|
|
|
(self.inner)()
|
2018-08-24 00:42:34 +02:00
|
|
|
.new_service()
|
2018-08-22 02:08:23 +02:00
|
|
|
.map(move |inner| {
|
2018-09-07 20:35:25 +02:00
|
|
|
let service: BoxedServerService = Box::new(ServerService::new(inner));
|
2018-08-22 02:08:23 +02:00
|
|
|
service
|
|
|
|
}),
|
|
|
|
)
|
2018-08-19 19:47:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-24 00:42:34 +02:00
|
|
|
impl ServerServiceFactory for Box<ServerServiceFactory> {
|
|
|
|
fn clone_factory(&self) -> Box<ServerServiceFactory + Send> {
|
2018-08-19 19:47:04 +02:00
|
|
|
self.as_ref().clone_factory()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create(&self) -> Box<Future<Item = BoxedServerService, Error = ()>> {
|
|
|
|
self.as_ref().create()
|
|
|
|
}
|
|
|
|
}
|
2018-09-07 20:35:25 +02:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub(crate) struct Counter(Rc<CounterInner>);
|
|
|
|
|
|
|
|
struct CounterInner {
|
|
|
|
count: Cell<usize>,
|
|
|
|
maxconn: usize,
|
|
|
|
task: AtomicTask,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Counter {
|
|
|
|
pub fn new(maxconn: usize) -> Self {
|
|
|
|
Counter(Rc::new(CounterInner {
|
|
|
|
maxconn,
|
|
|
|
count: Cell::new(0),
|
|
|
|
task: AtomicTask::new(),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(&self) -> CounterGuard {
|
|
|
|
CounterGuard::new(self.0.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn check(&self) -> bool {
|
|
|
|
self.0.check()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn total(&self) -> usize {
|
|
|
|
self.0.count.get()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct CounterGuard(Rc<CounterInner>);
|
|
|
|
|
|
|
|
impl CounterGuard {
|
|
|
|
fn new(inner: Rc<CounterInner>) -> Self {
|
|
|
|
inner.inc();
|
|
|
|
CounterGuard(inner)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for CounterGuard {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.0.dec();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CounterInner {
|
|
|
|
fn inc(&self) {
|
|
|
|
let num = self.count.get() + 1;
|
|
|
|
self.count.set(num);
|
|
|
|
if num == self.maxconn {
|
|
|
|
self.task.register();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn dec(&self) {
|
|
|
|
let num = self.count.get();
|
|
|
|
self.count.set(num - 1);
|
|
|
|
if num == self.maxconn {
|
|
|
|
self.task.notify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check(&self) -> bool {
|
|
|
|
self.count.get() < self.maxconn
|
|
|
|
}
|
|
|
|
}
|