MD
Múltiplas abas e carregamento assíncrono de página
Olá, boa tarde a todos!
Alguns colegas devem em momento ou outro, ter enfrentado algum problema com a execução de múltiplas páginas/programas "lentos" ao mesmo tempo, ou ainda, com a característica "síncrona" de execução do PHP.
Qual era o nosso cenário, tínhamos um dashboard carregado vários componentes via Ajax, sob o qual eram executadas algumas consultas "lentas", ao acessar o dashboard era visível que ele somente iniciava o processamento de um bloco após finalizar o bloco prévio, ou seja, fazia uma coisa de cada vez. Algo similar, mas mais complexo para a experiencia do usuário, acontecia no advento de executar o mesmo sistema com diversas abas abertas ao mesmo tempo no navegador, com alguma frequência nos deparávamos com a mensagem de "Carregando" que demorava para ser executada (claro, ela estava esperando o fim de algum outro processo).
Pesquisando, acabamos por descobrir que esse "lock" referia-se a sessão do PHP, uma vez que a sessão não pode ser aberta duas vezes (imagine uma variável de sessão sendo escrita por dois programas ao mesmo tempo), uma segunda ou terceira execução simultânea de um Programa na mesma sessão fica aguardando no "session_start" do TSession até que o script prévio seja finalizado (momento em que a sessão aberta é fechada).
Como resolvemos isso? Utilizando a função session-commit() (que na verdade é um atalho para session-write-close), modificando o comportamento (e não os métodos) do componente TSession do framework que esta armazenado em lib/adianti/registry/TSession.php. O arquivo utilizado segue em anexo para que possa ser avaliado e utilizado se julgarem pertinente.
E o que ela faz? Bem, ela faz o que o nome diz, grava a sessão e a fecha para escrita durante a execução daquele programa, permitindo que um segundo ou terceiro programa possa abrir a sessão e realizar a sua execução de forma assíncrona, utilizando essa função adotamos um formato de trabalho onde através do TSession a sessão sempre esta aberta para leitura e fechada para escrita, ela somente é aberta (e fechada na sequencia) quando um valor é salvo na sessão.
E o funcionamento de TSession::getValue, permanece o mesmo? Sim! Sempre que uma sessão é iniciada, ela é aberta e fechada na sequência, permanecendo aberta para leitura, ou seja TSession::getValue funciona perfeitamente.
E quanto ao TSession::setValue? Bem, ele também permanece funcionando normalmente, sempre que formos salvar um valor, a sessão é aberta para escrita, o valor é salvo e no fim a sessão é fechada novamente.
Há algum cuidado extra? Sim, não é recomendada a manipulação da sessão de forma direta, sempre use TSession, a manipulação direta da sessão irá falhar pois os dados setados na sessão não serão persistidos para outras execuções. Caso se faça necessário manipular a sessão de forma direta neste cenário, utilize:
Quais os nossos resultados finais?
O carregamento completo do nosso dasboard era de 9,22 segundos em média, ele passou para 4,27 segundos em média, com os componentes sendo carregados de forma simultânea. Quanto as mensagens de "Carregando", bem, elas não aparecem mais no cenário que foi mencionado acima.
Algumas fontes:
https://www.php.net/manual/pt_BR/function.session-commit.php
https://www.php.net/manual/pt_BR/function.session-write-close.php
https://www.php.net/manual/pt_BR/function.session-start.php
https://ma.ttias.be/php-session-locking-prevent-sessions-blocking-in-requests/
https://coderwall.com/p/h9gu8g/php-session-locking
https://imasters.com.br/back-end/php-session-locking-como-evitar-bloqueio-de-sessoes-nas-solicitacoes-php
Alguns colegas devem em momento ou outro, ter enfrentado algum problema com a execução de múltiplas páginas/programas "lentos" ao mesmo tempo, ou ainda, com a característica "síncrona" de execução do PHP.
Qual era o nosso cenário, tínhamos um dashboard carregado vários componentes via Ajax, sob o qual eram executadas algumas consultas "lentas", ao acessar o dashboard era visível que ele somente iniciava o processamento de um bloco após finalizar o bloco prévio, ou seja, fazia uma coisa de cada vez. Algo similar, mas mais complexo para a experiencia do usuário, acontecia no advento de executar o mesmo sistema com diversas abas abertas ao mesmo tempo no navegador, com alguma frequência nos deparávamos com a mensagem de "Carregando" que demorava para ser executada (claro, ela estava esperando o fim de algum outro processo).
Pesquisando, acabamos por descobrir que esse "lock" referia-se a sessão do PHP, uma vez que a sessão não pode ser aberta duas vezes (imagine uma variável de sessão sendo escrita por dois programas ao mesmo tempo), uma segunda ou terceira execução simultânea de um Programa na mesma sessão fica aguardando no "session_start" do TSession até que o script prévio seja finalizado (momento em que a sessão aberta é fechada).
Como resolvemos isso? Utilizando a função session-commit() (que na verdade é um atalho para session-write-close), modificando o comportamento (e não os métodos) do componente TSession do framework que esta armazenado em lib/adianti/registry/TSession.php. O arquivo utilizado segue em anexo para que possa ser avaliado e utilizado se julgarem pertinente.
E o que ela faz? Bem, ela faz o que o nome diz, grava a sessão e a fecha para escrita durante a execução daquele programa, permitindo que um segundo ou terceiro programa possa abrir a sessão e realizar a sua execução de forma assíncrona, utilizando essa função adotamos um formato de trabalho onde através do TSession a sessão sempre esta aberta para leitura e fechada para escrita, ela somente é aberta (e fechada na sequencia) quando um valor é salvo na sessão.
E o funcionamento de TSession::getValue, permanece o mesmo? Sim! Sempre que uma sessão é iniciada, ela é aberta e fechada na sequência, permanecendo aberta para leitura, ou seja TSession::getValue funciona perfeitamente.
E quanto ao TSession::setValue? Bem, ele também permanece funcionando normalmente, sempre que formos salvar um valor, a sessão é aberta para escrita, o valor é salvo e no fim a sessão é fechada novamente.
Há algum cuidado extra? Sim, não é recomendada a manipulação da sessão de forma direta, sempre use TSession, a manipulação direta da sessão irá falhar pois os dados setados na sessão não serão persistidos para outras execuções. Caso se faça necessário manipular a sessão de forma direta neste cenário, utilize:
- <?php
- session_start();
- $_SESSION[variavel] = valor;
- session_commit();
- ?>
Quais os nossos resultados finais?
O carregamento completo do nosso dasboard era de 9,22 segundos em média, ele passou para 4,27 segundos em média, com os componentes sendo carregados de forma simultânea. Quanto as mensagens de "Carregando", bem, elas não aparecem mais no cenário que foi mencionado acima.
Algumas fontes:
https://www.php.net/manual/pt_BR/function.session-commit.php
https://www.php.net/manual/pt_BR/function.session-write-close.php
https://www.php.net/manual/pt_BR/function.session-start.php
https://ma.ttias.be/php-session-locking-prevent-sessions-blocking-in-requests/
https://coderwall.com/p/h9gu8g/php-session-locking
https://imasters.com.br/back-end/php-session-locking-como-evitar-bloqueio-de-sessoes-nas-solicitacoes-php
uma dúvida, no seu caso você não recebeu aviso assim?
não é a todo momento, mas as vezes surge esse aviso no log do php.
Olá, bom dia,
Desculpe pela demora no retorno.
Não recebi esse alerta, inclusive acabo de fazer uma busca nos logs do servidor por isso, em nenhuma das aplicações me deparei com esse cenário.
Aparentemente, ele esta tentando inicializar uma sessão que já esta inicializada, ou esta tentando enviar informações para o cliente, em momento que os headers já foram enviados.
Recomendo uma leitura em https://pt.stackoverflow.com/questions/28359/warning-ao-tentar-session-start-php
Espero ter ajudado, abraço!
Achei interessante, tenho problemas com sessão, o tempo dela não obedece, tentei implementar essa sua modificação para ver se me ajudava, mas tive problemas, percas de sessão, mesmo só usando o TSession, acabei perdendo dados da sessão em várias partes do sistema.
Só uma observação, fiz login com o GIT para postar no fórum e não faço ideia de onde veio essa foto de perfil, não sou eu e não é ninguém que eu conheça kkkkkkkk
Olá Leonardo, boa noite!
É bem estranho seu relato, tenho usado essa mesma modificação em outros sistemas sem nenhum problema.
O único e pertinente cuidado, como mencionado, é a manipulação direta de variáveis da sessão, ou ainda, a manipulação da sessão por bibliotecas externas, o que pode ser resolvido com a mesma técnica mencionada no artigo.
Apenas esteja atento, essa modificação diz respeito apenas ao tempo de carga de chamadas simultâneas do PHP, ela não refere-se a duração da sessão, menciono isso, pois em sua mensagem você refere-se a sessão não obedecer o tempo, o que não é o caso do artigo.
Se me fornecer mais detalhes, talvez possa lhe ajudar melhor.
Um abraço!
Olá Marco, Boa Tarde!
O anexo "TSession.phps" não está mais acessível. Poderia reenviar, ou disponibilizar?
Grato! Leonam.
Olá, boa tarde!
Revisitamos esse tópico recentemente devido a outra postagem.
Centralizamos o componente em: https://github.com/plenatech/adianti-community-contribs/tree/main/TitansTemplate/TSession