Am o astfel de configurare pe Ubuntu
Browser --> HAProxy --> Server backend
Serverul backend este o aplicație web ASP.NET Core.
Funcționează 99,9% din timp, cu excepția cazului în care este încărcat un fișier binar (POST simplu cu date de formular în mai multe părți), caz în care primesc eroarea:
System.IO.IOException: Sfârșitul neașteptat al fluxului, este posibil ca conținutul să fi fost deja citit de o altă componentă.
la Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
la Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
la Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.DrainAsync(Stream stream, ArrayPool`1 bytePool, Nullable`1 limit, CancellationToken cancellationToken)
la Microsoft.AspNetCore.Http.Features.FormFeature.InnerReadFormAsync(CancellationToken cancellationToken)
la Microsoft.AspNetCore.Antiforgery.DefaultAntiforgeryTokenStore.GetRequestTokensAsync(HttpContext httpContext)
la Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext)
la Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)
la Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(Invocator ResourceInvoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
la Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(invocator ResourceInvoker)
la Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
la Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Deci, am încercat să investighez de ce.
Am încercat direct backend-ul ASP.NET Core, funcționează.
Așa că am înregistrat datele primite în backend și am constatat că, dacă o fac direct, primesc antetele cererii așteptate și apoi fișierul încărcat în corp.
Apoi am înregistrat datele primite în backend prin HAProxy și jumătate din date lipsesc.
ie. primele date văzute de backend par să fie
04 E2 22 FC 60 FF 2B E1 BF 85 D2 75 F9 44 94 86
dar aceștia sunt octeții aproximativ la jumătatea fișierului meu, care este de 25.126 de octeți. Nu văd deloc informații despre antet.
Sunt pregătit să accept că înregistrarea mea este imperfectă și nu neapărat exactă. Se pare că, într-un fel, cererea a fost împărțită în două sau un buffer a fost completat și apoi scris.
Care ar putea fi problema?
global
chroot /var/lib/haproxy
log /dev/log local0 informații
socket statistici /run/haproxy/admin.modul sock 660 nivel admin
statistici timeout 30s
utilizator haproxy
utilizatorii grupului
demonul
lua-load /home/user/haproxy-mapping.lua
ssl-default-bind-ciphers ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:! DSS:!AESCCM
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
tune.ssl.default-dh-param 2048
implicite
jurnal global
modul http
timeout connect 30000
timeout client 50000
server timeout 50000
opțiune forwardfor
opțiunea http-server-close #have încercați și http-keep-alive
frontend httpfront
modul http
lega *:80
schema de redirecționare codul https 301 dacă !{ ssl_fc }
frontend web_front_end
bind *:443 ssl crt /home/.....file.pem
modul http
log /var/lib/haproxy/dev/log local0 informații
# Limitare de rata
tip stick-table dimensiune ip 100k expiră 600s magazin http_req_rate(60s) #store până la 100k cereri pentru 60s, vezi dacă peste 60s există mai mult de 600
http-request track-sc0 src
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 600 }
# Asigurați-vă că avem o stare curată pentru început
http-request del-header X-SERVER-SNI
# Setați valoarea concatenată a valorii SNI la un antet temporar
http-request set-header X-SERVER-SNI haproxy.%[ssl_fc_sni] dacă { ssl_fc_sni -m găsit }
# Setați valoarea antetului la o variabilă la nivel de tranzacție
http-request set-var(txn.fc_sni) ssl_fc_sni #hdr(X-SERVER-SNI) dacă { hdr(X-SERVER-SNI) -m găsit }
#utilizați codul Lua pentru a determina la ce backend să trimiteți
use_backend %[lua.legacy_new_backend]
backend backendnodes_1_https
echilibru roundrobin
opțiune forwardfor
server node1 127.0.0.1:446 ssl verify none sni var(txn.fc_sni)