Nesta página, você encontra dicas para escrever plug-ins de extensões de serviço corretos, com bom desempenho e bem isolados. A correção é fundamental porque os plug-ins são executados em uma sandbox de mecanismo restrita com uma superfície de API limitada. O desempenho é fundamental porque os plug-ins são executados durante as solicitações do usuário final, com pequenas quantidades de recursos. O isolamento é fornecido no nível do projeto.
Primeiros passos
Comece com as amostras
Use APIs compatíveis
Execute testes funcionais e comparativos
Começar com os exemplos
Uma boa maneira de começar é navegar pelos nossos exemplos de código de plug-in. Estes são exemplos de padrões de plug-in comuns, como análise de caminho ou consulta, reescrita de cabeçalho, geração de registros e autenticação personalizadas.
Usar APIs compatíveis
Os plug-ins precisam ser compilados com a interface binária (ABI) Proxy-Wasm. As extensões de serviço são compatíveis com um subconjunto da ABI Proxy-Wasm
que inclui mutações de cabeçalho e corpo HTTP, respostas locais, registros personalizados
e configuração de plug-in. O Proxy-Wasm também é compatível com um pequeno subconjunto da
prévia 1 do WASI,
incluindo stdout e stderr para geração de registros, clock_time_get e random_get.
As extensões de serviço não são compatíveis com timers, métricas personalizadas, dados compartilhados, filas compartilhadas ou chamadas de rede de saída. As extensões de serviço também não aceitam valores de retorno de callback de plug-in que tentam pausar o processamento de solicitações e os ignoram.
Executar testes funcionais e comparativos
Para avaliar a correção e o desempenho, oferecemos uma ferramenta local de teste de plug-in que pode executar, testar e comparar seu plug-in. Você invoca essa ferramenta em um contêiner do Docker, transmitindo um binário de plug-in e um proto de texto de entradas e expectativas. Consulte a documentação do testador local e o exemplo de entrada de teste.
Correção
Não dependa de relógios
Trate os nomes de cabeçalho como sem diferenciação de maiúsculas e minúsculas
Não confie em relógios
Por motivos de segurança, a hora do relógio é definida na criação do contexto (para um plug-in ou uma solicitação) e permanece congelada durante as invocações do plug-in. Isso significa que os plug-ins do WebAssembly não podem entrar em modo de espera. Um modo de espera atinge o tempo limite porque o tempo não avança. Isso também significa que os plug-ins não podem medir o próprio tempo de execução, embora essas informações estejam disponíveis no Cloud Monitoring.
Tratar nomes de cabeçalho sem diferenciação entre maiúsculas e minúsculas
De acordo com a semântica HTTP, os nomes dos campos de cabeçalho HTTP não diferenciam maiúsculas de minúsculas. O uso de maiúsculas e minúsculas em um cabeçalho escrito por um plug-in pode ser alterado antes do envio para clientes ou back-ends.
Desempenho
Evite falhas de plug-in
Compile para velocidade de execução
Pré-compile expressões regulares
Evite copiar dados para contextos HTTP
Evitar falhas de plug-ins
Quando um plug-in falha, a solicitação que acionou o problema recebe um erro. Se isso acontecer com frequência, as reinicializações de plug-ins serão limitadas, o que vai gerar picos de erros que afetam vários usuários.
Para evitar falhas no plug-in, tente o seguinte:
- Evite declarações de todos os tipos. Em vez disso, configure o registro de erros ou respostas locais para os usuários.
- Em Rust, evite usar métodos, como
unwrap, que podem resultar em falhas. Além disso, é possível configurar o plug-in para processar falhas usandopanic::set_hook. - Teste seu plug-in usando o testador de plug-ins fornecido pelo Google e verifique se entradas malformadas ou vazias são processadas sem que o plug-in falhe.
Compilar para velocidade de execução
Compile seu código WebAssembly para alcançar a melhor velocidade de execução usando a
opção de build -O3 (para C++) ou opt-level=3 (para Rust).
Pré-compilar expressões regulares
Evite operações que exigem muita computação no caminho por solicitação (em manipuladores HTTP). Em vez disso, faça qualquer trabalho que não seja específico da solicitação no momento da configuração do plug-in e transmita qualquer estado pré-calculado para cada contexto de solicitação HTTP (também conhecido como contexto de fluxo).
Em particular, pré-compile todas as expressões regulares no momento da configuração do plug-in. Nosso exemplo de código de regex mostra como fazer isso.
Evite copiar dados para contextos HTTP
Ao compartilhar dados entre o contexto raiz e os contextos HTTP, evite cópias ou chamadas de clonagem caras. Em vez disso, compartilhe indicadores ou referências. Em C++, isso pode ser feito com std::shared_ptr ou ponteiros e referências brutos porque o contexto raiz dura mais que qualquer contexto HTTP. Em Rust, os valores podem ser compartilhados usando
std::rc::Rc. Em Go, os valores podem ser compartilhados armazenando ponteiros para eles,
que são removidos pelo coletor de lixo.
Segurança
Isolar cargas de trabalho por projeto
Na infraestrutura do Google, plug-ins pertencentes ao mesmo projeto Google Cloud podem ser executados na mesma sandbox segura. Isso significa que o ambiente de execução do WebAssembly é a única barreira de segurança entre plug-ins no mesmo projeto.
Use projetos Google Cloud separados para cargas de trabalho que precisam de separação de segurança. Essa prática também oferece separação de recursos e permissões.
Restringir secrets na Media CDN
Por design, a Media CDN é executada em uma frota de hardware operada fora do controle físico do Google. Ao escrever plug-ins relacionados à segurança para a Media CDN, use nomes de host ou subdomínios dedicados e configure plug-ins com chaves de assinatura que são trocadas com frequência.