Rust is a systems programming language. Modern server software -- a primary use case for a systems language -- is heavily async by default for a long list of compelling architectural reasons. Providing first-class language tooling to support that seems eminently sensible since this is how people will want to use the language.
When you are writing high-performance server code, async is the common scenario.
async is not the default. The standard library is 100% blocking, and Rust does not come with a runtime. However, async makes sense for a lot of people, which is why libraries like tokio and async-std are so popular.
Web servers are the quintessential product of async. It’s no surprise that for an industry dominated by web titans spend a lot of time writing web servers and have a huge interest in asynchronous processing. The importance of a sync was cemented way back in 1999 with the c10k problem with nginx vs Apache.
Ah yeah, as someone whose first langauge is javascript where all IO and even things like timers are async, I forget that not everyone groks it. It's really not that complicated (at work we have junior devs with 6 months experience writing async code no problem), but I think there is a certain amount of unlearning that needs to be done if you're used to working with threaded code.
>But for the rest of us, simple, blocking code will do just fine and save us a few headaches.
I understand your point, but if performance isn't a concern, why use Rust at all? If the intricacies of async is that much of a burden then Rust is probably not the right tool of the job.
And once you get to a limit, the alternative to rewriting everything in non-blocking code might be to put multiple instances of your blocking app on multiple VMs/k8s/whatever behind a load balancer.
Or, you just take the initial leap and write async from the start. For languages with decent abstractions such as async/await, it really isn't hard when you've done it for a while, and I'd make the same argument as one of the parent posters in that it's great "documentation".
K8s is brings way more complexity and headache, so it's kind of funny that you suggest that before using async/await.
I haven't used async in Python, but I'd bet you don't really _need_ to understand every single one of those concepts, unless you're developing something very niche and low level (or an interpreter). If you do need to know it, I'd argue that it's not a great abstraction; you definitely don't need to know that implementation details and concepts in either C# or Rust to use async/await.
Setting up k8s once solves the problem for all your apps. In contrast, the additional software complexity of async/await is duplicated across all of them.
If your planning to scale up, k8s is likely something you'll want later. Additional complexity in your apps is not.
My point was that it really isn't that much additional complexity. 99.9% of the time, the main difference is that you'll have to write "await". You don't really need to know that there's a state machine hiding beneath.
In fairness it's just the announcement of V1 of the library. There doesn't seem to me to be anyone promoting its use "everywhere".
On the other hand, there has been from day one a sort of hype around Rust's safety features, and an eagerness to promote any new library or framework written in Rust as a savior of programming. This library, as you note, will be used inappropriately (i.e. in contexts where it's not really necessary or reasonable to do) and lead to the worst kinds of bugs--those that lurk in complicated, difficult to understand code, and that are generally worse than any memory-related security vulnerability.
If you think OS threads are "better" than async tasks, then use them. Other people want to use async, so they use it. Rust does not have a runtime and provides blocking APIs by default, but gives you the option to use async if you want to.
In rust you can block your thread on the completion of an async future. Let other people use async code if they want to, and you can write your code in a syncronous blocking kind of way.
It should, but it shouldn't be the default. Right now, reqwest is the default HTTP request library in Rust ecosystem, and async is mandatory for reqwest. This is a bad situation to be in.
reqwest provides a blocking API, but reqwest also always depends on Tokio. A blocking API doesn't help when I don't want Tokio in my dependency tree at all.
I am using isahc, but that also doesn't help when (say) Rusoto AWS library pulls reqwest pulls Tokio pulls async.
Can you explain exactly what that library using Tokio internally exposes to you that's a problem? Because, as written, this sounds like a religious argument.
If you need to use (for the sake of the example) Rusoto, since it is based on tokio, you'll need to set up the Tokio executor or at least add a macro to your main for this to be done for you. I believe Rusoto actually would take care of this for you if you haven't done it yourself however friction arises when you were already using a different version of tokio and Rusoto is built against another.
Basically, it isn't entirely opaque to you how it is handled.
I had a simple rust program that used reqwest -- it just pulled down a few web pages and parsed some data out of tables in the HTML. At the time reqwest had a simple synchronous API function that made this easy. The version of reqwest which added async support broke compatibility of that function and didn't appear to provide any similarly easy to use equivalent. Luckily my use-case went away (the website I was screen scraping died) so I didn't need to try to actually fix my program to work with newer reqwest versions. But it left a pretty sour taste regarding async...