O poço de uma estrutura para integrar a configuração do druida

------ Registre uma jornada amarga de localização de bug no nível do sistema

 

    Horário: 27 de março de 2021. Ainda é muito novo Este artigo comemora a amargura de todo o processo de investigação e também fornece algumas referências para "macacos" que tiveram problemas semelhantes.

 

Projeto: Um projeto 2B + 2C (incluindo terminal móvel e terminal de PC)

 

Fenômeno: Cenários de alta simultaneidade (todos relacionados à epidemia: o primeiro dia em que o passe eletrônico está online, o primeiro dia em que o registro da vacina está online), o sistema trava e o PV chega a quase 80 em 2-3 horas no primeiro dia de registro e registro da vacina Dez mil, QPS não foi calculado e calculado e, teoricamente, não será muito alto.

 

Análise de causa superficial: nginx tem uma solicitação para entrar, mas a solicitação de conexão do serviço de interface em segundo plano atingiu o tempo limite. Por meio do monitoramento de log, foi descoberto que o serviço de interface em segundo plano solicitou o recebimento de logs, mas nenhuma saída de resposta. O julgamento preliminar está preso na execução de parte da lógica de negócios. Como resultado, todas as solicitações subsequentes estão no estado wating. Como o serviço de interface sempre pode receber novas solicitações, essa situação anormal não é reconhecida no mecanismo de sondagem de carga do nginx, resultando em falha de carga, o nginx tem distribuído continuamente novas solicitações para o serviço de interface anormal.

 

Amargura: Duas tarefas políticas consecutivas, o sistema não conseguiu suportar a pressão simultânea não é muito, porque a razão específica não foi localizada, não houve conclusões precisas e soluções correspondentes, o modelo de vacina é registrado online Eu também realizei um teste de estresse antes, e a conclusão é que ele pode suportar a simultaneidade de 2000 (talvez o método do teste de estresse esteja errado, parece que apenas interfaces individuais são pressionadas separadamente), o que faz as pessoas subestimarem psicologicamente o inimigo e pensarem que o anterior e -passar O problema do acidente está prestes a se tornar história, mas eu nunca esperei que o primeiro dia de registro de vacinas entraria em colapso nas primeiras duas ou três horas. Sob a premissa de que uma equipe de pessoas e outras pessoas trabalharam juntas para investigar e localizar o problema e não encontrou resultados, só podia ser visualizado de lado. O sistema foi otimizado em vários aspectos, como aumento de nós de carga, redução do número de chamadas de interface, aumento do uso de caches, otimização de scripts de estatísticas de consulta, etc. ., até certo ponto, para aliviar a pressão no lado do servidor o máximo possível. Depois de uma noite de trabalho árduo, depois de estar online novamente no dia seguinte, resisti temporariamente à pressão e não mais travamentos, mas a simultaneidade no O segundo dia obviamente não foi tão alto quanto o primeiro. Além disso, o problema não foi resolvido a partir da causa raiz (sempre se suspeitou que fossem os problemas do Framework da arquitetura do sistema), sempre fazem as pessoas se sentirem pouco confiáveis. Como muitas pessoas participaram do processo de investigação antes, o ponto de partida de todos é diferente e várias tentativas são feitas, incluindo alterar os parâmetros do thread de conexão de middleware, alterar a configuração do servidor e localizar o banco de dados que não é resistente. exigem a separação da leitura e da escrita ... Em suma, os deuses de todas as esferas da vida mostraram seus poderes mágicos naquele dia, mas o problema ainda existia. Olhando para trás agora, me sinto tão impotente.

 

Rastreando a estrada: passei um ano novo chinês com ansiedade e me acalmei por um período de tempo após o festival.Finalmente, reuni minha coragem e determinação para re-investigar e resolver os crimes, para lavar a vergonha!

 

Desde a última vez em que o sistema travou e suspendeu a animação, um conjunto de ambientes de teste foi reimplantado e o teste de estresse foi executado novamente. Felizmente, o travamento e a animação suspensa podem ser reproduzidos com sucesso e de forma estável, o que torna mais fácil solucionar a causa.

 

Primeiro, verifique as informações da pilha. Como o serviço está suspenso, não há saída de log do sistema. Você só pode procurar pistas nas informações da pilha JVM.

 

 

O projeto adota o modo de implantação docker,

Insira o contêiner por meio do comando docker exec -it container_name / bin / bash ,

Use o comando jps para encontrar o id do processo java, que é 1 no docker,

Use o comando top -Hp 1 para ver a ocupação de recursos correspondente,

Use o comando jstack 1> jstack.log para exportar as informações da pilha para o arquivo jstack.log.

 

 

Verificou-se que a estrutura do conjunto de conexões de banco de dados do druid está integrada no sistema e o motivo da paralisação é que a aquisição da conexão de banco de dados no druid estava em um estado de espera.

 

Rastreie o código-fonte do druida para descobrir onde a discussão está bloqueada:

 

Continue a rastrear para cima e encontre o método getConnectionInternal ( private DruidPooledConnection getConnectionInternal ( long maxWait) throws SQLException ):

 

 

 

O parâmetro maxWatit é usado para determinar se o processo takeLast deve ser executado , e o valor de maxWatit é sempre o valor padrão -1 em vez de 60000 no arquivo de configuração application.yml.

 

 

 

Então, aí vem o problema: Todos os parâmetros de configuração do druid no arquivo de configuração application.yml (configurado em spring.datasource.druid ) não são eficazes.

 

Siga a videira, a próxima etapa é localizar o problema do parâmetro de configuração do druida:

 

Para o efeito, porque o framework utilizado pelo sistema é BladeX (quanto ao motivo do framework ter sido escolhido, não se sabe. Li parte do seu código-fonte em privado. A qualidade do código ainda precisa de ser melhorada. Pode também estar relacionado ao nível técnico de pessoal individual na equipe de desenvolvimento. Nem todas as pessoas em uma equipe de desenvolvimento têm o mesmo nível técnico, mas eles apenas foram descobertos.) O pool de conexão Druid introduzido também é fornecido pelo BladeX, e o O arquivo de configuração application.yml também é fornecido pelo BladeX, que parece corresponder ao Perfect, não deveria haver tal problema. Na verdade, não é:

 

Como o modo de configuração de fonte de dados dinâmica é adotado no projeto, ele se baseia na estrutura dynamic-datasource-spring-boot-starter de terceiros ,

Depois de rastrear o código-fonte, descobriu-se que os parâmetros de configuração no nó spring.datasource.dynamic.datasource.primary-name ( como mysql1) .druid são carregados automaticamente na configuração de inicialização de dynamic-datasource-spring-boot- iniciador !

 

       Com certeza, ele foi levado para a vala pela configuração padrão de uma determinada estrutura!

 

Nota: Você deve usar druid-spring-boot-starter 1.2.1 e superior para suportar a configuração dinâmica de carregamento!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Após os ajustes acima (1-ajuste a posição da configuração do parâmetro do druida e coloque-o sob o nó da fonte de dados dinâmica; 2-atualize a versão do druid-spring-boot-starter para 1.2.1 e superior), o teste de pressão original para o mesmo o ambiente só pode chegar a 100 O sistema à esquerda e à direita pode resistir a mais de 2.000 no momento (limitado pelo cliente da ferramenta de teste de estresse, o valor limite ainda não foi testado).

 

É claro que, além dos problemas de configuração, o complexo design lógico de negócios do sistema e a consulta lenta que pode ser vista em todos os lugares também são um dos principais fatores que afetam o desempenho do sistema. A próxima etapa será otimizada em tempo e refatorada, se necessário.

 

Em anexo

Baixe a última versão do druid:

https://codeload.github.com/alibaba/druid/zip/refs/tags/1.2.5

 

Descrição dos parâmetros de configuração do druida:

 

Descrição do valor padrão da configuração

nome

 

A importância de configurar esse atributo é que, se houver várias origens de dados, elas podem ser distinguidas pelo nome durante o monitoramento. Se não houver configuração, um nome será gerado, o formato é: "DataSource-" + System.identityHashCode (this). Além disso, configurar esta propriedade pelo menos na versão 1.0.5 não funciona, e definir o nome forçosamente irá causar um erro.

url

 

A URL para se conectar ao banco de dados é diferente para bancos de dados diferentes. Por exemplo: mysql: jdbc: mysql: //10.20.153.104: 3306 / druid2oracle: jdbc: oracle: thin: @ 10.20.149.85: 1521: ocnauto

nome de usuário

 

Nome de usuário para conectar ao banco de dados

senha

 

A senha para se conectar ao banco de dados. Se não quiser que a senha seja gravada diretamente no arquivo de configuração, você pode usar o ConfigFilter .

driverClassName é identificado automaticamente com base no url

Este item pode ser configurado ou não, se o druid não estiver configurado , o dbType será automaticamente reconhecido de acordo com a url , e então o driver correspondente será selecionado

initialSize 0

O número de conexões físicas estabelecidas durante a inicialização. A inicialização ocorre na chamada de exibição do método init ou na primeira hora de getConnection

maxActive 8

Número máximo de pools de conexão

maxIdle 8

Não está mais em uso, sem efeito após a configuração

minIdle

 

Número mínimo de pools de conexão

maxWait

 

O tempo máximo de espera para obter uma conexão, em milissegundos. Depois que maxWait é configurado , bloqueios justos são habilitados por padrão e a eficiência de simultaneidade será reduzida. Se necessário, bloqueios injustos podem ser usados ​​configurando o atributo useUnfairLock como true .

halfPreparedStatements FALSE

Se a cache de preparedStatement , isto é, PSCache . PSCache melhora muito o desempenho de bancos de dados que oferecem suporte a cursores, como oracle . Recomenda-se fechá-lo em mysql .

maxPoolPreparedStatementPerConnectionSize -1

Para habilitar o PSCache , você deve configurá-lo para ser maior que 0. Quando for maior que 0 , poolPreparedStatements é automaticamente disparado e alterado para true . No Druid , não há problema de que o PSCache no Oracle ocupe muita memória. Você pode configurar esse valor para ser maior, por exemplo, 100

validaçãoQuery

 

O sql usado para verificar se a conexão é válida requer uma instrução de consulta, geralmente selecione 'x' . Se validationQuery for null , testOnBorrow , testOnReturn , testWhileIdle não funcionará.

validationQueryTimeout

 

Unidade: segundos, o tempo limite para detectar se a conexão é válida. A camada inferior chama o método void setQueryTimeout (int seconds) do objeto jdbc Statement

testOnBorrow TRUE

Ao solicitar uma conexão, execute validationQuery para verificar se a conexão é válida. Esta configuração reduzirá o desempenho.

testOnReturn FALSE

Quando a conexão é retornada, o validationQuery é executado para verificar se a conexão é válida.Esta configuração irá reduzir o desempenho.

testWhileIdle FALSE

É recomendado configurar como verdadeiro , o que não afetará o desempenho e garantirá a segurança. Verifique ao solicitar uma conexão. Se o tempo ocioso for maior que timeBetweenEvictionRunsMillis , execute um validationQuery para verificar se a conexão é válida.

keepAlive false 1.0.28

Se o tempo ocioso exceder minEvictableIdleTimeMillis para conexões dentro do número de minIdle no pool de conexão , a operação keepAlive será executada .

timeBetweenEvictionRunsMillis 1 minuto ( 1.0.14 )

Existem dois significados: 1) O thread Destroy detectará o intervalo de conexão e, se o tempo ocioso da conexão for maior ou igual a minEvictableIdleTimeMillis , a conexão física será encerrada. 2) A base de julgamento de testWhileIdle , consulte a descrição da propriedade testWhileIdle em detalhes

numTestsPerEvictionRun 30 minutos ( 1.0.14 )

Não é mais usado, um DruidDataSource suporta apenas um EvictionRun

minEvictableIdleTimeMillis

 

O tempo mínimo em que a conexão permanece ociosa sem ser despejada

connectionInitSqls

 

SQL executado quando a conexão física é inicializada

exceptionSorter é identificado automaticamente de acordo com dbType

Quando o banco de dados lança algumas exceções irrecuperáveis, descarte a conexão

filtros

 

O tipo de atributo é uma string. Os plug-ins de extensão são configurados por meio de aliases. Os plug-ins comumente usados ​​são: filter: stat para monitorar estatísticas e filter: log4j para se defender contra injeção de sql filter: wall

proxyFilters

 

O tipo é List <com.alibaba.druid.filter.Filter> , se os filtros e proxyFilters forem configurados ao mesmo tempo , é um relacionamento de combinação, não um relacionamento de substituição

 

Acho que você gosta

Origin blog.csdn.net/yinianshen/article/details/115299645
Recomendado
Clasificación