Tokio does sync I/O in the background with dedicated I/O threads if memory serves. (it is sync in the sense it does syscalls, which are pushed to a dedicated thread).
I don't understand why some people think async is difficult to write. It's difficult if language doesn't have good support for it, but rust does. I remember async ruby was pretty weird to write initially.
(Your response isn't entirely accurate though: it's using a thread pool whose size is configurable, not one thread per spaw_blocking)