nginx grpc отказоустойчивость двойного прокси - PullRequest
0 голосов
/ 23 марта 2019

У меня есть служба GRPC, связанная с localhohst, и прокси nginx в качестве терминатора ssl на том же хосте (назовем его localhost-proxy).Кроме того, у меня есть еще один прокси-сервер nginx grpc, который я хочу использовать как балансировщик + отработка отказа, этот прокси перенаправляет на localhost-proxy.Проблема в конфигурации отработки отказа пограничного прокси - я не работаю, когда служба переключена, но локальный прокси работает.Когда служба выключена - localhost-proxy возвращает http статус 204 с заголовком grpc-status=14.Сначала моя конфигурация была:

#localhost-proxy

upstream direct {
  server localhost:50032;
  keepalive 10;
  keepalive_timeout 60s;
}

server {
  listen 50042 ssl http2;

  ssl_certificate     /etc/service/certs/internal_api_server/server.crt;
  ssl_certificate_key /etc/service/certs/internal_api_server/server.key;
  ssl_client_certificate /etc/service/certs/internal_api_server/clientCA.crt;
  ssl_verify_client on;

  access_log /var/log/nginx/direct.json grpc_json;

  location / {
    grpc_set_header X-Real-IP $client_ip;

    grpc_pass grpc://direct;
  }

  include /etc/nginx/errors.grpc.conf;
  default_type application/grpc;

}

edge-proxy:
upstream edge {
  server localhost-proxy1:50042;
  server localhost-proxy2:50042 backup;
  keepalive_timeout 60s;
}

server {
  listen 50052 ssl http2;

  ssl_certificate     /etc/service/certs/internal_api_server/server.crt;
  ssl_certificate_key /etc/service/certs/internal_api_server/server.key;
  ssl_client_certificate /etc/service/certs/internal_api_server/clientCA.crt;
  ssl_verify_client on;

  access_log /var/log/nginx/edge.json grpc_json;

    grpc_ssl_certificate /etc/service/certs/internal_api_client/client.crt;
    grpc_ssl_certificate_key /etc/service/certs/internal_api_client/client.key;
    grpc_ssl_trusted_certificate /etc/service/certs/internal_api_client/serverCA.crt;
    grpc_ssl_verify on;
    grpc_ssl_name api.server;
    grpc_set_header X-Real-IP $client_ip;
    grpc_connect_timeout 5s;
  location / {
    grpc_connect_timeout 5s;



    grpc_pass grpcs://edge;

  }

Но при такой конфигурации аварийное переключение работает, только если localhost-proxy выключен.Когда он работает - пограничный прокси просто возвращает ответ от localhost-proxy.Это не то, что я хочу.После того, как я добавил это в конфигурацию localhost-proxy:

...
    grpc_pass grpc://direct;
#from here 
    error_page 502 = /error502grpc;
  }

  location = /error502grpc {
        internal;
        default_type application/grpc;
        add_header grpc-status 14;
        add_header grpc-message "unavailable";
        return 502;
  }

Он начинает возвращать 502 для edge-proxy, когда служба недоступна.

После этого я попробовал это с помощью edge-прокси:

  1. Добавить grpc_next_upstream error timeout http_502 non_idempotent invalid_header; - без эффекта
  2. Добавить
  ...
  grpc_intercept_errors on;
  error_page 502 = @failover;
 }
 location @failover {
    grpc_pass grpcs://edge_failover;
 }

upstream edge_failover {
  server localhost-proxy2:50052;
  keepalive 10;
  keepalive_timeout 60s;
}

По-прежнему без эффекта - возвращается тот же 502 ответ.

Я хочу аварийное переключение на пограничном прокси, и оно должно меняться в восходящем направлении, когда служба не работает (независимо от локального прокси-сервера).Но сейчас я не знаю, как это сделать.

ОБНОВЛЕНИЕ

После некоторого исследования в журналах отработки отказа я обнаружил, что с последним вариантом (2) запрос действительно идетв отказоустойчивый бэкэнд, но - nginx пересылает только заголовки grpc, тело запроса (пакет GRPC DATA) не отправляется.Таким образом, аварийное переключение ожидает полного запроса, а затем пограничный прокси-сервер сбрасывает соединение по таймауту.

...