Если вы хотите быть абсолютно уверены в том, что данный пользователь никогда не испытает задержки из-за того, что процесс R используется кем-то другим, тогда да, вам понадобится 400 потоков для 400 одновременных пользователей.
In практика, и если (как вы говорите) в приложении не так много вычислительно-ресурсоемких функций, то вы можете обойтись значительно меньшим количеством ядер. Если пользователю требуется, скажем, 200 мс для вычисления некоторой функции, тогда вам понадобится несколько пользователей в одном потоке, выполняющих такую функцию одновременно, прежде чем кто-либо заметит значительную (например, 1 с) задержку. Скорее всего, вам удастся обойтись десятками одновременных подключений на поток, прежде чем пользовательский интерфейс не пострадает, если не будут задействованы тяжелые вычисления.
Сказав все это, я понимаю, что ShinyProxy будет запускать новый экземпляр для каждого нового соединения, поэтому количество одновременно работающих пользователей может быть ограничено количеством ядер. Я не совсем понимаю по этому поводу. Однако, если это так, и если предположить, что модель состоит из нескольких сотен соединений, но с небольшими требованиями к обработке, я думаю, что лучшим подходом может быть несколько экземпляров Shiny Server за балансировщиком нагрузки. Серверы не должны быть особенно мощными (в любом случае вы используете только один поток). Каждый сервер может обрабатывать> 100 подключений (я не знаю, есть ли верхний предел).
Подводя итог, на мой взгляд, ShinyProxy лучше, когда у вас меньше подключений, работающих больше приложения с интенсивными вычислениями, тогда как Shiny Server (даже бесплатная версия) лучше, когда у вас больше подключений к простому в вычислительном отношении приложению.
С точки зрения определения требований к инфраструктуре, хорошим местом для начала было бы shinyloadtest .