2013-04-18 1 views
0

구체적인 해결책이없는 유사한 스레드가 있으며 새 솔루션을 시작하는 것이 더 좋습니다.단일 사용자 웹 응용 프로그램을 여러 사용자로 확장하는 방법

웹 애플리케이션이 RESIN에서 호스팅되는 상황에 직면하고 있습니다 (Tomcat과 비슷합니다). 지금까지 저는 db4o를 사용하여 앱을 개발했습니다. 저는 혼자 였기 때문에 가능한 빨리 앱을 완성해야했습니다. 사용자를위한 DB와 단일 사용자 (나)를위한 앱 데이터를위한 DB가 있습니다. 이제 앱이 거의 완료되었습니다. done 나는 postgresql로 옮길려고하고 있는데, 비록 기밀 데이터를 다루기 때문에 DB가 여러개의 응용 프로그램에 대한 데이터를 보유하고 있어도 사용자 당 DB에 대해 심각하게 생각하고 있습니다. 분리 된 DB를 사용하는 것이 최선일 것입니다 (보안 현명). 브라우저에 ID와 같은 사용자 데이터를 저장하는 기본 세션 관리가 이미 있습니다. 하지만 어떻게 여러 사용자/db 확장 할 수 있습니다 궁금 해서요.

문맥 데이터를 유지하는 리스너 클래스를 확장하여 올바른 db 객체를 앱 인스턴스에 전달하거나 그 목적을 위해 필터를 설정할 수도 있습니다.

. UPDATE.

저는 현재 갖고있는 것에 대해 좀 더 자세히 설명하고자합니다.

제가있다 : 일부 개체에 대한 참조를 보유

콘텍스트 이들 개체 중 하나가 사용자 DB와 패스워드를 검사에 연결된다.

/login에 POST 할 로그인 양식이있는 "/"에 매핑 된 프리젠 테이션 서블릿 (HttpServlet).

"/ login"에 매핑 된 로그인 서블릿 (HttpServlet)은 컨텍스트에있는 각각의 객체에 대해 httpSession 사용자 비밀번호 속성을 검사합니다. 일치하는 경우 USERID를 보유하는 httpSession 속성을 설정하고 사용자를 /index-debug.html에있는 앱 자체는 로그인 폼이있는 새 html 페이지를 다시 만듭니다.

/index-debug.html에 매핑 된 인증 및 인증 필터는 USERID 속성에 대한 httpServletRequest를 확인하고 사용자가 앱에 액세스 할 권한이 있는지 여부를 확인합니다.

마지막으로 webApp 사용자 데이터 DB에 대한 읽기 및 쓰기를 담당하는 DB bean입니다. 웹 애플리케이션 CP2JAVAWS에서 특정 메소드를 실행하면 해당 메소드가 빈의 해당 메소드와 일치합니다. 문제는이 빈에 정적 데이터베이스가 있으며 지금까지는 한 명의 사용자 만 허용한다는 것입니다.

나는이 DB 빈이 사용자 당 한 번 인스턴스화하고 현재 로깅 된 사용자에 따라 해당 데이터를 읽고 저장할 수 있도록하고 싶습니다.

사용자 당 하나의 DB에 대한 아이디어는 현재 폐기되었지만 정확히 어떻게 제거했는지는 알 수 없습니다.

답변

1

Postgres를 데이터베이스 백엔드로 언급했는데 스키마라는 기능이 있습니다. 이것은 하나의 실제 데이터베이스와 여러 스키마가 데이터베이스 내에있는 곳입니다. 이것에 대한 나의 경험은 Rails에서 비롯되었지만 개념은 같습니다. 이 방법은 사람들의 주요 관심사처럼 들리는 동일한 테이블 세트에서 사람들의 데이터를 함께 모으는 것을 피합니다.

  1. 가있다 : 나는 여기

    당신이 포스트 그레스 스키마를 사용하여이 길을 시작하는 몇 가지 구체적인 단계는 등, 당신이 자바를 사용하고 알고 있지만,이 트레이드 오프의 작동 방식에 watch this talk on Multi-tenant apps in Rails to get a background from Guy Naor 기본값 인 Postgres의 공용 스키마.사용자 로그인 테이블 및 기타 일반 메타 데이터 테이블을 사용자 로그인 등에 사용하는 위치입니다. See Postgres docs for more info on how schemas work

  2. 만들 스키마마다 이름 지정 규칙이 있습니다 (예 : user_001, user_002 등). . 모든 테이블 설정이 포함 된 빈 스키마를 미리 할당하고 사용자가 처음 등록하거나 로그인 할 때 스키마를 할당하고 공용 스키마의 사용자 레코드에 스키마 이름을 저장하고 사용자 개체에 해당 스키마를 저장합니다. 당신은 HttpSession에 있습니다. 처음 사용자를 위해 테이블 ​​생성 스크립트를 실행할 필요가 없습니다. 이것은 웹 앱의 성능 드래그가 될 것입니다. 새로운 사용자의 비율보다 앞서 있어야합니다. 당신이 당신의 DB 콩을 만들 때

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

  3. 이 (슈퍼 클래스를 사용 : 예를 들어, 당신은 빈 user_standby_1의 무리 ... user_standby_100 스키마 누군가가 또는 레지스터 로그인 할 때 다음이 SQL을 실행하는 것을 가질 수 이를 위해,) 아래 참조의 HttpSession에서 사용자 개체에서 스키마 이름을 전달하고 그들의 스키마로 분리하는 모든 작업 전에이 SQL을 실행

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

  4. 당신은 비어있는 경우 전체 스키마 공개, 검색 경로에서 public을 생략하려면 검색 경로에 같은 이름의 테이블이 2 개 있어야합니다. 사용자 검색 경로에 SET search_path TO user_001,public을 포함 시키려면 표를 만든 후에 사용자 및 필요한 메타 정보 외에 공개 된 모든 데이터 표를 삭제하십시오.

  5. 유지 관리를 위해 명령 줄을 통해 실행할 수있는 스크립트를 작성하여 빈 user_standby 스키마를 삭제하고 새 user_standby 스키마를 작성한 후 보조 테이블 변경 사항에 대해 Migrations for Java과 동일하게 수행하십시오.
  6. 대규모 유지 관리 활동의 경우 새 스키마를 만드는 것이 가장 좋습니다. user_v2_001을 작성한 다음 각 사용자에 대한 스크립트를 작성하여 데이터를 마이그레이션하십시오. 변경 사항은 테이블에 얼마나 복잡한가에 따라 다릅니다. 당신이 다른 경로를 이동 및 테이블의 한 세트에서 모든 사용자 데이터가있는 경우

후 가장 좋은 방법은 모든 테이블의 USER_ID 그 모든 시간을 사용하도록 SQL을 작성하는 것입니다. 전통적인 정규화를 사용하고 join을 수행하여 user_id를 얻는다면 실수로 조인을 놓치지 않도록하거나 사용자가 서로의 데이터를보기 시작할 것입니다.

Postgres 스키마 기능을 사용하면 사용자 액세스를 자신의 데이터에만 고정 할 수 있습니다. 기본 사항을 파악한 후 Java의 수퍼 클래스를 사용하여 위의 3 단계를 작성하면 모든 MyTableDBBean이 MasterDBBean에서 확장되고 수퍼 클래스 생성자를 사용하여 검색 경로를 사용자의 스키마로 분리합니다. 그렇다면 코드에서이 작업이 수행되는 곳은 1 곳 밖에 없으므로 모든 테이블이나 쿼리가 비즈니스 로직 이상을 수행 할 수 있다는 것을 기억할 필요가 없습니다.

+0

대단히 고마워, ryan1234가 만든 대답을 기본적으로 보완한다. 둘 다 고마워. – Jigzat

2

수지! 나는 꽤 오래 동안 Resin에 대해 들어 본 적이 없었습니다. =)

시스템의 사용자 당 하나의 데이터베이스가 스택 오버플로에서 자주 발생한다는 아이디어를 보았습니다. 반응은 일반적으로 동일합니다. 좋은 생각은 아닙니다.

이유가 많이 있지만 스케일, 유지 관리 및 변동성에 만 충실합니다.

규모

일부 데이터베이스는이 가질 수있는 얼마나 많은 데이터베이스에 제한이 있습니다. 나는 하나의 Postgres 인스턴스가 가질 수있는 데이터베이스의 수를 모른다.

이 링크 (https://dba.stackexchange.com/questions/23971/maximum-number-of-databases-for-single-instance-of-postgresql-9)는 한 인스턴스에 10,000 개의 데이터베이스가 있다고합니다.

시간이 지남에 따라 사이트에 대해 1 백만 명의 사용자를 확보하는 것은 드문 일이 아닙니다. 물론 모든 사이트가 활성화되는 것은 아닙니다. 즉, 사용자 당 하나의 데이터베이스를 사용하여 사용자 수에 따라 Postgres가 깨질 수 있습니다.

유지 보수성

하는의는 지금까지 10,000 명의 사용자를 원하는 당신을 가정하고 그래서 당신은 10,000 데이터베이스를 만들 수 있습니다 보자. 각 데이터베이스의 테이블을 업데이트하려면 어떻게됩니까? 이러한 변경 사항을 롤아웃하는 것은 고통 스럽습니다.

일반적으로 각 데이터베이스를 터치하는 스크립트를 작성하고 스크립트를 테스트 했는데도 스크립트가 종료되어 이제 한 상태에서 절반의 테이블로 필사적으로 빠져 있습니다. 다른 일부 주에서는 절반.

더 나쁜 것은 어떻게 든 데이터베이스가 동기화되지 않고 나머지 데이터베이스와 다른 스키마를가집니다. 이제 잠재적으로 "사용자"데이터베이스의 라이브 버전이 두 개 이상 있습니다.

변동성

사용자가 변덕이다. 그들은 오늘 가입하고 다시 오지 않을 것입니다. 2 년 후에 다시 가입하고 로그인합니다. 비밀번호를 잊어 버렸기 때문에 여러 계정을 만듭니다.

이렇게하면 고아 데이터베이스가 빨리 생성됩니다. 주기적으로 정리할 스크립트를 작성해야합니다 (또는 작성하려고합니다).

또한 MongoDB 및 Couchbase와 같은 최신 데이터베이스는 실제로 데이터베이스를 만들 때 디스크/메모리의 많은 부분을 미리 할당합니다. 나는 Postgres가 이것을한다고 생각하지 않지만, 고려해야 할 사항이다. 데이터베이스에서 사용자를 분리

보안

누군가가 당신의 포스트 그레스 상자를 해킹하는 경우

, 당신 도움이 될 수 없습니다. 테이블간에 레코드를 이동하는 것만 큼 쉽게 잠재적으로 데이터베이스간에 이동할 수 있습니다. 데이터베이스 시스템을 정말로 잘 잠그고 사용자가 한 테이블에 함께 살도록하는 것이 좋습니다. 확장이 쉽고 유지 보수가 쉽고 변동성을 관리 할 수 ​​있습니다.

+0

감사합니다. 예, 사용자 당 데이터베이스 주제가 스택 오버플로로 여러 번 감동되었으며 실제로 그 방법으로 그렇게하지 않겠다고 설득하는 첫 번째 답변이 있지만 여전히 어떻게 확장 할 수 있습니까? 내 웹 응용 프로그램을 여러 사용자에게 제공 하시겠습니까? 이것에 대한 나의 지식은 매우 초보적이며 웹 애플리케이션 (Cappuccino/Objective-J)은 DB를 직접 쿼리하지 않고 CP2JAVAWS를 통해 자바 스크립트 원격 JAVA 메소드 호출을 사용하므로 실제로 QUERY가 서버에서 발생한다. 객체들을 JSON 객체로 보내라. (물론 이것은 내게 투명하다.) – Jigzat

관련 문제