spin
spin copied to clipboard
HTTPS Connection reuse from Spin worker
Hi all,
I am looking into possibly having two outbound HTTPS calls from my Spin worker or Webasembly module in general to the same server and reusing the connection.
It would be beneficial so we don't have to do a handshake to the server again, and requests over the network would be faster for that use-case.
If I understood correctly, there is no technical reason why we can't support connection reuse with wasi-http, I have not found a good code example of the implementation for that use case.
Is this something that is planned to be implemented in Spin? Could you please point me to some examples that cover this use case?
Thank you!
@dicej Is this something @dlozina could access by wit-bindgen-ing the wasi-http outgoing-handler interface directly into their project, or is it something the Spin host would need to (invisibly) do?
This requires a Spin change. Currently, we use the default outgoing request handler provided by wasmtime-wasi-http (https://github.com/fermyon/spin/blob/b86af6c7188e84f5824f7eef757c65ff2ad265c4/crates/core/src/lib.rs#L236), which creates a new TCP connection and sends the request using hyper: https://github.com/bytecodealliance/wasmtime/blob/de0a9d7ce959d83a336d4f13487cf00e69e9efb2/crates/wasi-http/src/types.rs#L114. In order to reuse requests, we'd need to provide our own handler instead.
One appealing option would be to use reqwest, which has built-in support for connection pooling. However, as of this writing it does not yet support trailers, which means it can't be used to fully implement wasi:http/outgoing-handler. Using trailers is pretty rare in the real world, though, so perhaps that's an acceptable tradeoff.
Hi @itowlson and @dicej , first of all thank you for the extremely fast response! 🙏🏻
I agree with @dicej , trailer support is not a dealbreaker ATM.
@dicej does this boils down changing hyper with reqwest?
@dlozina We'll need to create an outgoing http implementation from scratch based on reqwest instead of using the one provided by wasmtime-wasi-http, which is based on hyper. It shouldn't be terribly difficult. FWIW, I created one for wasi:[email protected] which we could use as a starting point: https://github.com/dicej/isyswasfa/blob/df9a153fafbbdf532d811bdc53e61ff7368e4898/cli/src/main.rs#L126-L244
BTW, @lann has done a bit of research, and it looks like adding basic trailer support to reqwest could be pretty easy.
That is great! Thank you @dicej How can I help? This is not something I have done before but I am willing to learn and put in the work.
@dlozina If you want to try making a PR for this, the code should go here: https://github.com/fermyon/spin/blob/b86af6c7188e84f5824f7eef757c65ff2ad265c4/crates/trigger-http/src/lib.rs#L694. You'll want to replace the wasmtime_wasi_http::types::default_send_request(data, request) line with code that translates the wasmtime_wasi_http::types::OutgoingRequest into a reqwest::Client::request call similar to the code I linked to above, and then translate the resulting response into a wasmtime_wasi_http::types::HostFutureIncomingResponse. The key to making reqwest reuse connections is to reuse a reqwest::Client instance, which means you'll want to add that as a field to the HttpRuntimeData struct in that file.
@dicej thanks for the instructions and help! 🙏🏻