TL;DR: Ao se conectar ao meu contêiner SQL Server Docker por meio de um nome que resolve para o loopback IPv6 ( ::1
), as chamadas SMO são muito lentas. Ao usar 127.0.0.1
, eles são rápidos.
Estou tentando aprender a usar a imagem do Docker microsoft/mssql-server-windows-developer . De acordo com a documentação da Microsoft, esse contêiner expõe apenas a porta 1433 TCP.
docker run -d -p 1433:1433 -e sa_password=Passw0rd! -e ACCEPT_EULA=Y -v C:\dockerdb:C:\dockerdb microsoft/mssql-server-windows-developer
Estou executando o contêiner no Windows 10 e consegui iniciá-lo com êxito, autenticando com autenticação do SQL Server e executando consultas na instância usando sqlcmd e SSMS 17.4 no host do Windows (conectando-se ao localhost ou “.”) e SQL Operations Studio em um mac ao lado conectando por IP. Não vejo problemas de desempenho perceptíveis ao executar consultas dessa maneira.
No SSMS, também posso navegar no explorador de objetos, mas se eu tentar fazer algo no menu do botão direito em um objeto no explorador de objetos, como abrir a janela de parâmetros de instância ou anexar um banco de dados, o SSMS não mostra uma resposta por cerca de 5 -10 minutos, momento em que exibe a janela que solicitei ou exibe esta mensagem de erro:
Também estou tentando fazer alguns scripts do PowerShell nessa instância usando o objeto SMO Scripter e vejo o mesmo tipo de comportamento. O script PS faz um loop pelos objetos no banco de dados e os scripts para arquivo e, embora trabalhe para reunir a lista de objetos de forma relativamente rápida, cada objeto individual leva de 5 a 10 minutos para o script - muito lento para ser usado.
Eu tenho um palpite de que a única porta exposta não é suficiente e que o SMO e o SSMS estão tentando se conectar de uma maneira semelhante que os está desacelerando. Também pode ser que, ao se conectar ao localhost, essas ferramentas suponham que haja outros canais de comunicação presentes que normalmente não seriam protegidos por firewall? Existem parâmetros de conexão adicionais que eu poderia estar usando? Alguém pode validar minha suposição de que o SSMS está usando o SMO ou outra coisa para falar com o SQL Server?
ATUALIZAÇÃO: ainda estou investigando, mas é plausível que este seja um problema do Docker em torno de restrições de recursos. Isso é confuso porque a maior parte da documentação parece indicar que os contêineres do Windows não têm restrições de recursos padrão (e não podem ser definidas na GUI do Docker para Windows — apenas para contêineres do Linux ), mas parece que, na realidade, o Windows contêineres em execução no Windows 10 obtêm uma alocação de RAM padrão de 1 GB. Ainda estou tentando descobrir como inspecionar um contêiner em execução para ver sua alocação de RAM e CPU, mas em seguida tenho que tentar aumentá-los de quaisquer que sejam os padrões, usando docker run
parâmetros.
ATUALIZAÇÃO ADICIONAL: Não estou conseguindo obter nenhum tipo de métrica confiável do docker que me diga quais limites de CPU e memória ele possui para o contêiner. Pesquisas variadas indicam que os contêineres do docker não têm um limite de memória por padrão, ou têm e são 1 GB, mas tudo o que posso verificar no momento é que docker stats
o contêiner SQL está usando apenas entre 750 e 850 meg, e quando Eu tento adicionar um parâmetro de execução para definir a memória disponível para 4 gb, dá erro. Então parei de seguir esse segmento de consulta e fui para uma verificação de intestino diferente: entrar em uma sessão interativa do powershell no contêiner em execução e, em seguida, invocar meu script do powershell vinculado acima de dentro do contêiner.
Rodando dentro do container não houve problema. Ele atravessou 2780 objetos em apenas alguns minutos. Acho que isso confirma que o problema está no limite do contêiner/host, então vou ver se consigo abrir essa porta UDP. ATUALIZAÇÃO: Abrir a porta 1434 UDP não ajudou.
MAIS ATUALIZAÇÕES - Solução alternativa alcançada, não é um problema de restrição de recursos: parece haver problemas relacionados à configuração de grandes alocações de memória para contêineres do Windows - eu estava recebendo erros semelhantes para 3g e 2g, mas finalmente consegui iniciar o contêiner com 1,5g e Eu vi uma diferença no docker stats
contêiner que (eu acho) confirma que estava sendo executado com uma alocação padrão de 1 GB. Nas configurações padrão, a estatística PRIV WORKING SET (para a qual não consigo encontrar nenhuma documentação, mas meu melhor palpite é que é RAM) está entre 700MiB e 850MiB. Comdocker run —memory="1.5g"
definido, é em torno de 1.0GiB. Então, ele se expandiu, mas parece estar deixando mais alocação livre do que antes. Eu interpreto isso (talvez incorretamente) como significando que este servidor (que está executando absolutamente NENHUMA carga e NÃO possui bancos de dados de usuários) não está sob pressão de memória. Verifiquei a configuração de memória máxima do servidor para confirmar que ela está definida no máximo padrão de 2PiB.
Então as coisas ficaram estranhas. Ainda estou testando as coisas executando meu script powershell de vários locais. Rápido dentro do container, lento no host. Então eu fiz RDP para outra máquina Windows na rede e executei o script dessa máquina, conectando-me ao meu host Windows 10 por IP. E foi RÁPIDO! Isso parece apoiar a teoria de que, ao se conectar a algo que deveria ser localhost, o SMO está tentando se conectar ao SQL Server usando algo diferente da porta 1433 TCP, que aguarda um tempo limite muito longo antes de retornar à conexão TCP.
Decidi tentar validar essa teoria inserindo uma entrada de arquivo hosts para se referir a localhost por um nome diferente de localhost:
127.0.0.1 dockersucks
Eu me conectei no SSMS a dockersucks em vez de localhost ou ".", e imediatamente as coisas ficaram mais rápidas. A navegação no explorador de objetos foi como de costume, e a abertura de painéis como anexar banco de dados ou propriedades do servidor aconteceu tão rapidamente quanto o normal. E, quando executei meu script powershell do host do Windows 10 usando esse alias como nome do servidor, também foi rápido.
Adicionei essa atualização à pergunta em vez de uma resposta, pois ainda estou procurando uma explicação de por que isso está ocorrendo e se há uma maneira de corrigi-la para conexões com "localhost" com esse nome.