Cómo configurar dinámicamente la inyección de fallas usando OpenNJet

NGINX evoluciona hacia la nube nativa, todo en  OpenNJet


Las interrupciones del servicio causadas por cortes de energía pueden tener graves consecuencias comerciales, por lo que es importante construir, ejecutar y probar sistemas resilientes. La resiliencia de un sistema proviene de la resiliencia de sus partes: cada parte del sistema es capaz de manejar una cierta cantidad de errores o fallas. Ya sea que se trate de indisponibilidad posterior del servicio, latencia de la red o problemas de disponibilidad de datos, los sistemas distribuidos están llenos de requisitos no funcionales implícitos para el manejo de errores correspondiente.

¿Qué falla la inyección?

La inyección de fallas es una técnica complementaria a las pruebas de software y se utiliza para mejorar el rendimiento y la resiliencia del software. Mientras que los métodos de prueba habituales verifican el comportamiento correcto del software, la inyección de fallas evalúa el comportamiento correcto del software mediante fallas inyectadas deliberadamente.
La inyección de fallas HTTP admite la cancelación de solicitudes HTTP de servicios posteriores y/o el retraso de las solicitudes de proxy. Una regla de falla debe tener un retraso, una cancelación o ambas. Se pueden inyectar una o más fallas al reenviar solicitudes HTTP al destino especificado en la ruta. Las estrategias de inyección de errores se aplican al tráfico HTTP del cliente.
Las especificaciones de retraso se utilizan para inyectar retrasos en la ruta de reenvío de solicitudes.
La especificación de cancelación se utiliza para cancelar una solicitud antes de tiempo y devolver un código de error preespecificado.

tipo

Hay tres tipos principales de inyección de fallas. Solo se permite configurar un tipo en la misma ubicación:
  • Retraso: solo inyecta fallas de retraso. Una vez que expire el tiempo de retraso, inicie una solicitud de conexión ascendente.
  • Abortar: solo inyecta fallas de cancelación, recibe la solicitud del cliente, devuelve directamente el código de estado inyectado al cliente y finaliza la solicitud.
  • Retraso + Abortar: inyecta falla de retraso y aborta falla al mismo tiempo. Retraso primero. Una vez transcurrido el tiempo de retraso, devuelve directamente el código de estado establecido por el aborto al cliente, finaliza la solicitud y ya no inicia una solicitud de conexión ascendente. .

Instrucción (fault_inject):

directiva de inyección de falla

Introducción de parámetros:
parámetro tipo Requerido ilustrar
tipo = {tipo} cadena retrasar, abortar, retrasar_abortar uno de los tres retrasos: retrasar el tipo de inyección abortar: abortar el tipo de inyección delay_abort: retrasar + abortar el tipo de inyección
demora_duración={duración} cadena Sí (se requieren retraso y retraso_abort) tiempo de retardo, 1h/1m/1s/1ms, debe ser >=1ms
código_estado={código} uint Sí (se requieren cancelar y retrasar_abort) El código establece el código de retorno de la inyección, [200, 600].
porcentaje_retraso={pct} uint Opcional, predeterminado 100 (100%) Establezca el porcentaje de solicitudes retrasadas inyectadas, el valor predeterminado es 100%, rango: [1, 100], por ejemplo: 1 significa 1%, 10 significa 10%
porcentaje_aborto={pct} uint Opcional, predeterminado 100 (100%) Establezca el porcentaje de solicitudes de cancelación inyectadas, el valor predeterminado es 100%, rango: [1, 100], por ejemplo: 1 significa 1%, 10 significa 10%

Abortar el tipo de inyección

Función: de acuerdo con el porcentaje de probabilidad establecido, la solicitud de visita devuelve directamente el código de estado especificado
Introducción de parámetros:
 
parámetro tipo Requerido ilustrar
código_estado={código} uint El código establece el código de retorno de la inyección, [200, 600].
porcentaje_aborto={pct} uint Opcional, predeterminado 100 (100%) Establezca el porcentaje de solicitudes de cancelación inyectadas, el valor predeterminado es 100%, rango: [1, 100], por ejemplo: 1 significa 1%, 10 significa 10%

1.3.2 Tipo de inyección retardada

Función: De acuerdo con el porcentaje de probabilidad establecido, la solicitud de acierto se retrasará durante el tiempo de duración establecido para iniciar una solicitud al canal ascendente.
Introducción de parámetros:
parámetro tipo Requerido ilustrar
demora_duración={duración} cadena tiempo de retardo, 1h/1m/1s/1ms, debe ser >=1ms
porcentaje_retraso={pct} uint Opcional, predeterminado 100 (100%) Establezca el porcentaje de solicitudes retrasadas inyectadas, el valor predeterminado es 100%, rango: [1, 100], por ejemplo: 1 significa 1%, 10 significa 10%

Tipo de inyección retardada+abortar

Función: De acuerdo con el porcentaje de probabilidad establecido, la solicitud de acierto se retrasará durante el tiempo de duración establecido para iniciar una solicitud al canal ascendente.
Introducción de parámetros:
parámetro tipo Requerido ilustrar
demora_duración={duración} cadena tiempo de retardo, 1h/1m/1s/1ms, debe ser >=1ms
código_estado={código} uint El código establece el código de retorno de la inyección, [200, 600].
porcentaje_retraso={pct} uint Opcional, predeterminado 100 (100%) Establezca el porcentaje de solicitudes retrasadas inyectadas, el valor predeterminado es 100, rango: [1, 100], por ejemplo: 1 significa 1%, 100 significa 100%
porcentaje_aborto={pct} uint Opcional, predeterminado 100 (100%) Establezca el porcentaje de solicitudes de aborto inyectadas, el valor predeterminado es 100, rango: [1, 100], por ejemplo: 1 significa 1%, 100 significa 100%

Inyección de fallas dinámicas de API declarativa en OpenNJet

URL de la interfaz

 GET  http://{ip:port}/config/2/config/http_dyn_fault_inject

 PUT  http://{ip:port}/config/2/config/http_dyn_fault_inject

El formato Json es el siguiente:

{
    "servers": [
        {
            "listens": [
                "0.0.0.0:92"
            ],
            "serverNames": [
                ""
            ],
            "locations": [
                {
                    "location": "/",
                    #此处type可为下面四种
                    #abort   这个表示中止注入
                    #delay   这个表示延迟注入
                    #delay_abort  这个表示延迟+中止注入
                    #none    这个表示取消故障注入或者不设置故障注入
                    
                    "fault_inject_type": "delay_abort", #如果该值为none,则其他参数取值无意义
                    
                    "delay_percentage": 100,      #延迟故障注入百分比,如果是abort类型,该值无意义
                    "abort_percentage": 100,      #中止故障注入百分比,如果是delay类型,该值无意义
                    "status_code": 405,         #故障注入状态码,如果是delay类型,该值无意义
                    "delay_duration": "5s",     #故障注入延迟时间,如果是abort类型,该值无意义
                    "locations": [
                        {
                            "location": "/demo",
                            "fault_inject_type": "none", #子location /demo 故障注入类型
                        }
                    ]
                }
            ]
        }
    ]
}

Archivo de configuración de OpenNJet

load_module modules/njt_http_dyn_fault_inject_module.so; #使用动态故障注入功能需要load该模块

Compilación del módulo

El módulo de inyección de fallas se compila estáticamente y se habilita mediante el control de macro NJT_HTTP_FAULT_INJECT.
El módulo de inyección de fallas dinámicas de la API declarativa adopta una compilación dinámica y debe cargarse mediante la instrucción loadmodule.

prueba de funcionamiento

Prueba del protocolo HTTP1.1

cancelar prueba de inyección de falla

Configuración:
server {
        listen       80 ;
        server_name  localhost;

        location / {
          fault_inject type=abort  status_code=405 abort_percentage=100;
          proxy_next_upstream_tries 0;      #关闭重试
          proxy_next_upstream_timeout 0;    #关闭超时
          proxy_pass http://back/;
        }
     }

Resultados de la prueba:

El acceso http1.1 del navegador devolverá inmediatamente 405, de la siguiente manera:
 
Registro de OpenNJet:  
2023/07/17 17:04:51 [debug] 13179#0: *35  fault injet abort 405, client: 192.168.40.205, server: localhost, request: "GET / HTTP/1.1", host: "192.168.40.136"

prueba de inyección de falla retardada

Configuración:
server {
        listen       80 ;
        server_name  localhost;

        location / {
          fault_inject type=delay  delay_duration=10s delay_percentage=100;
          proxy_next_upstream_tries 0;      #关闭重试
          proxy_next_upstream_timeout 0;    #关闭超时
          proxy_pass http://back/;
        }
     }

Resultados de la prueba:

Acceda al navegador http1.1, espere 10 segundos y regrese a la página de acceso exitoso, de la siguiente manera:
 
 
Registro de OpenNJet:
#等待10s 后正常处理并成功返回页面
2023/07/17 17:02:04 [debug] 13015#0: *28  fault inject start deleay, client: 192.168.40.205, server: localhost, request: "GET / HTTP/1.1", host: "192.168.40.136"
2023/07/17 17:02:14 [debug] 13015#0: *28  fault njet delay success, client: 192.168.40.205, server: localhost, request: "GET / HTTP/1.1", host: "192.168.40.136"
2023/07/17 17:02:14 [debug] 13015#0: *28  fault inject delay timer clean while closing request, client: 192.168.40.205, server: localhost, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8008/", host: "192.168.40.136"

prueba de inyección de fallas delay_abort

Configuración:
server {
        listen       80 ;
        server_name  localhost;

        location / {
          fault_inject type=delay_abort  delay_duration=10s status_code=405 delay_percentage=100;
          proxy_next_upstream_tries 0;      #关闭重试
          proxy_next_upstream_timeout 0;    #关闭超时
          proxy_pass http://back/;
        }
     }
Resultados de la prueba:
Cuando el navegador accede a http1.1, devolverá 405 directamente después de esperar 10 segundos, de la siguiente manera:
Registro de OpenNJet:
# 先delay等待10s
2023/07/17 16:57:48 [debug] 11894#0: *26  fault inject start deleay, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/1.1", host: "192.168.40.136"
2023/07/17 16:57:58 [debug] 11894#0: *26  fault njet delay success, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/1.1", host: "192.168.40.136"

#直接返回 405 abort
2023/07/17 16:57:58 [debug] 11894#0: *26  fault injet abort 405, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/1.1", host: "192.168.40.136"
2023/07/17 16:57:58 [debug] 11894#0: *26  fault inject delay timer clean while closing request, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/1.1", host: "192.168.40.136"

Prueba del protocolo HTTP2

cancelar prueba de inyección de falla

Configuración:

server {
        listen       81 ssl http2;
        server_name  192.168.40.136;
        ssl_certificate                 /root/bug/njet1.0/mycert/www.tmlake.xn--com-7m0aa+3.pem;
        ssl_certificate_key             /root/bug/njet1.0/mycert/www.tmlake.xn--com-7m0aa+3-key.pem;

        location / {
          fault_inject type=abort  status_code=405 abort_percentage=100;
          proxy_next_upstream_tries 0;      #关闭重试
          proxy_next_upstream_timeout 0;    #关闭超时
          proxy_pass http://back/;
        }
     }
Resultados de la prueba:
 
Cuando el navegador accede a http2, inmediatamente devuelve 405, de la siguiente manera:
 
Registro de OpenNJet:
#直接返回405
2023/07/17 16:43:54 [debug] 11894#0: *8  fault injet abort 405, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", host: "192.168.40.136:81"

prueba de inyección de falla retardada

Configuración:
server {
        listen       81 ssl http2;
        server_name  192.168.40.136;
        ssl_certificate                 /root/bug/njet1.0/mycert/www.tmlake.xn--com-7m0aa+3.pem;
        ssl_certificate_key             /root/bug/njet1.0/mycert/www.tmlake.xn--com-7m0aa+3-key.pem;

        location / {
          fault_inject type=delay  delay_duration=10s delay_percentage=100;
          proxy_next_upstream_tries 0;      #关闭重试
          proxy_next_upstream_timeout 0;    #关闭超时
          proxy_pass http://back/;
        }
     }
Resultados de la prueba:
 
Acceda al navegador http2, espere 10 segundos y acceda exitosamente a la página, de la siguiente manera:
 
Registro de OpenNJet:
#delay 10s后成功访问到页面
2023/07/17 16:42:03 [debug] 11783#0: *4  fault inject start deleay, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", host: "192.168.40.136:81"
2023/07/17 16:42:13 [debug] 11783#0: *4  fault njet delay success, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", host: "192.168.40.136:81"
2023/07/17 16:42:13 [debug] 11783#0: *4  fault inject delay timer clean while sending to client, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", upstream: "http://127.0.0.1:8008/", host: "192.168.40.136:81"

prueba de inyección de fallas delay_abort

Configuración:
 
server {
        listen       81 ssl http2;
        server_name  192.168.40.136;
        ssl_certificate                 /root/bug/njet1.0/mycert/www.tmlake.xn--com-7m0aa+3.pem;
        ssl_certificate_key             /root/bug/njet1.0/mycert/www.tmlake.xn--com-7m0aa+3-key.pem;

        location / {
          fault_inject type=delay_abort  delay_duration=10s status_code=405 delay_percentage=100;
          proxy_next_upstream_tries 0;      #关闭重试
          proxy_next_upstream_timeout 0;    #关闭超时
          proxy_pass http://back/;
        }
     }
Resultados de la prueba:
 
El navegador accede a http2 y devuelve 405 después de esperar 10 segundos, de la siguiente manera:
 
Registro de OpenNJet:
#先delay 10s
2023/07/17 16:39:10 [debug] 11598#0: *2  fault inject start deleay, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", host: "192.168.40.136:81"
2023/07/17 16:39:20 [debug] 11598#0: *2  fault njet delay success, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", host: "192.168.40.136:81"

#再直接返回405 abort
2023/07/17 16:39:20 [debug] 11598#0: *2  fault injet abort 405, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", host: "192.168.40.136:81"
2023/07/17 16:39:20 [debug] 11598#0: *2  fault inject delay timer clean, client: 192.168.40.205, server: 192.168.40.136, request: "GET / HTTP/2.0", host: "192.168.40.136:81"

Pruebas dinámicas de inyección de fallos de API declarativa en OpenNJet

Configuración estática de OpenNJet

...
load_module modules/njt_http_dyn_fault_inject_module.so;     #load 动态模块so
...

http{
...

    upstream back{
       server 127.0.0.1:8008;
    }

     server{
                listen 8008;
                location / {
                        index 8008.html;
                        add_header Set-Cookie route=8008;
                }
     }

     #8009 为普通server, 返回8008.html文件
     server{
                listen 8009;
                location / {
                        proxy_pass http://back/;
                }
     }
...
}

Ejecutar solicitud de obtención

curl http://192.168.40.136:8081/config/2/config/http_dyn_fault_inject | jq
{
  "servers": [
    {
      "listens": [
        "0.0.0.0:8009"
      ],
      "serverNames": [
        ""
      ],
      "locations": [
        {
          "location": "/",
          "fault_inject_type": "none",         #8009 静态默认为none,即没有设置故障注入,
                                               #相关参数没有意义
          "delay_percentage": 100,
          "abort_percentage": 100,
          "status_code": 200,
          "delay_duration": ""
        }
      ]
    },
    {
      "listens": [
        "0.0.0.0:8008"
      ],
      "serverNames": [
        ""
      ],
      "locations": [
        {
          "location": "/",
          "fault_inject_type": "none",
          "delay_percentage": 100,
          "abort_percentage": 100,
          "status_code": 200,
          "delay_duration": ""
        }
      ]
    }
  ]
}

Acceso al navegador

Sin demora, regrese a la página de resultados inmediatamente

Ejecutar solicitud de venta y modificar

curl -X PUT http://192.168.40.136:8081/config/2/config/http_dyn_fault_inject -d '@json.txt'
json.txt es el siguiente:
{
  "servers": [
    {
      "listens": [
        "0.0.0.0:8009"
      ],
      "serverNames": [
        ""
      ],
      "locations": [
        {
          "location": "/",
          "fault_inject_type": "delay_abort", #修改为delay_abort, delay 5s, 然后返回405
          "delay_percentage": 100,
          "abort_percentage": 100,
          "status_code": 405,
          "delay_duration": "5s"
        }
      ]
    },
    {
      "listens": [
        "0.0.0.0:8008"
      ],
      "serverNames": [
        ""
      ],
      "locations": [
        {
          "location": "/",
          "fault_inject_type": "none",
          "delay_percentage": 100,
          "abort_percentage": 100,
          "status_code": 200,
          "delay_duration": ""
        }
      ]
    }
  ]
}

volver a conseguir

curl http://192.168.40.136:8081/config/2/config/http_dyn_fault_inject | jq
{
  "servers": [
    {
      "listens": [
        "0.0.0.0:8009"
      ],
      "serverNames": [
        ""
      ],
      "locations": [
        {
          "location": "/",
          "fault_inject_type": "delay_abort",     #与put 修改一致,说明修改成功
          "delay_percentage": 100,
          "abort_percentage": 100,
          "status_code": 405,
          "delay_duration": "5s"
        }
      ]
    },
    {
      "listens": [
        "0.0.0.0:8008"
      ],
      "serverNames": [
        ""
      ],
      "locations": [
        {
          "location": "/",
          "fault_inject_type": "none",
          "delay_percentage": 100,
          "abort_percentage": 100,
          "status_code": 200,
          "delay_duration": ""
        }
      ]
    }
  ]
}

Acceso real a través del navegador

El efecto real es esperar 5 segundos y devolver 405, lo cual es consistente con las expectativas.

Registro de fondo


#日志也显示delay 5s后,返回abort 405
2023/07/20 15:55:17 [debug] 30305#0: *12  fault inject start deleay,
client: 192.168.40.205, server: , request: "GET / HTTP/1.1", host: "192.168.40.136:8009"
2023/07/20 15:55:22 [debug] 30305#0: *12  fault njet delay success, client: 192.168.40.205,
 server: , request: "GET / HTTP/1.1", host: "192.168.40.136:8009"
2023/07/20 15:55:22 [debug] 30305#0: *12  fault injet abort 405, client: 192.168.40.205, server: , 
request: "GET / HTTP/1.1", host: "192.168.40.136:8009"
2023/07/20 15:55:22 [debug] 30305#0: *12  fault inject delay timer clean while closing request, 
client: 192.168.40.205, server: , request: "GET / HTTP/1.1", host: "192.168.40.136:8009"=

Para casos más prácticos, consulte njet.org.cn


OpenNJet   se basó por primera vez en la bifurcación básica de NGINX1.19 y evolucionó de forma independiente. OpenNJet tiene las características de alto rendimiento, estabilidad y fácil expansión. También resuelve los problemas de larga data de NGINX, como la dificultad en la configuración dinámica y las funciones de administración que afectan negocio. Como motor subyacente, OpenNJet utiliza el mecanismo de carga dinámica para implementar diferentes formas de productos, como puerta de enlace API, proxy de mensajes, proxy entrante y saliente, equilibrio de carga, WAF, etc. En la arquitectura nativa de la nube, OpenNJet no solo proporciona funciones de puerta de enlace de comunicación norte-sur, sino que también proporciona nuevas características como comunicación este-oeste en la red de servicios, secuestro de tráfico transparente, disyuntor, telemetría e inyección de fallas.

    El grupo de correo
Gitee lo invita a abrir código y construir juntos: https://njet.org.cn/

Multado con 200 yuanes y más de 1 millón de yuanes confiscados You Yuxi: La importancia de los documentos chinos de alta calidad El servidor de migración de núcleo duro de Musk Solon para JDK 21, ¡los hilos virtuales son increíbles! ! ! El control de congestión de TCP salva Internet Flutter para OpenHarmony está aquí El período LTS del kernel de Linux se restaurará de 6 años a 2 años Go 1.22 solucionará el error de la variable del bucle for Svelte construyó una "nueva rueda" - runas Google celebra su 25 aniversario
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/6606114/blog/10114624
Recomendado
Clasificación