Limitação da taxa de solicitação baseada em URL no Apache

3

Existem muitas ferramentas de limitação de taxa e de QoS, mas até agora não consegui encontrar uma que atenda às minhas necessidades específicas, como segue:

Eu tenho um aplicativo da Web em execução no Apache 2.2 e quero que cada um dos meus clientes fique limitado a, digamos, 10000 solicitações por dia. A limitação não deve ser baseada no endereço IP do cliente, mas na conta do cliente, que pode ser extraída do URL; por exemplo: link . Quando eles ultrapassarem seu limite, eu gostaria que os pedidos deles sejam "desacelerados" para algum valor predefinido, como 15 solicitações por minuto, talvez pela introdução de um atraso. Se isso não for possível, a devolução de um erro como o 503 Serviço indisponível estará ok.

Como posso fazer isso com o Apache? Se não há como fazer isso com o Apache, então eu estaria interessado em sugestões para outras ferramentas, proxies reversos, etc.

ATUALIZAÇÃO: A limitação de taxa precisa acontecer em vários serviços (mod_dav_svn, mod_passenger, mod_wsgi) e deve ser de alto desempenho.

    
por Matt White 08.12.2011 / 09:36

2 respostas

1

Eu não acho que você será capaz de fazer isso apenas no Apache.

Existem alguns módulos do Apache que limitam a largura de banda , mas eu não acho qualquer um deles corresponderá ao que você descreveu.

O

mod_bw pode limitar a largura de banda com base em várias partes do pedido. Ele pode limitar com base no endereço IP, extensão do arquivo, tipo mime, tamanho do arquivo e diretório (com base na minha leitura de os documentos ). Você atinge a limitação baseada em diretório colocando as diretivas do módulo dentro de um bloco <Directory > , portanto, espero que funcionem tão bem dentro de um bloco <Location > . mod_bwshare parece estar dentro dos blocos <Directory > e <Location > também.

A configuração desses módulos do Apache vai para a sua configuração do Apache e eles não procuram valores de qualquer fonte externa, o que significa que você terá que reiniciar o Apache para alterar qualquer um dos valores. Se você quiser limitar a largura de banda apenas depois que um cliente ultrapassar sua cota, será necessário editar os arquivos de configuração do Apache e reiniciar o Apache sempre que algum deles o fizer e o fizer novamente quando o uso da cota expirar.

O jeito que eu faria isso é escrever um pequeno aplicativo em qualquer idioma que aceite um pedido de um arquivo, verificar no banco de dados se o cliente está acima da cota e, em seguida, enviar o arquivo em qualquer taxa apropriada . O cara que escreveu mod_bw explicou como ele conseguiu o afogamento: ele simplesmente divide o arquivo em pequenos "pedaços" (digamos 5KB por pedaço) e então tem um curto sleep() entre ecoar cada pedaço para o cliente.

Eu usaria então mod_rewrite para fazer com que as solicitações de arquivos originais (que você disse pareçam com /customer1/page1 ) traduzissem em algo como /throttle.php?customer=customer1&file=page1 .

O aplicativo pode gravar no banco de dados no início do download para indicar que está processando um arquivo no momento e, novamente, no final, para indicar que está finalizado. Isso deve permitir que você evite que um cliente monopolize todos os seus filhos do Apache.

    
por 08.12.2011 / 23:45
1

Acabei de aceitar a resposta de @ Ladadadada de "Não pode ser feito com o Apache", mas pensei em listar algumas maneiras que estou tentando resolver em torno disso, para referência:

  1. Escreva meu próprio módulo do Apache. Ele usaria a memória compartilhada para acompanhar todos os pedidos e quais contas eles deveriam. Essas contagens expirariam após 24 horas. Contas com um limite inferior teriam cada uma de suas solicitações atrasadas por um determinado período de tempo, e as contas que estivessem acima de um limite superior retornariam um status 503 para todas as solicitações. O nome da conta seria extraído da URL usando SetEnvIf.

  2. Escreva um script (em Ruby) que seja executado como um daemon e siga o log de acesso do Apache. Ele extrairia o nome da conta de cada solicitação registrada e os controlaria de maneira semelhante a # 1, sem as complexidades da memória compartilhada. Ele também rastrearia todos os IPs associados a uma determinada conta nas últimas 24 horas. Quando uma conta ultrapassa seu limite, ela adiciona regras de iptables do NFQUEUE para cada IP associado à conta. Os pacotes desses IPs seriam capturados pelo script Ruby usando Netfilter :: Queue (em um segundo thread), onde eles seriam atrasados.

por 11.12.2011 / 01:44