Com a filosofia 1RTT do Discourse, acho que pode ser hora de reescrever o código de serviço de imagens de avatar.
As imagens de avatar devem ser tratadas como qualquer outro upload de imagem. Redimensionadas no upload, armazenadas e servidas diretamente do sistema de arquivos/S3/CDN.
O método atual do Discourse usa um método de proxy para servir imagens de avatar. Essa abordagem cria idas e vindas HTTP desnecessárias e desafios de endereço IP.
Aqui está uma visão geral das solicitações de avatar:
O HTML inicial do Discourse é pintado.
O navegador detecta uma imagem de avatar e solicita uma imagem do servidor Discourse
O servidor Discourse atua como um proxy e solicita a imagem do armazenamento de arquivos local/S3/CDN
O servidor Discourse recebe a imagem
O servidor Discourse envia a imagem para o navegador.
Cada avatar personalizado tem 1 ida e volta HTTP adicional e tempo de processamento do servidor relacionado. Um tópico típico ou listagem de tópicos pode ter mais de 30 imagens de avatar personalizadas. No meu site, isso resulta em 10 mil a 20 mil RTTs extras e carga de servidor relacionada por dia que poderiam ser evitadas.
Além disso, as imagens de avatar são chamadas de acesso direto do servidor. Para qualquer proteção em nível de CDN, é necessário adicionar o endereço IP à lista de permissões. Isso requer a permissão de gateways em vez de endereços IP de servidor. As empresas de hospedagem fazem alterações para balancear o tráfego de rede regularmente. Meu endereço IP do gateway mudará/evoluirá. O software não deve depender da atualização do endereço IP para que imagens básicas de avatar funcionem. Isso é baseado no seguinte incidente de suporte, Proxy de Avatar e Proteção contra Hot-Link de CDN
Do ponto de vista de desempenho e simplicidade, podemos ter imagens de avatar servidas diretamente do armazenamento de arquivos designado do Discourse?
Esta é, de fato, uma parte muito complicada do aplicativo @LotusJeff.
Para resolver algumas de suas deficiências, recentemente desenvolvemos uma maneira de reduzir essas idas e vindas em nossa hospedagem, mas acho que nunca documentamos isso aqui. Existem documentações públicas sobre isso, @david?
Sim, temos essa GlobalSetting, que você pode habilitar definindo a variável de ambiente DISCOURSE_REDIRECT_AVATAR_REQUESTS=true
Então, em vez de fazer proxy, as requisições de avatar serão atendidas com um redirecionamento 302 para o armazenamento de arquivos.
Por si só… isso não é realmente uma boa ideia. Significa que os navegadores terão que fazer duas viagens completas de ida e volta HTTP para cada avatar. Portanto, embora possa resolver seu problema de ‘proteção contra hotlinking’… eu não recomendaria habilitá-lo. Isso tornará a experiência pior para seus usuários.
Usamos a configuração em nossa hospedagem discourse.org. Mas a complementamos com uma função lambda rodando em nosso CDN Cloudfront. Ela detecta o 302 e faz o proxy por si mesma. Essencialmente: movemos o proxy de nossos servidores de aplicação para o CDN.
Quanto à questão mais geral de “podemos mudar os avatares para linkar diretamente para o asset”. É complicado porque os URLs de avatar estão embutidos em todas as postagens históricas (por exemplo, citações). Os URLs dinâmicos /user-avatar/ nos permitem mantê-los funcionando quando um usuário altera seu avatar. Receio que não tenhamos planos de mudar esse sistema.
Se houver uma maneira fácil e de baixo risco de fazer o proxy existente funcionar para seu caso de uso (por exemplo, adicionar uma GlobalSetting que insira um cabeçalho HTTP específico em quaisquer requisições de proxy de avatar), então poderíamos considerar aceitar um PR para a mudança.
Nenhuma das opções mencionadas acima é viável ou preferida no meu ambiente atual. Gostaria de ajudar a resolver essa parte convoluta da aplicação, mas sou muito novo nesta stack de tecnologia.
A única assistência que posso oferecer agora é usando minhas antigas habilidades de BA e Gerenciamento de Desenvolvimento. Então, no espírito de sentir que estou ajudando, estas são minhas opiniões.
Quando olho para qualquer enigma técnico, primeiro verifico suposições possíveis que tornariam a solução mais difícil.
Uma suposição é salvar uma imagem de avatar atualizada como um novo nome de arquivo. A pessoa possui apenas um avatar. Não mantemos um registro dos nomes dos avatares. Sugiro que, quando uma pessoa atualizar sua imagem de avatar, ela seja salva usando o mesmo nome de arquivo do avatar existente. Isso é basicamente o que o link /user-avatar/ está fazendo. Em vez de ter uma solução alternativa, realize essa lógica durante a criação/atualização do avatar. Isso resolveria as preocupações com posts históricos para futuras postagens baked.
Isso é uma mudança de grande impacto? Não, essa mudança poderia ser implementada ao longo de meses, melhorando lentamente o desempenho do site. Minhas equipes de desenvolvimento sempre tiveram uma lista de melhorias oportunísticas para cada bloco de código. Queríamos fazer essas melhorias, mas elas não eram críticas o suficiente para serem feitas individualmente. Quando o código era aberto para desenvolvimento por algum outro motivo, o desenvolvedor também fazia mudanças oportunísticas. Isso minimizava nossos testes e erros ao reduzir o número de vezes que o código era aberto e atualizado.
Eu dividiria este projeto nas seguintes fases:
Atualizar a lógica de salvamento de imagens de avatar para substituir quaisquer atualizações de imagem usando o nome de arquivo atual.
Substituir todos os usos de imagens de avatar por uma função padrão que utilize o sistema de armazenamento/distribuição de arquivos preferido do discourse. Essas poderiam ser implementadas ao longo de meses, passando lentamente para a nova lógica de apresentação de imagens de avatar.
Após a conclusão das duas primeiras etapas, fornecer à comunidade os passos e trechos de código para trocar e refazer os avatares históricos em HTML baked para seu sistema de arquivos preferido. Isso ficaria a critério dos proprietários do site do discourse implementar. (Essas instruções de código e trechos seriam úteis para fazer alterações brutas no HTML)
Tenho certeza de que você considerou tudo isso. Sei também que corrigir códigos antigos nunca entra na lista de prioridades.
Se houver algo que eu possa fazer para ajudar neste esforço, por favor, me avise.
ps. Agradeço a oferta de um PR para uma configuração de cabeçalho global. Deixe-me fazer alguma pesquisa adicional e retornar com requisitos mais definidos. obrigado pela sua assistência.
Infelizmente, se o arquivo for mutável, isso significaria que não poderíamos mais habilitar o cache infinito do ativo na CDN e nos navegadores dos usuários finais.
Existem estratégias para fazer algo assim funcionar sem prejudicar muito o desempenho… por exemplo, a diretiva stale-while-revalidate. Mas isso traz seus próprios custos e implicações de UX.