Em um filtro ISAPI, qual é uma boa abordagem para um arquivo de log comum para vários processos?

StackOverflow https://stackoverflow.com/questions/1511290

Pergunta

Eu tenho um filtro ISAPI que é executado no IIS6 ou 7. Quando houver vários processos trabalhadores ("jardim da web"), o filtro será carregado e executado em cada w3wp.exe.

Como posso permitir com eficiência que o filtro registre suas atividades em um único arquivo de log consolidado?

  • As mensagens de log dos diferentes processos (simultâneos) não devem interferir entre si. Em outras palavras, uma única mensagem de log emitida de qualquer um dos w3wp.exe deve ser realizada como uma única linha contígua no arquivo de log.

  • Deve haver uma contenção mínima para o arquivo de log. Os sites podem atender a 100 pedidos por segundo.

  • A ordem de tempo estrita é preferida. Em outras palavras, se o processo w3wp.exe nº 1 emite uma mensagem em T1, o processo nº 2 emite uma mensagem em T2 e o processo nº 1 emite uma mensagem no T3, as mensagens devem aparecer na ordem de tempo adequada no arquivo de log.

A abordagem atual que tenho é que cada processo possui um arquivo de log separado. Isso tem desvantagens óbvias.

Algumas ideias:

  • Nomeie um dos w3wp.exe para ser "proprietário do arquivo de log" e envie todas as mensagens de log nesse processo especial. Isso tem problemas em caso de reciclagem do processo do trabalhador.

  • Use um sistema mutex para proteger o acesso ao arquivo de log. Isso é alto o suficiente? Nesse caso, cada w3wp.exe teria um arquivo no mesmo arquivo de sistema de arquivos. Devo fazer o arquivo de log após cada gravação? Isso vai funcionar?

alguma sugestão?

Foi útil?

Solução

No começo, eu diria que mais gosto da sua abordagem atual, porque cada processo não compartilha nada, e então percebi que, bem, eles provavelmente estão compartilhando o mesmo disco rígido por baixo. Portanto, ainda há um gargalo onde ocorre a contenção. Ou talvez o sistema operacional e controladores de disco rígido sejam realmente inteligentes em lidar com isso?

Eu acho que o que você quer fazer é ter a escrita do log não diminuindo os threads que estão fazendo o trabalho real.

Então, execute outro processo na mesma máquina (prioridade mais baixa?) Que realmente grava as mensagens de log no disco. Comunique -se ao outro processo usando o UDP não sugerido, mas a memória que os processos compartilham. Também conhecido, confuso, como um arquivo mapeado de memória. Mais sobre arquivos mapeados de memória. Na minha empresa, encontramos arquivos mapeados de memória muito mais rápidos que o Loopback TCP/IP para comunicação na mesma caixa, por isso estou assumindo que também seria mais rápido que o UDP.

O que você realmente tem na sua memória compartilhada pode ser, para iniciantes, uma fila std :: onde os empurrões e os pops são protegidos usando um mutex. Seus threads isapi agarrariam o Mutex para colocar as coisas na fila. O processo de registro pegaria o Mutex para retirar as coisas da fila, soltar o mutex e, em seguida, escrever as entradas no disco. O mutex é protegido apenas a atualização da memória compartilhada, não a atualização do arquivo, por isso parece, em teoria, que o mutex seria mantido por um tempo mais curto, criando menos gargalo.

O processo de registro pode até reorganizar a ordem do que está escrevendo para colocar os registros de data e hora em ordem.

Aqui está outra variação: Contine para ter um log separado para cada processo, mas tenha um encadeamento de logger em cada processo, para que o encadeamento principal crítico não precise esperar que o registro ocorra para prosseguir com seu trabalho.

O problema com tudo o que escrevi aqui é que todo o sistema - hardware, sistema operacional, a maneira como o cache da CPU L1/L2 multicore funciona, seu software - é muito complexo para ser facilmente previsível por pensar justo. Code alguns aplicativos simples de prova de conceito, instrumente-os com alguns horários e experimente-os no hardware real.

Outras dicas

O registro em um banco de dados faria sentido aqui?

Eu usei um sistema de log baseado em UDP no passado e fiquei feliz com esse tipo de solução.

Os logs são enviados via UDP para um processo de coletor log que seu responsável por salvá-lo em um arquivo regularmente.

Não sei se pode funcionar no seu contexto de alto desempenho, mas fiquei satisfeito com essa solução em um aplicativo menos estressante.

Espero que ajude.

Em vez de um OS Mutex para controlar o acesso ao arquivo, você pode usar mecanismos de travamento de arquivos Win32 com LockFile () e desblockfile ().

Minha sugestão é enviar mensagens de forma assíncrona (UDP) para um processo que se encarregará de gravar o log.
O processo irá:
- Um receptor de thread coloca as mensagens em uma fila;
- Um thread é responsável por remover as mensagens da fila de colocar uma lista de ordem;
- Um monitor de thread Mensagens na lista e apenas mensagens com comprimento de tempo maior que o mínimo devem ser salvas no arquivo (para impedir que uma mensagem atrasada seja escrita fora de ordem).

Você pode continuar fazendo log para separar arquivos e encontrar/escrever uma ferramenta para mesclá -los mais tarde (talvez automatizada, ou você pode executá -lo no ponto em que deseja usar os arquivos.)

Rastreamento de eventos para Windows, incluído no Windows Vista e posterior, oferece uma boa capacidade para isso.

Excerto:

O rastreamento de eventos para Windows (ETW) é uma instalação de rastreamento de nível de kernel eficiente que permite registrar kernel ou eventos definidos por aplicativos em um arquivo de log. Você pode consumir os eventos em tempo real ou de um arquivo de log e usá -los para depurar um aplicativo ou determinar onde os problemas de desempenho estão ocorrendo no aplicativo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top