сервер.
У меня есть состояние которое завернуто в Data<Arc<Mutex<State>>>
я завернул в не асинхронный мютекс состояние.
Есть роуты, один из них очень тяжелый, и там очень часто используется State,
я написал скрипт, который дает 100+ запросов за секунду по этому роуту,
и возникает проблема что запросы начинают обрабатываться, но это затягивается до вечности и если дать просто любой запрос на сервер, то он не обрабатывается а просто вечно грузится, может ли это быть из-за не асинхронного мютекса?
Я еще до конца не преисполнился в асинхронности и в мютексах и не совсем до конца понимаю из-за чего это, но подозреваю что это происходит из-за того что где-то в токио в планировщике задач параллельно блокируется мой State одновременно и из-за этого возникает проблема зависания. Поможет ли мне тут асинхронный мютекс? Или же мне использовать лучше сообщения? А может делить состояния на каждый запрос как это было показано в доках токио?
состояние актора завернуто в мьютекс?
Удерживается ли lock guard мьютекса через какие-либо await? Например: let state = state.lock().unwrap(); smth.await; state.do_smth()
да мой mutex используется в некоторых асинхрнных функциях если вы про это
Важно не только в асинхронных функциях, а как именно Универсальный рецеп +- такой: Если мьютекс держится поверх какого-то из .await, то его надо делать асинхронным Если нет - не надо
Вообще, если данные часто читаются, но редко изменяются, можно сделать так: Mutex<Arc<T>>, делать копию этого Arc под мьютексом и сразу освобождать его. Или, как вариант, использовать крейт arc-swap, который позволяет делать атомарный свап Arc. Если надо менять состояние, то можно сделать обновлённую копию, потом сделать std::mem::swap под блокировкой, освободить блокировку и дропнуть копию. Таким образом можно уменьшить критические секции. Ещё есть вариант разделить State на куски и каждый кусок защитить мьютексом, кусок выбирать через хэш каких-то входных данных запроса. Тогда 2 потока смогут одновременно работать, если у них хэши не совпадают. Асинхронный мьютекс поможет только другим запросам, которые вообще не используют эти данные.
Если данные часто читаются, но редко меняются нужен RwLock
С RwLock может случится, что будет writer starving (если у нас несправедливая реализация, например, в Linux). Вообще, зависит от ситуации. Если нам обязательно нужно новые данные возвращать, rwlock хорош, но в большинстве веб-сервисов eventual consistency приемлем. И в таких случаях есть смысл максимально сократить продолжительность критической секции.
Асинхронные мютексы и рвлоки помогли справится с этой проблемой
Обсуждают сегодня