The Tokio Upgrade from 0.2 to 1.x

At Fly.io, we run a Rust-based load-balancer which handles almost all of our traffic. It stands on the shoulders of Tokio and Hyper. When the Tokio team announced 0.3 and then 1.0, we figured we’d have to upgrade sooner than later to access related cr

Jerome Gravel-Niquet
5 min readbeginner
--
View Original

Overview

The article discusses the upgrade of the Tokio framework from version 0.2 to 1.x, highlighting significant changes, improvements, and the rationale behind the upgrade. It emphasizes the importance of staying current with the rapidly evolving Rust ecosystem and provides insights into specific modifications in the API and usage patterns.

What You'll Learn

1

How to adapt your code to the new AsyncRead and AsyncWrite traits in Tokio 1.x

2

Why mutable access requirements have been relaxed in Tokio 1.x

3

When to use tokio-stream for Stream implementations

4

How to ensure TcpListener from_std is set to nonblocking

Key Questions Answered

What are the main differences between Tokio 0.2 and 1.x?
The main differences include the removal of Stream implementations until stabilization, relaxed mutable access requirements, new AsyncRead and AsyncWrite traits that return Result<(),()> instead of byte counts, and the need for TcpListener from_std to be set to nonblocking. These changes aim to improve usability and performance.
How do you handle the absence of block_on in runtime::Handle?
Currently, runtime::Handle does not implement block_on, but you can work around this by using Arc<Runtime> since block_on no longer requires mutable access to Runtime. This allows for easier management of asynchronous tasks without needing mutable references.
What should you do if TcpListener from_std is not set to nonblocking?
If TcpListener from_std is not set to nonblocking, the application may hang when accepting connections. It's crucial to set the listener to nonblocking before using it with Tokio to ensure that it operates correctly in an asynchronous context.

Technologies & Tools

Some links below are affiliate links. We may earn a commission if you make a purchase.

Backend
Tokio
Used as the asynchronous runtime for handling network operations.
Backend
Hyper
Used for building HTTP clients and servers in conjunction with Tokio.
Programming Language
Rust
The language in which Tokio and Hyper are implemented.

Key Actionable Insights

1
Ensure that your TcpListener is set to nonblocking to prevent application hangs when accepting connections.
This is particularly important when using socket2 to create TcpListeners with additional options. Not setting it to nonblocking can lead to unexpected behavior in your application.
2
Utilize tokio-stream for Stream implementations if you require Stream functionality in your application.
Since Tokio 1.x does not include Stream implementations, using tokio-stream allows you to maintain similar functionality while adhering to the new API changes.
3
Take advantage of the relaxed mutable access requirements in Tokio 1.x to simplify your code.
This change reduces the need for extensive locking mechanisms in your applications, making your code cleaner and potentially improving performance.

Common Pitfalls

1
Not setting TcpListener from_std to nonblocking can cause the application to hang when accepting connections.
This issue arises because the default behavior of standard TcpListeners is blocking. To avoid this, always ensure that the listener is explicitly set to nonblocking before integrating it with Tokio.

Related Concepts

Asynchronous Programming In Rust
Networking With Tokio
Stream And Future Patterns In Rust