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?
tipo
-
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
parámetro | tipo | Requerido | ilustrar |
tipo = {tipo} | cadena | Sí | 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
parámetro | tipo | Requerido | ilustrar |
código_estado={código} | uint | Sí | 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
parámetro | tipo | Requerido | ilustrar |
demora_duración={duración} | cadena | Sí | 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
parámetro | tipo | Requerido | ilustrar |
demora_duración={duración} | cadena | Sí | tiempo de retardo, 1h/1m/1s/1ms, debe ser >=1ms |
código_estado={código} | uint | Sí | 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
prueba de funcionamiento
Prueba del protocolo HTTP1.1
cancelar prueba de inyección de falla
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:
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
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:
#等待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
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/;
}
}
# 先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/;
}
}
#直接返回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
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/;
}
}
#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
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/;
}
}
#先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
{
"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
Ejecutar solicitud de venta y modificar
{
"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
{
"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
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/