actix-web: Connection pool using client::get(uri).with_connector(...) is not respecting keep-alive

I hacked together a quick proxy which is very similar to the proxy example, except I’m using ClientRequestBuilder.with_connector() trying to utilize the built-in connection pooling.

#![feature(proc_macro, generators)]

extern crate actix;
extern crate actix_web;
extern crate futures_await as futures;

use actix::{Actor, Addr, Unsync};
use actix_web::{client, server, App, Path, State};
use actix_web::http::Method;
use futures::prelude::*;

struct AppState {
    conn: Addr<Unsync, client::ClientConnector>,
}

#[async(boxed)]
fn index(info: Path<(u32, String)>, state: State<AppState>) -> Result<String, actix_web::error::Error> {
    let uri = format!("http://127.0.0.1:8081/{}/{}/index.html", info.0, info.1);

    let resp = await!(client::get(uri)
        .with_connector(state.conn.clone())
        .no_default_headers()
        .upgrade()
        .finish()?
        .send()
    )?;

    let body = await!(resp.into_future())
        .unwrap()
        .0
        .unwrap();

    Ok(std::str::from_utf8(&body)?.to_owned())
}

fn main() {
    let addr = "127.0.0.1:8080";
    println!("Listening on http://{}", addr);

    server::new(|| {
        let conn: Addr<Unsync, _> = client::ClientConnector::default().start();
        App::with_state(AppState{conn})
            .resource("/{id}/{name}/index.html", |r| r.method(Method::GET).with2(index))
    }).bind(addr)
        .unwrap()
        .run();
}

The proxy functionality works (using the basic hello-world example as an upstream on port 8081), but keep-alive is not working, as you can see from tcpdump:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
18:05:42.542170 IP 127.0.0.1.58422 > 127.0.0.1.8080: Flags [S], seq 1194112351, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 1218386738 ecr 0,sackOK,eol], length 0
18:05:42.542279 IP 127.0.0.1.8080 > 127.0.0.1.58422: Flags [S.], seq 3083285766, ack 1194112352, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 1218386738 ecr 1218386738,sackOK,eol], length 0
18:05:42.542301 IP 127.0.0.1.58422 > 127.0.0.1.8080: Flags [.], ack 1, win 12759, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.542322 IP 127.0.0.1.8080 > 127.0.0.1.58422: Flags [.], ack 1, win 12759, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.542350 IP 127.0.0.1.58422 > 127.0.0.1.8080: Flags [P.], seq 1:154, ack 1, win 12759, options [nop,nop,TS val 1218386738 ecr 1218386738], length 153: HTTP: GET /123/jay/index.html HTTP/1.1
18:05:42.542367 IP 127.0.0.1.8080 > 127.0.0.1.58422: Flags [.], ack 154, win 12754, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.542567 IP 127.0.0.1.58423 > 127.0.0.1.8081: Flags [S], seq 1266615293, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 1218386738 ecr 0,sackOK,eol], length 0
18:05:42.542637 IP 127.0.0.1.8081 > 127.0.0.1.58423: Flags [S.], seq 2134870156, ack 1266615294, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 1218386738 ecr 1218386738,sackOK,eol], length 0
18:05:42.542647 IP 127.0.0.1.58423 > 127.0.0.1.8081: Flags [.], ack 1, win 12759, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.542658 IP 127.0.0.1.8081 > 127.0.0.1.58423: Flags [.], ack 1, win 12759, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.542708 IP 127.0.0.1.58423 > 127.0.0.1.8081: Flags [P.], seq 1:91, ack 1, win 12759, options [nop,nop,TS val 1218386738 ecr 1218386738], length 90
18:05:42.542726 IP 127.0.0.1.8081 > 127.0.0.1.58423: Flags [.], ack 91, win 12756, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.542810 IP 127.0.0.1.8081 > 127.0.0.1.58423: Flags [P.], seq 1:135, ack 91, win 12756, options [nop,nop,TS val 1218386738 ecr 1218386738], length 134
18:05:42.542827 IP 127.0.0.1.58423 > 127.0.0.1.8081: Flags [.], ack 135, win 12755, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.542908 IP 127.0.0.1.8080 > 127.0.0.1.58422: Flags [P.], seq 1:135, ack 154, win 12754, options [nop,nop,TS val 1218386738 ecr 1218386738], length 134: HTTP: HTTP/1.1 200 OK
18:05:42.542935 IP 127.0.0.1.58422 > 127.0.0.1.8080: Flags [.], ack 135, win 12755, options [nop,nop,TS val 1218386738 ecr 1218386738], length 0
18:05:42.546016 IP 127.0.0.1.58422 > 127.0.0.1.8080: Flags [F.], seq 154, ack 135, win 12755, options [nop,nop,TS val 1218386741 ecr 1218386738], length 0
18:05:42.546051 IP 127.0.0.1.8080 > 127.0.0.1.58422: Flags [.], ack 155, win 12754, options [nop,nop,TS val 1218386741 ecr 1218386741], length 0
18:05:42.546107 IP 127.0.0.1.8080 > 127.0.0.1.58422: Flags [F.], seq 135, ack 155, win 12754, options [nop,nop,TS val 1218386741 ecr 1218386741], length 0
18:05:42.546137 IP 127.0.0.1.58422 > 127.0.0.1.8080: Flags [.], ack 136, win 12755, options [nop,nop,TS val 1218386741 ecr 1218386741], length 0
18:05:43.200008 IP 127.0.0.1.58423 > 127.0.0.1.8081: Flags [F.], seq 91, ack 135, win 12755, options [nop,nop,TS val 1218387384 ecr 1218386738], length 0
18:05:43.200039 IP 127.0.0.1.8081 > 127.0.0.1.58423: Flags [.], ack 92, win 12756, options [nop,nop,TS val 1218387384 ecr 1218387384], length 0
18:05:43.200085 IP 127.0.0.1.8081 > 127.0.0.1.58423: Flags [F.], seq 135, ack 92, win 12756, options [nop,nop,TS val 1218387385 ecr 1218387384], length 0
18:05:43.200123 IP 127.0.0.1.58423 > 127.0.0.1.8081: Flags [.], ack 136, win 12755, options [nop,nop,TS val 1218387385 ecr 1218387385], length 0

I would expect the FIN packets to not be sent to port 8081 (timestamps 18:05:43.200008 and above) if keep-alive was working, and the sockets should be reused indefinitely. The FIN is also delayed from the last ACK packet at 18:05:42.542827 … by about 650ms.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 16 (9 by maintainers)

Commits related to this issue

Most upvoted comments

fixed in master, i will release new version later this week.