Adoro modificar o código do SQL Server para melhorar o desempenho, mas ocasionalmente há cenários em que, mesmo depois de ajustar o código, indexar e projetar, uma tarefa do usuário do aplicativo leva mais tempo para ser concluída do que a experiência do usuário final esperada. Quando isso acontece, a interface do usuário precisa aguardar a conclusão do processo ou temos que criar uma maneira alternativa de lidar com a tarefa. O processamento assíncrono fornecido pelo Service Broker é adequado para muitos desses cenários e permite que o processamento em segundo plano da tarefa de longa execução seja executado separadamente da interface do usuário, permitindo que o usuário continue trabalhando imediatamente sem esperar que a tarefa seja realmente executada . Nos próximos artigos, espero criar uma série sobre como você pode aproveitar o Service Broker com as explicações apropriadas e exemplos de código ao longo do caminho para facilitar o aproveitamento dos recursos do Service Broker sem problemas de implementação.
Métodos de execução de processamento assíncrono
Existem várias maneiras de lidar com um processo de longa duração, mas já ajustado. O código do aplicativo também pode ser reescrito para usar um BackgroundWorker, o ThreadPool em segundo plano ou uma solução baseada em Thread escrita manualmente no .NET que executa a operação de forma assíncrona. No entanto, isso permite que um número ilimitado desses processos de longa execução sejam enviados pelo aplicativo, a menos que seja feito trabalho de codificação adicional para rastrear e limitar o número de processos ativos. Isso significa que o aplicativo terá um impacto potencial no desempenho ou, sob carga, atingirá um limite e retornará à espera anterior que estávamos tentando impedir originalmente.
Também vi esses tipos de processos transformados em trabalhos do SQL Agent vinculados a uma tabela que é usada para armazenar as informações a serem processadas. Em seguida, o trabalho é agendado para ser executado periodicamente ou é iniciado pelo aplicativo usando
sp_start_job
quando uma alteração é armazenada para processamento. No entanto, isso só permite a execução serial dos processos de execução longa, pois o SQL Agent não permite que um trabalho seja executado várias vezes simultaneamente. O trabalho também teria que ser projetado para lidar com cenários em que várias linhas entram na tabela de processamento para que a ordem correta de processamento ocorra e os envios subsequentes sejam processados separadamente. Aproveitar o Service Broker para processamento assíncrono no SQL Server realmente aborda as limitações com os métodos mencionados anteriormente para lidar com o processamento assíncrono. A implementação do broker permite que novas tarefas sejam enfileiradas para processamento assíncrono em segundo plano e também permite o processamento paralelo das tarefas que foram enfileiradas até um limite configurado. No entanto, diferentemente da camada do aplicativo ter que esperar quando o limite é atingido, a solução do broker simplesmente enfileira a nova mensagem que está sendo recebida e permite que ela seja processada quando uma das tarefas de processamento atuais for concluída - isso permite que o aplicativo continue sem esperar.
Configuração do agente de serviço de banco de dados único
Embora as configurações do Service Broker possam se tornar complexas, para o processamento assíncrono simples, você só precisa conhecer os conceitos básicos para criar uma configuração de banco de dados único. Uma única configuração de banco de dados requer apenas:
- Criando dois tipos de mensagem
- Um para solicitar o processamento assíncrono
- Um para a mensagem de retorno quando o processamento for concluído
- Um contrato usando os tipos de mensagem
- Define qual tipo de mensagem é enviado pelo serviço iniciador e qual tipo de mensagem é retornado pelo serviço de destino
- Um procedimento de fila, serviço e ativação para o destino
- A fila fornece o armazenamento de mensagens enviadas ao serviço de destino pelo serviço iniciador
- O procedimento de ativação automatiza o processamento de mensagens da fila
- Retorna uma mensagem concluída ao serviço iniciador quando ele conclui o processamento de uma tarefa solicitada
- Lida com os tipos de mensagem do sistema http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog e http://schemas.microsoft.com/SQL/ServiceBroker/Error
- Um procedimento de fila, serviço e ativação para o iniciador
- A fila fornece o armazenamento das mensagens enviadas ao serviço
- O procedimento de ativação é opcional, mas automatiza o processamento das mensagens da fila
- Processa a mensagem concluída para o serviço de destino e encerra a conversa
- Lida com os tipos de mensagem do sistema http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog e http://schemas.microsoft.com/SQL/ServiceBroker/Error
Além desses componentes básicos, prefiro usar um procedimento armazenado de wrapper para criar uma conversa e enviar mensagens entre os serviços do broker para manter o código limpo e facilitar o dimensionamento conforme necessário, implementando a reutilização de conversas ou o truque de 150 conversas explicado em o whitepaper da equipe SQLCAT. Para muitas das configurações de processamento assíncrono simples, essas técnicas de ajuste de desempenho podem não precisar ser implementadas. No entanto, usando um procedimento armazenado de wrapper, fica muito mais fácil alterar um único ponto no código, em vez de alterar todos os procedimentos que enviam uma mensagem no futuro, caso seja necessário.
Se você não deu uma olhada no Service Broker, ele pode fornecer um método alternativo de realizar o processamento desacoplado de forma assíncrona para resolver vários cenários possíveis. Na minha próxima postagem, examinaremos o código-fonte para um exemplo de implementação e explicaremos onde as alterações específicas precisariam ser feitas para aproveitar o código para processamento assíncrono.