하단 (500 테넌트 / 10000 사용자)에서 이것이 내가 한 방법입니다. 먼저, 전체적으로 중앙에 있고 테넌트 및 사용자에 대한 모든 정보를 포함하는 "제어"데이터베이스가 있습니다 (실제로 SQL 인증 로그인으로 관리하고 싶지는 않습니다). 다음 테이블이있는 "Control"이라는 데이터베이스를 상상해보십시오.
CREATE TABLE dbo.Instances
(
InstanceID INT PRIMARY KEY,
Connection VARCHAR(255)
--, ...
);
INSERT dbo.Instances SELECT 1, 'PROD1\Instance1';
INSERT dbo.Instances SELECT 1, 'PROD2\Instance1';
-- ...
CREATE TABLE dbo.Tenants
(
TenantID INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL UNIQUE,
InstanceID INT -- Foreign key tells which instance this tenant's DB is on
--, ...
);
INSERT dbo.Tenants SELECT 1, 'MyTenant', 1;
-- ...
CREATE TABLE dbo.Users
(
UserID INT PRIMARY KEY,
Username VARCHAR(320) NOT NULL UNIQUE,
PasswordHash VARBINARY(64), -- because you never store plain text, right?
TenantID INT -- foreign key
--, ...
);
INSERT dbo.Users SELECT 1, 'foo@bar.com', 0x43..., 1;
새 테넌트를 추가 한 경우 관리자가 UI에서 확인을 클릭 할 때가 아니라 데이터베이스를 동적으로 빌드하지만 5 분마다 큐에서 새 데이터베이스를 가져 오는 백그라운드 작업이 있었고 모델을 single_user로 설정했습니다. 그런 다음 각 새 데이터베이스를 순차적으로 작성했습니다. (a) 관리자 사용자가 데이터베이스 생성을 기다리는 것을 방지하고 (b) 두 관리자 사용자가 동시에 데이터베이스를 만들려고하거나 모델을 잠그는 기능을 거부하는 것을 피하기 위해 (새 데이터베이스를 만들 때 필요함) ).
데이터베이스는 이름 구성표 Tenant000000xx
로 xx
표현되었습니다 Tenants.TenantID
. 이로 인해 이름 BurgerKing
이 McDonalds
, KFC
등인 모든 종류의 데이터베이스를 보유하는 대신 유지 보수 작업이 매우 쉬워졌습니다 . 우리는 패스트 푸드가 아니라 단지 예로 사용했습니다.
우리가 의견에서 제안한 것처럼 수천 개의 데이터베이스를 사전 할당하지 않은 이유는 관리자 사용자가 일반적으로 테넌트가 얼마나 커질 지, 우선 순위가 높은지 등을 알기 때문입니다. 따라서 UI에서 기본 선택 항목이있었습니다. 초기 크기 및 자동 증가 설정, 데이터 / 로그 파일이 전송되는 디스크 하위 시스템, 복구 설정, 연결을 끊을 백업 일정 및 사용 균형을 맞추기 위해 데이터베이스를 배포 할 인스턴스에 대한 스마트도 결정합니다 ( 우리의 관리자는 이것을 무시할 수 있습니다). 데이터베이스가 생성되면 테넌트 테이블이 선택한 인스턴스로 업데이트되고 테넌트에 대한 관리자가 생성되었으며 관리자가 자격 증명을 전자 메일로 보내 새로운 테넌트에게 전달했습니다.
단일 진입 점을 사용하는 경우 여러 테넌트가 동일한 사용자 이름을 가진 사용자를 가질 수 없습니다. 모든 사용자가 회사에서 일하고 회사 전자 메일 주소를 사용하는 경우 전자 메일 주소를 사용하는 것이 좋습니다. 우리의 솔루션은 결국 두 가지 이유로 더 복잡해졌습니다.
- 둘 이상의 고객을 위해 일하는 컨설턴트가 있었으며 여러 사람에게 액세스해야했습니다.
- 실제로 여러 명의 세입자로 구성된 세입자가있었습니다.
그래서 TenantUsers
한 명의 사용자가 여러 테넌트와 연결될 수 있는 테이블이 생겼습니다.
처음에 사용자가 로그인하면 앱은 제어 데이터베이스의 연결 문자열 만 알게됩니다. 로그인이 성공하면 찾은 정보를 기반으로 연결 문자열을 작성할 수 있습니다. 예 :
SELECT i.Connection
FROM dbo.Instances AS i
INNER JOIN dbo.Tenants AS t
ON i.InstanceID = t.InstanceID
INNER JOIN dbo.TenantUsers AS u
ON i.TenantID = u.TenantID
WHERE u.UserID = @UserID;
이제 앱이 사용자의 데이터베이스 (각 사용자가 기본 테넌트를 가짐)에 연결하거나 사용자가 액세스 할 수있는 테넌트 중에서 선택할 수 있습니다. 그런 다음 앱은 단순히 새 연결 문자열을 검색하고 해당 테넌트의 홈 페이지로 리디렉션합니다.
제안한이 10MM 사용자 영역에 들어가면 균형을 잘 잡기 위해 반드시 필요합니다. 서로 다른 제어 데이터베이스에 연결하는 다른 진입 점을 갖도록 응용 프로그램을 연합 할 수 있습니다. 각 테넌트에 서브 도메인 (예 : TenantName.YourApplicationDomain.com)을 제공하는 경우 추가 스케일 아웃이 필요할 때이를 방해하지 않고 DNS / 라우팅을 사용하여 씬 뒤에서이를 수행 할 수 있습니다.
@Darin과 같이 여기에는 더 많은 것이 있습니다. 여기서 표면을 긁적입니다. 무료 상담이 필요한 경우 알려주십시오. :-)