Linguagem de Política de Roteamento para Balanceadores de Carga

Saiba como gravar instruções de condição de política de roteamento que orientem o comportamento de roteamento de um balanceador de carga.

Para controlar como as solicitações de entrada para recursos como servidores Web são roteadas, crie políticas. Essas políticas assumem uma forma geral de "Se isso acontecer, encaminhe o tráfego para um conjunto de backend". O conjunto de backend deve ser um que você já tenha criado.

As políticas de roteamento funcionam das seguintes maneiras:

  • Cada solicitação HTTP é avaliada segundo as regras.

  • As regras são executadas na ordem definida na política.

  • Cada regra tem pelo menos uma condição e um conjunto de backend.

  • Se a condição da solicitação HTTP corresponder a uma regra, a solicitação será encaminhada para o conjunto de backend definido para a regra. As outras regras na política são ignoradas e a solicitação não é avaliada de acordo com elas.

Exemplo: Uma Regra de Caminho

Veja um exemplo de conjunto de regras de política de roteamento que contém apenas uma regra baseada em caminho:

{
  "name": "BasicPathBasedPolicy",
  "conditionLanguageVersion": "V1",
  "rules": [
    {
      "name": "Documents_rule",
      "condition" : "any(http.request.url.path eq (i '/documents'))",
      "actions": [{
        "name": "FORWARD_TO_BACKENDSET",
        "backendSetName": "backendSetForDocuments"
      }]
    }
  ]
}

Esse exemplo mostra os seguintes elementos:

  • O conjunto de regras está entre chaves { } e contém um nome e o número da versão do idioma.

  • O nome do conjunto de regras no exemplo é "BasicPathBasedPolicy". As regras no conjunto estão contidas entre colchetes.

  • A única regra no conjunto é denominada "Documents_rule".

  • A condição da regra informa que se any (qualquer uma) das condições for atendida, execute a ação em "actions".

  • A condição compara o caminho do URL da solicitação HTTP de entrada com /documents. A comparação é eq, que significa igual e também pode ser escrito como =.

  • Na instrução de condição (i '/documents') declara que '/documents' não faz distinção entre maiúsculas e minúsculas.

  • Quando a condição é atendida, a medida tomada é encaminhar a solicitação para um conjunto de backend específico; nesse caso, "backendSetForDocuments". Esse conjunto de backend deve existir para que a regra seja válida.

A regra pode ser parafraseada como "Se o caminho do URL solicitado for uma correspondência exata para /documents, encaminhe a solicitação ao conjunto de backend backendSetForDocuments.

Exemplo: Duas Regras de Caminho Simples

Veja um exemplo de conjunto de regras de política de roteamento que contém duas regras simples baseadas em caminho. Uma consulta de entrada é enviada para outro conjunto de backend com base no caminho do URL da solicitação, e o encaminhamento acontecerá se a primeira ou a segunda condição for atendida. Várias regras são avaliadas em sua ordem na política. Se uma consulta corresponder a ambas as condições, a ação será executada na primeira correspondente e a segunda correspondência será ignorada.

{
  "name": "PathBasedPolicy",
  "conditionLanguageVersion": "V1",
  "rules": [
    {
      "name": "Documents_rule",
      "condition" : "any(http.request.url.path eq (i '/documents'))",
      "actions": [{
        "name": "FORWARD_TO_BACKENDSET",
        "backendSetName": "backendSetForDocuments"
      }]
    },
    {
      "name": "Videos_rule",
      "condition" : "any(http.request.url.path eq (i '/videos'))",
      "actions": [{
        "name": "FORWARD_TO_BACKENDSET",
        "backendSetName": "backendSetForVideos"
      }]
    }
  ]
}

Exemplo: Uma Regra com Duas Condições

A próxima política tem uma regra com duas condições (cada condição é separada por uma vírgula). A primeira condição examina os cabeçalhos de solicitação e a segunda examina a string de consulta da solicitação:

      {
        "name": "Example_policy",
        "conditionLanguageVersion": "V1",
        "rules": [
          {
            "name": "HR_mobile_user_rule",
            "condition" : "all(http.request.headers[(i 'user-agent')] eq (i 'mobile'), http.request.url.query['department'] eq 'HR')",
            "actions": [{
              "name": "FORWARD_TO_BACKENDSET",
              "backendSetName": "backendSetForHRMobileUsers"
            }]
          }
        ]
      }

A regra agora exige que duas condições sejam verdadeiras para encaminhar uma solicitação a um conjunto de backend, uma vez que ela começa com a palavra-chave all. As condições da regra podem ser parafraseadas como "Se o valor user-agent solicitado no cabeçalho for definido como mobile e o valor department no cabeçalho for HR, encaminhe para o conjunto de backend especificado.

Exemplo: Duas Regras

O exemplo final mostra duas regras. Cada regra tem uma ação diferente e ambas têm duas condições. É importante ressaltar que a segunda regra começa com a palavra-chave any, o que significa que somente uma das duas condições precisa ser verdadeira para disparar a ação. Se mais de duas condições forem especificadas, se uma delas for verdadeira, a ação será disparada.

      {
        "name": "Example_policy",
        "conditionLanguageVersion": "V1",
        "rules": [
          {
            "name": "HR_mobile_user_rule",
            "condition" : "all(http.request.headers[(i 'user-agent')] eq (i 'mobile'), http.request.url.query['department'] eq 'HR')",
            "actions": [{
              "name": "FORWARD_TO_BACKENDSET",
              "backendSetName": "backendSetForHRMobileUsers"
            }]
          },
          {
            "name": "Documents_rule",
            "condition" : "any(http.request.url.path eq (i '/documents'), http.request.headers[(i 'host')] eq 'doc.myapp.com')",
            "actions": [{
              "name": "FORWARD_TO_BACKENDSET"
              "backendSetName": "backendSetForDocuments"
            }]
          }
        ]
      }

Condições da Regra

Saiba mais sobre as condições da regra da linguagem de política de roteamento para um recurso do Balanceador de Carga.

As condições da regra são escritas na forma de predicados. Vários predicados podem ser usados em uma condição, usando combinadores. Os dois combinadores: any() e all() se comportam como um operador OR ou AND lógico. Um combinador também pode ser negado colocando a palavra-chave not antes dele. Um predicado simples pode ser expresso como:

left value matcher right value

Uma condição para uma regra que deve corresponder se o caminho do URL da solicitação HTTP começar com /foo/bar seria:

http.request.url.path sw '/foo/bar'

Mais detalhes sobre os correspondentes disponíveis estão em Correspondentes.

Mais detalhes sobre as variáveis disponíveis estão em Variáveis.

Sintaxe para vários predicados

not? any|all(<condition>,<condition>,...)

Exemplo:

all(http.request.url.path sw '/foo', 'bar' in (http.request.url.query))

Exemplos de condição

Veja a seguir mais exemplos de como as condições podem ser usadas. Veja a seguir mais detalhes sobre sintaxe exata e funcionalidade.

  • Para corresponder a uma solicitação HTTP se o caminho do URL começar com "/category/element":

    http.request.url.path sw '/category/element'
  • Para corresponder a uma solicitação HTTP se seu caminho de URL começar com "/category" ou terminar com "/id":

    any(http.request.url.path sw '/category', http.request.url.path ew '/id')
  • Para corresponder a uma solicitação HTTP se um cabeçalho de solicitação "User-Agent" estiver presente:

    (i 'User-Agent') in (http.request.headers)
  • Para corresponder a uma solicitação HTTP se o cabeçalho "User-Agent" tiver o valor "Some User Agent":

    http.request.headers[(i 'User-Agent')] eq 'Some User Agent'
  • Para corresponder a uma solicitação HTTP se a string de consulta de URL tiver uma chave "search" que distingue maiúsculas de minúsculas, por exemplo, como no URL https://www.example.com/category/?search=item+foo%20bar&page=1

    'search' in (http.request.url.query)
  • Para corresponder a uma solicitação HTTP se a string de consulta de URL tiver uma chave "search" que distingue maiúsculas de minúsculas (distinção entre maiúsculas e minúsculas) com um valor "item+foo%20bar" sem distinção entre maiúsculas e minúsculas, por exemplo, como no URL https://www.domain.com/category/?search=item+foo%20bar&page=1
    http.request.url.query['search'] = (i 'item foo bar')

    A correspondência da consulta de URL (chaves e valores) deve ser feita usando as versões de seus valores sem escape de URL.

  • Para fazer uma correspondência sem distinção entre maiúsculas e minúsculas com uma solicitação HTTP para um cookie chamado "tastycookie":

    (i 'tastycookie') in (http.request.cookies)
  • Para fazer uma correspondência sem distinção entre maiúsculas e minúsculas com uma solicitação HTTP para um cookie chamado "tastycookie" que contém o valor "strawberry" que distingue maiúsculas de minúsculas:

    http.request.cookies[(i 'tastycookie')] = 'strawberry'

Correspondentes

Saiba como usar correspondentes na linguagem de política de roteamento para um recurso do Balanceador de Carga.

Vários correspondentes estão disponíveis para uso em condições.

Correspondentes de String

A próxima tabela lista os correspondentes que operam em valores de string. Alguns correspondentes têm variantes alternativas, o que significa que qualquer uma dessas variantes pode ser usada de forma intercambiável para esse correspondente.

Os exemplos de cada correspondente coincidem com http.request.url.path contendo '/category/element/id':

Nome

Alternativas

Descrição

Exemplo

eq

=, ==, igual, igual

Corresponde se os valores do lado esquerdo e direito do correspondente são iguais.

http.request.url.path eq "/category/element/id"

ovelha

Corresponde se o valor do lado esquerdo termina com o valor do lado direito.

http.request.url.path ew '/id'

sw

Corresponde se o valor do lado esquerdo começa com o valor do lado direito.

http.request.url.path sw '/categoria'

não eq

!=, not equal, not equals

Corresponde se os valores do lado esquerdo e direito do correspondente não são iguais.

http.request.url.path neq '/some/other/path'

não ew

Corresponde se o valor do lado esquerdo não termina com o valor do lado direito.

http.request.url.path not ew '/not_id'

não sw

Corresponde se o valor do lado esquerdo não começa com o valor do lado direito.

http.request.url.path not sw '/not_category'

Correspondentes Parciais

Algumas das variáveis usadas nas regras contêm mapas arbitrários de chave/valor de dados quando as regras são executadas. Por exemplo, http.request.headers contém os cabeçalhos de solicitação HTTP. Para obter mais detalhes sobre os mapas disponíveis, consulte Variáveis.

Os correspondentes in e not in podem ser usados para verificar se uma variável de mapa contém uma chave específica. Depende da variável que a chave realmente representa.

A sintaxe para verificar se uma variável de mapa contém uma chave específica é:

<key> in (<map variable>)
  • <key> deve ser uma string com ou sem distinção entre maiúsculas e minúsculas.

  • O valor do lado direito deve estar entre parênteses.

Por exemplo, essa condição corresponde se a solicitação HTTP tem um cookie com o nome 'Foo':

'Foo' in (http.request.cookies)

Valores

Saiba como usar valores na linguagem de política de roteamento para um recurso do Balanceador de Carga.

Os valores usados em predicados podem ser valores constantes ou variáveis que são avaliados no runtime.

Constantes

Saiba mais sobre as constantes associadas aos valores na linguagem de política de roteamento de um recurso do Balanceador de Carga.

As regras suportam constantes de string gravadas entre aspas simples.

Exemplo:

http.request.url.path sw '/foo'

Distinção entre maiúsculas e minúsculas da string

A correspondência de string usa comparações com distinção entre maiúsculas e minúsculas por padrão.

Por exemplo, se o caminho do URL da solicitação HTTP para alguma solicitação fosse /foo, o seguinte predicado não corresponderia a essa solicitação porque a comparação de string com distinção entre maiúsculas e minúsculas é usada:

http.request.url.path eq '/FOO'

A correspondência sem distinção entre maiúsculas e minúsculas será feita se pelo menos um dos valores comparados for uma string sem distinção entre maiúsculas e minúsculas. A sintaxe de uma string que não faz distinção entre maiúsculas e minúsculas é:

(i '<string content>')

Por exemplo, essas strings não fazem distinção entre maiúsculas e minúsculas, portanto são equivalentes quando usadas em predicados:

(i 'foo')
(i 'Foo')
(i 'FOO')

Em comparação com o exemplo original - esse predicado não corresponde, porque usa comparação sem distinção entre maiúsculas e minúsculas:

http.request.url.path eq (i '/FOO')

Variáveis

Saiba mais sobre as variáveis associadas aos valores na linguagem de política de roteamento de um recurso do Balanceador de Carga.

As variáveis são usadas em condições para corresponder a algum valor específico da solicitação HTTP. Os valores reais de cada variável são determinados quando as regras são executadas, ou seja, durante cada solicitação HTTP individual.

Variáveis de Tipo de Mapa

Algumas das variáveis contêm mapas arbitrários de chave/valor de dados de solicitação, por exemplo, cabeçalhos de solicitação ou cookies. Para cada chave, pode haver um ou mais valores. Por exemplo, pode haver vários cabeçalhos de solicitação com o mesmo nome.

Geralmente, as variáveis de mapa podem ser usadas nas regras das seguintes maneiras:

  • Para verificar se um mapa tem uma chave específica.

  • Para verificar se um mapa tem uma chave específica com um valor específico.

Verificando se um mapa tem uma chave específica:

A verificação se uma variável de mapa tem uma chave específica é feita com o correspondente in. Para obter mais detalhes, consulte Linguagem de Política de Roteamento para Balanceadores de Carga.

Por exemplo:

'Foo' in (http.request.cookies)

Essa condição corresponde se a solicitação HTTP tem um cookie com o nome 'Foo'.

Verificando se um mapa tem uma chave específica com um valor específico:

A verificação se um mapa tem uma chave específica com um valor específico é feita usando a notação de colchete [] para obter os valores em uma chave específica. A sintaxe para usar a notação de colchete é:

<variable>[<key>]

O valor <key> deve ser especificado como string com ou sem distinção entre maiúsculas e minúsculas.

A verificação real de um valor específico é feita usando o correspondente eq para verificar se any (algum) dos valores nessa chave é igual a esse valor específico. O predicado corresponderá se pelo menos um dos valores nessa chave corresponder a esse valor específico.

Exemplos:

  • Para fazer a correspondência se qualquer valor do cabeçalho "header-name" for igual a "header-value":

    http.request.headers[(i 'header-name')] eq 'header-value'

    O nome do cabeçalho é comparado sem distinção entre maiúsculas e minúsculas, mas o valor do cabeçalho é comparado com distinção entre maiúsculas e minúsculas.

  • Para corresponder se qualquer valor do cookie "cookie-name" for igual a 'cookie-value':

    http.request.cookies['cookie-name'] eq 'cookie-value'

O correspondente not eq pode ser usado para verificar se none (nenhum) dos valores nessa chave é igual a um valor específico.

Exemplos:

  • Para corresponder se nenhum valor do cabeçalho "header-name" for igual a "header-value":

    http.request.headers[(i 'header-name')] not eq 'header-value'

    O nome do cabeçalho é comparado sem distinção entre maiúsculas e minúsculas. O valor do cabeçalho é comparado com distinção entre maiúsculas e minúsculas.

  • Para corresponder se nenhum valor do cookie "cookie-name" for igual a 'cookie-value':

    http.request.cookies['cookie-name'] not eq 'cookie-value'

Todas as Variáveis Disponíveis

As variáveis disponíveis para uso nas condições são:

Nome

Descrição

Exemplo

http.request.headers

Um mapa contendo cabeçalhos de solicitação HTTP.

Esse mapa tem um comportamento especial - as chaves (nomes de cabeçalho) devem ser strings sem distinção entre maiúsculas e minúsculas. O uso de strings com distinção entre maiúsculas e minúsculas para chaves http.request.headers em predicados não é permitido.

  • Uso correto:

    (i 'User-Agent') in http.request.headers
    http.request.headers[(i 'User-Agent')] = 'Mobile'
  • Uso incorreto:

    'User-Agent' in http.request.headers
    http.request.headers['User-Agent'] = 'Foo'

http.request.url.path

Caminho do URL de solicitação HTTP Este é o URL de solicitação, sem protocolo, domínio, porta e string de consulta.

http.request.url.query

Um mapa contendo elementos de consulta de URL de solicitação HTTP. Se o URL da solicitação não tiver uma consulta (não tiver o caractere ?) ou se a consulta estiver vazia (o caractere ? for o último no URL), esse mapa estará vazio.

A consulta é analisada para produzir o mapa http.request.url.query, tomando a parte da string de consulta do URL (que é a parte após o primeiro caractere ?) e dividindo-a em pares de chave/valor, tratando estes caracteres como especiais:

  • O caractere & é o separador entre diferentes pares de chave/valor
  • O caractere = é o separador entre a chave e o valor (em um par de chave/valor)

O primeiro caractere ? presente no URL marca o início da string de consulta. Se caracteres ? extras aparecerem após o primeiro, eles serão tratados da mesma forma que qualquer outro caractere, sem nenhum tratamento especial.

Em um par de chave/valor, o primeiro caractere = presente separa a chave do valor. Se caracteres = extras estiverem presentes, eles serão tratados como parte do valor.

Chaves e valores não têm escape de acordo com as regras de escape de URL.

URL: https://www.domain.com/path?key=value&key=%61&another%20key=another+value

Os dados http.request.url.query de uma solicitação com esse URL terão esta aparência expressa como JSON:

{
  "key": [
    "value",
    "a"
  ],
  "another key": [
    "another value"
  ],
}

Nesse exemplo, a correspondência de chave e valor faz distinção entre maiúsculas e minúsculas. Portanto, se em vez de key=value, o URL contiver KEY=value ou key=VALUE, a condição não corresponderá.

No entanto, um par de chave/valor da string de consulta de URL não é adicionado ao mapa http.request.url.query nestes casos:

  • Se um caractere = não estiver presente em um par de chave/valor

    Exemplo:

    URL: https://www.example.com/path?no_key"

    Nesse caso, o elemento de string de consulta no_key não está presente no mapa http.request.url.query.

  • Se o lado esquerdo do caractere = estiver vazio (a chave não está especificada)

    Exemplo: URL: https://www.domain.com/path?=no_value

    Nesse caso - o elemento de string de consulta no_value não está presente no mapa http.request.url.query.

Se o lado direito do caractere = estiver vazio - o valor desse par de chave/valor será uma string vazia ''.

http.request.cookies

Um mapa contendo cookies de solicitação HTTP, analisados no cabeçalho de solicitação "Cookie", conforme chamado em RFC-6265, em que a chave é um nome de cookie e o valor é o valor de cookie correspondente. Se o cabeçalho de solicitação "Cookie" não estiver presente na solicitação, esse mapa estará vazio.

Exemplos

Uma solicitação HTTP/1.1 de entrada se parece com esta (linha e cabeçalhos da solicitação):

GET /category/some_category?action=search&query=search+terms&filters[]=5&features[]=12 HTTP/1.1
Accept-Encoding: gzip, deflate, br
Cookie: cookie_a=1; cookie_b=foo
Host: www.domain.com
User-Agent: Browser Foo/1.0
X-Forwarded-For: 1.2.3.4, 5.6.7.8
X-Forwarded-For: 9.10.11.12

Em seguida, as variáveis disponíveis para regras seriam preenchidas com dados dessa solicitação da seguinte forma: (os dados para variáveis estruturadas são mostrados no formato JSON)

http.request.url.path: "/category/some_category"
 
http.request.url.query: {
  "action": ["search"],
  "query": ["search terms"],
  "filters[]": ["5", "12"]
}
 
http.request.headers: {
  "Accept-Encoding": ["gzip, deflate, br"],
  "Cookie": ["some_cookie=1; another_cookie=foo"],
  "Host": ["www.domain.com"],
  "User-Agent": ["Browser Foo/1.0"],
  "X-Forwarded-For": ["1.2.3.4, 5.6.7.8", "9.10.11.12"]
}
 
http.request.cookies: {
  "cookie_a": ["1"],
  "cookie_b": ["foo"]
}

Veja alguns exemplos de como poderíamos fazer a correspondência dessa solicitação:

  • Se quiséssemos fazer a correspondência das solicitações com o domínio "www.domain.com" e caminhos de URL que começam com "/category/", usaríamos uma condição como esta:

    all(http.request.headers[(i 'Host')] eq 'www.domain.com', http.request.url.path sw '/category')
  • Para fazer a correspondência das solicitações em que o caminho do URL é exatamente "/category/some_category" ou o elemento de consulta de solicitação "action=search"

    any(http.request.url.path eq '/category/some_category', http.request.url.query['action'] eq 'search')
  • Para fazer a correspondência das solicitações que têm um elemento de string de consulta chamado "query" com o valor "search terms" (após a eliminação do escape do URL)

    http.request.url.query['query'] eq 'search terms'
  • Para corresponder às solicitações que têm o cookie "cookie_a", mas não têm o cookie "cookie_c":

    all('cookie_a' in (http.request.cookies), 'cookie_c' not in (http.request.cookies))