O tratamento de um número modesto de clientes (inquilinos) em um servidor comum com bancos de dados separados para a instância de cada inquilino do aplicativo é relativamente simples e normalmente é a maneira correta de fazer isso. Atualmente, estou analisando a arquitetura de um aplicativo em que cada inquilino tem sua própria instância de banco de dados.
No entanto, o problema é que esse aplicativo terá um grande número de inquilinos (5.000 a 10.000) com um número substancial de usuários, talvez 2.000 para um único inquilino. Precisamos apoiar o crescimento do sistema por vários inquilinos toda semana.
Além disso, todos os inquilinos e seus usuários receberão um processo de login comum (ou seja, cada inquilino não pode ter seu próprio URL). Para fazer isso, preciso de um processo de login centralizado e um meio de adicionar dinamicamente bancos de dados ao sistema e registrar usuários.
Como o processo de criação de registro e banco de dados pode ser automatizado de maneira robusta?
É o processo de criação e registro de bancos de dados de inquilinos no sistema que pode causar problemas de desempenho ou bloqueio. Se você acha que isso pode ser um problema, alguém pode sugerir maneiras de mitigá-lo?
Como gerenciar a autenticação central de uma maneira em que as credenciais do usuário serão associadas ao banco de dados de um inquilino específico, mas o usuário pode efetuar login através de uma página comum (ou seja, através do mesmo URL de login, mas seu aplicativo inicial estará no banco de dados de algum inquilino específico ) Os inquilinos deverão poder manter seus próprios logins e permissões, mas um sistema central de logon deve estar ciente disso. Alguém pode sugerir uma maneira de fazer isso?
Se eu precisar 'expandir' adicionando vários servidores de banco de dados, alguém pode sugerir quais problemas eu posso ter para lidar com o gerenciamento de identificações de usuários entre servidores (representação etc.) e alguma maneira de atenuar esses problemas?
fonte
Respostas:
Na extremidade inferior (500 inquilinos / 10000 usuários), foi assim que eu fiz. Primeiro, você tem um banco de dados de "controle" que é global, central e contém todas as informações sobre inquilinos e usuários (eu realmente não acho que você queira gerenciá-los como logins de autenticação SQL). Imagine um banco de dados chamado "Controle" com as seguintes tabelas:
No nosso caso, quando adicionamos um novo inquilino, construiríamos o banco de dados dinamicamente, mas não quando o usuário administrador clicou em OK na interface do usuário ... tivemos um trabalho em segundo plano que retirou novos bancos de dados de uma fila a cada 5 minutos, configurou o modelo para single_user e, em seguida, criou cada novo banco de dados em série. Fizemos isso para (a) impedir que o usuário administrador aguarde a criação do banco de dados e (b) evitar que dois usuários administradores tentem criar um banco de dados ao mesmo tempo ou que não sejam capazes de bloquear o modelo (necessário ao criar um novo banco de dados )
Os bancos de dados foram criados com o esquema de nomes
Tenant000000xx
ondexx
representadosTenants.TenantID
. Isso fez trabalhos de manutenção muito fácil, em vez de ter todos os tipos de bancos de dados nomeadosBurgerKing
,McDonalds
,KFC
etc. Não que estávamos em fast food, apenas usando isso como um exemplo.O motivo de não pré-alocarmos milhares de bancos de dados, conforme sugerido pelo comentário, é que nossos usuários administrativos geralmente tinham uma idéia de quão grande o inquilino se tornaria, se eram de alta prioridade etc. Então, eles tinham escolhas básicas na interface do usuário que ditariam suas configurações iniciais de tamanho e crescimento automático, para qual subsistema de disco seus arquivos de dados / log seriam, suas configurações de recuperação, agendamento de backup e até mesmo saber sobre qual instância implantar o banco de dados para equilibrar melhor o uso ( embora nossos administradores possam substituir isso). Depois que o banco de dados é criado, a tabela de inquilino foi atualizada com a instância escolhida, um usuário administrador foi criado para o inquilino e nossos administradores receberam por e-mail as credenciais para repassar ao novo inquilino.
Se você estiver usando um único ponto de entrada, não é possível permitir que vários inquilinos tenham usuários com o mesmo nome de usuário. Optamos por usar o endereço de email, que - se todos os usuários trabalharem para a empresa e usarem o endereço de email corporativo - deve estar bem. Embora nossa solução tenha se tornado mais complexa por dois motivos:
Então, acabamos com uma
TenantUsers
tabela que permite que um usuário seja associado a vários inquilinos.Inicialmente, quando um usuário faz login, o aplicativo conhece a cadeia de conexão apenas para o banco de dados de controle. Quando um login é bem-sucedido, ele pode criar uma cadeia de conexão com base nas informações encontradas. Por exemplo
Agora, o aplicativo poderia se conectar ao banco de dados do usuário (cada usuário tinha um inquilino padrão ) ou o usuário poderia selecionar um dos inquilinos que poderia acessar. O aplicativo simplesmente recupera a nova cadeia de conexão e redireciona para a página inicial desse inquilino.
Se você entrar nessa área de 10 milhões de usuários que propõe, você definitivamente precisará que isso seja melhor equilibrado. Você pode associar o aplicativo para que eles tenham pontos de entrada diferentes, conectando-se a diferentes bancos de dados de controle. Se você atribuir a cada inquilino um subdomínio (por exemplo, TenantName.YourApplicationDomain.com), poderá fazer isso nos bastidores com DNS / roteamento sem interrompê-los quando precisar expandir ainda mais.
Há muito mais nisso - como @Darin, estou apenas arranhando a superfície aqui. Entre em contato se precisar de uma consulta não gratuita. :-)
fonte
Você tem um projeto bastante interessante. Eu nunca vi diretamente alguém tentar implementar algo tão grande, pelo menos no SQL Server. Quanto mais eu leio sua postagem, mais perguntas surgem ...
No pior cenário, em termos de infraestrutura (que é o melhor cenário, em termos de negócios), você precisa de 10 mil bancos de dados vezes 2 mil usuários. São 20.000.000 de usuários. Você não terá êxito ao tentar gerenciar logons de 20 M do SQL Server. IMO. Apenas o número absoluto deles, lidando com a transferência de servidor para servidor, observando colisões de ID e IDs incompatíveis, além de não ter certeza de como o SQL Server se comportaria com linhas de 20 M em sys.server_principals. Além disso, seu aplicativo da web provavelmente desejará conectar-se como um número único ou muito baixo de usuários. O IIS não pode agrupar conexões, a menos que suas seqüências DSN sejam idênticas. Um dos atributos de uma sequência DSN é o nome do usuário. Usuários diferentes significa que não há pool.
Você precisará rolar seu próprio esquema de credenciais de usuário. Ele deve ser capaz de descobrir a que inquilino um usuário pertence e, em seguida, seu código da web precisará selecionar o banco de dados apropriado. Esses metadados do usuário são críticos, precisam ser armazenados em algum lugar, precisam ser agrupados ou espelhados, precisam ser rápidos e precisam ser bem protegidos (do ponto de vista da segurança. IOW, criptografá-lo.). Supondo que o SQL seja uma boa idéia aqui, eu manteria esse banco de dados longe das instâncias que o servidor inquilina. Isso ajuda do ponto de vista da segurança e do ponto de vista da carga, embora eu ache que, uma vez que os usuários sejam validados e o aplicativo Web seja direcionado para o banco de dados correto em outra instância, não haverá mais consultas sobre os metadados desse usuário relacionados a esse do utilizador.
Pergunta rápida: dois usuários diferentes, pertencentes a dois inquilinos diferentes, devem ter o mesmo nome de usuário?
Outra pergunta rápida: se eu lhe disser que trabalho na FuBar, Inc., como você sabe disso? O FuBar fornecerá uma lista de usuários e você fornecerá uma lista de nomes de usuários ou eles serão auto-fornecidos?
Você precisará executar várias instâncias. Se mesmo uma fração desses usuários decidir acessar o aplicativo de uma vez, uma única instância derreterá. Não haverá threads de trabalho suficientes para executar todas essas solicitações de uma só vez. Se apenas 1.000 usuários atingirem sua instância ao mesmo tempo, provavelmente ela ficará sem threads de trabalho e a solicitação começará a se acumular e aguardar. Eu já vi isso acontecer; o sintoma mais próximo é que novas conexões não poderão efetuar logon na instância porque não há threads de trabalho disponíveis para atendê-las. Se esse comportamento for de curta duração, seu aplicativo poderá sobreviver. Caso contrário, ou seu aplicativo é exigente, os usuários receberão erros.
Mesmo que você não tenha muitos inquilinos para iniciar, comece a pensar no futuro e na automação, porque quando perceber que o servidor está atolado e houver 10 novos inquilinos para colocar online, é muito tarde e seu serviço (e seus clientes e seus futuros ex-clientes) sofrerão até que você resolva o problema.
Você precisará de uma maneira de mover bancos de dados, de servidores sobrecarregados para servidores pouco carregados (ou novos). A obtenção ou não de uma janela de tempo de inatividade dependerá do seu SLA.
Você está fornecendo um aplicativo específico, como SalesForce, ou esses bancos de dados são apenas contêineres para o que seus inquilinos desejam incluir?
Qual o tamanho dos bancos de dados? Se eles não forem muito grandes, você poderá restaurar a partir de um arquivo de backup que fornece um modelo. (Isso não é muito diferente do que o banco de dados do modelo faz, mas não vejo ninguém realmente usar o modelo desde os meus dias com o SQL 6.5.) Depois que o modelo for restaurado para o novo nome do banco de dados, você poderá em seguida, personalize o novo banco de dados conforme necessário para um inquilino específico. Você não pode fazer a personalização antes de ter o inquilino, obviamente. Se o banco de dados for grande, você poderá seguir o mesmo procedimento básico, exceto a restauração antecipada, antes que qualquer novo inquilino precise do espaço. Você pode manter alguns desses bancos de dados por perto, talvez um por instância. Se você mantiver muitos por perto, isso forçará você a comprar mais hardware e / ou armazenamento do que o necessário,
Se esse for seu próprio aplicativo, como você lida com as atualizações dos esquemas? Como você manterá as versões do banco de dados alinhadas com as versões do código, se você estiver usando um único URL que acessa seu aplicativo Web?
Como você detecta e destrói bancos de dados que não estão mais em uso? Você espera até o seu grupo de contas a receber dizer que alguém não paga a conta há três meses?
Se os inquilinos estão gerenciando permissões, isso significa que eles têm alguma compreensão do funcionamento interno do aplicativo ou que seu aplicativo tem uma estrutura de funções muito simples. Usando algo como o Blogger como exemplo, os usuários podem (ler postagens), (ler postagens e fazer comentários), (... e criar postagens), (... e editar postagens de outras pessoas), (... e podem redefinir senhas de outros usuários) ou (... e o que for). Ter uma função para cada um desses diferentes conjuntos de direitos e atribuir um usuário a uma função ou outra não deve ser muito difícil, mas você não deseja que seu aplicativo execute instruções 'GRANT'. Cuidado com as funções que têm uma hierarquia e dependem da herança, pois pode ficar confuso. Se você estiver promovendo ou rebaixando um usuário, sugiro retirá-lo de todas as funções associadas e adicioná-lo novamente à única função necessária. Oh,
Eu acho que apenas arranhei a superfície aqui, e este post já é muito longo. O que você realmente precisa é de um livro, ou pelo menos de um whitepaper de alguém que fez isso. A maioria desses caras não fala, se eles vêem isso como uma vantagem competitiva.
fonte