2013-04-18 5 views
0

Есть аналогичные темы без конкретного решения, и я подумал, что лучше начать новый.Как расширить одного пользователя WebApp для нескольких пользователей

Я столкнулся с ситуацией, когда у меня есть WebApp, размещенный в RESIN (точно так же, как Tomcat, я думаю). До сих пор я разрабатывал приложение, используя db4o, так как я один, и мне нужно было завершить приложение ASAP, у меня есть БД для пользователей и еще одна БД для данных приложения для одного пользователя (меня), теперь, когда приложение почти Я собираюсь перейти к postgresql, и я серьезно отношусь к БД на пользователя, даже если БД хранит данные для нескольких приложений, так как будет обрабатывать любопытные конфиденциальные данные, и я думал, что отдельный БД будет лучшим (безопасным). Существует уже рудиментарное управление сеансом, в котором хранятся данные пользователя, такие как идентификатор в браузере. Но мне было интересно, как я могу расширить его до нескольких пользователей/db.

Я думал расширить класс слушателя, который сохраняет данные контекста, чтобы передать правильный объект db экземпляру приложения или, возможно, установить фильтр для этой цели.

.UPDATE.

Я хотел дать некоторое представление о том, что у меня есть.

у меня есть:

контекст, который содержит ссылки на некоторые объекты, один из этих объектов подключается к БД и проверяет пользователя и пароль.

Презентационный сервлет (HttpServlet), сопоставленный с «/», который имеет регистрационную форму, которая отправляется в/login.

Входной сервлет (HttpServlet), сопоставленный с именем «/ login», который проверяет атрибуты пароля пользователя httpSession на соответствующий объект, который находится в Контексте, если есть соответствие, задает атрибут httpSession, который содержит USERID, и перенаправляет пользователя на само приложение находится в /index-debug.html, если не создает новую страницу html с формой входа в систему.

Фильтры авторизации и проверки подлинности, сопоставленные с /index-debug.html, который проверяет HTTPServletRequest для атрибута USERID и проверяет, имеет ли пользователь разрешение на доступ к приложению.

Наконец, БД БД, который отвечает за чтение и запись в базу данных данных пользователя WebApp. Когда я выполняю определенный метод в webApp CP2JAVAWS, этот метод подходит к соответствующему методу в bean-компоненте, проблема в том, что этот компонент имеет статическую базу данных и пока он позволяет только одному пользователю в то время.

Что бы я хотел сделать, так это позволить этому БД БД создавать экземпляр один раз для каждого пользователя и читать и хранить соответствующие данные в зависимости от текущего зарегистрированного пользователя.

Идея одной БД на пользователя в настоящее время отбрасывается, но я не знаю, как именно это вытащить.

ответ

1

Вы упомянули Postgres как базу данных базы данных и функцию, называемую схемами. Это то, где у вас есть одна физическая база данных и несколько схем внутри базы данных. Мой опыт в этом связан с Rails, но концепции одинаковы. Этот метод позволяет избежать смятия данных людей в одном наборе таблиц, который звучит как ваша главная проблема. Я знаю, что вы используете Java, но watch this talk on Multi-tenant apps in Rails to get a background from Guy Naor о том, как это работает, компромиссы и т.д.

Вот некоторые конкретные шаги, чтобы вы начали по этому пути использования Postgres схемы:

  1. Там есть общедоступная схема в Postgres, которая по умолчанию.Это будет место, где вы помещаете свои таблицы аутентификации пользователя и любые другие общие таблицы метаданных о входах пользователей и т. Д. See Postgres docs for more info on how schemas work
  2. Придумайте соглашение об именах для каждой схемы, которую вы создадите (например, user_001, user_002 и т. Д.). , Предварительно распределите кучу пустых схем со всеми настройками таблиц и когда пользователь регистрируется или регистрируется в первый раз, вы назначаете им схему и сохраняете имя схемы в своей пользовательской записи в общедоступной схеме и в объекте пользователя, который у вас есть HttpSession. Не было бы необходимости запускать сценарии создания таблиц для первого пользователя - это было бы перетаскиванием производительности в веб-приложении. Вам просто нужно опережать темп новых пользователей. Например, вы можете иметь кучу пустых user_standby_1 ... user_standby_100 схемы, а затем, когда кто-то входит в систему или регистры, вы бы запустить этот SQL:

    myquery = "ALTER SCHEMA user_standby_? RENAME TO user_?"; myquery.setString(1,standby_id); myquery.setString(2,user_id);

  3. При создании БД боб (использовать суперкласс для этого, смотрите ниже), передать имя схемы из объекта пользователя из HttpSession, а затем выполнить этот SQL перед каждой операцией, чтобы изолировать их в схеме только:

    myquery2 = "SET search_path TO ?";
    myquery2.setString(1,user.search_path);

  4. Если у вас есть пустой полная схема публично, то вы хотите опустить публикацию из пути поиска, иначе у вас будет 2 таблицы с тем же именем в пути поиска. Если вы хотите, чтобы путь поиска пользователей включал SET search_path TO user_001,public, то после создания таблиц удалите все таблицы данных из общедоступных, кроме пользователей, и любую метаинформацию, в которой вы нуждаетесь.

  5. Для обслуживания напишите сценарий, который вы можете запустить через командную строку, чтобы удалить пустые схемы user_standby, создать новые схемы user_standby и выполнить эквивалент Rails Migrations for Java для незначительных изменений таблицы.
  6. Для больших операций обслуживания лучше всего создавать новые схемы, например. user_v2_001, для каждого пользователя, а затем писать сценарии для переноса своих данных. Это зависит от того, насколько сложны изменения в ваших таблицах.

Если вы идете альтернативный маршрут и иметь все пользователи данных в одном наборе таблиц, то лучший подход заключается в user_id в каждый стол и написать SQL, чтобы использовать эту каждый время. Если вы используете традиционную нормализацию и присоединяетесь, чтобы получить свой user_id, то вам лучше убедиться, что вы случайно не пропустите соединение, или пользователи начнут видеть данные друг друга.

Функция схемы Postgres позволяет блокировать доступ пользователей только к собственным данным. После выяснения основ используйте суперкласс в Java для написания шага 3 выше, поэтому каждый MyTableDBBean выходит из MasterDBBean и использует конструктор суперкласса для выделения пути поиска к схеме пользователя. Тогда у вас есть только 1 место в вашем коде, где это делается, и вам не нужно запоминать для каждой таблицы или запроса что-то большее, чем бизнес-логика.

+0

Большое спасибо, это в основном дополняет ответ, который сделал ryan1234. Спасибо вам обоим. – Jigzat

2

Смола! Я не слышал и не работал с Ресином довольно долго. =)

Я видел идею наличия одной базы данных для каждого пользователя системы, часто возникающей при переполнении стека. Реакция, как правило, одинакова - это не отличная идея.

Есть много причин, почему, но я просто придерживаюсь масштабов, ремонтопригодности и волатильности.

Масштаб

Некоторые базы данных имеют ограничения на сколько баз данных они могут иметь. Я не знаю, сколько баз данных может иметь один экземпляр Postgres.

Эта ссылка (https://dba.stackexchange.com/questions/23971/maximum-number-of-databases-for-single-instance-of-postgresql-9) говорит, что кто-то получил 10 000 баз данных на одном экземпляре.

Я бы сказал, что со временем это не редкость, чтобы получить миллион пользователей для сайта (конечно, не все активные). Другими словами, я бы поспорил, что ваш пользовательский счет в какой-то момент сломает Postgres с одной базой данных для каждого пользователя.

ремонтопригодность

Давайте предположим, что вы только когда-либо хотите 10,000 пользователей, и поэтому вы можете сделать 10000 баз данных. Что произойдет, если вы хотите обновить таблицу в каждой базе данных? Болезненно откатывать эти изменения.

Что обычно происходит, вы напишете скрипт, чтобы коснуться каждой базы данных, и хотя вы протестировали ее, на полпути через скрипт умирает, и теперь вы застряли на несколько отчаянных минут с половиной таблиц в одном состоянии и половина в другом государстве.

Или, что еще хуже, база данных выходит из синхронизации и имеет другую схему, чем остальные базы данных. Теперь у вас потенциально есть более одной живой версии базы данных «пользователь».

Волатильность

Пользователи непостоянны. Они подпишут сегодня, а затем никогда не вернутся. Они будут зарегистрироваться, а затем войти снова через два года. Они будут делать несколько учетных записей, потому что они забыли свой пароль.

Это быстро приведет к потерянным базам данных. Вы должны (или хотите) написать скрипт для периодической очистки.

Также некоторые более современные базы данных (такие как MongoDB и Couchbase) фактически предопределяют большие порции диска/памяти при создании базы данных. Я не верю, что Postgres делает это, но это то, что нужно учитывать.

безопасности

Если кто-то взламывает вашу Postgres коробку, отделяя пользователей от базы данных не собирается, чтобы помочь вам. Они могут перемещаться между базами данных так же легко, как перемещение между записями в таблице. Лучше всего просто заблокировать машину базы данных очень хорошо, а затем позволить пользователям жить вместе в одной таблице. Это проще в масштабировании, проще в обслуживании, и вы можете управлять волатильностью.

+0

Спасибо, да, тема базы данных для пользователя была затронута несколько раз в переполнении стека, и ваш ответ является первым, кто фактически убедит меня не делать этого таким образом, но все же, как я могу расширить мой webApp для нескольких пользователей? Мои знания об этом очень рудиментарны, и в моем случае WebApp (Cappuccino/Objective-J) не напрямую обращается к БД, в основном использует javascript remote JAVA-метод вызова через CP2JAVAWS, поэтому фактический QUERY происходит на сервере, где я использую объекты и отправить их как объекты JSON (конечно, это прозрачно для меня) – Jigzat