This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
StyloBot Release Series: Architecture de la Sidecar
Monday, 01 June 2026
StyloBot's moteur de détection est ASPM SK1NET Core. Cet article explique comment ce moteur se connecte aux passerelles GoMSC3 NodeMNK4js applicationsMST5 et tout autre stack par l'entremise d'un sidecar gRPC MST6 un type Go SDKMSR7 et un plugin CaddyMSL8 sans qu'aucun de ces consommateurs n'ait besoin de savoir quoi que ce soit sur les MSSK9NET internesMSS10
L'article 5 de la Loi sur l'immigration et le statut des réfugiés
github.com/scottgal/stylobot-goSDK, legithub.com/scottgal/caddy-stylobotplugin, et leMostlylucid.BotDetection.Sidecarle contenant sera publié prochainement. Tout ce qui suit décrit la surface qu’ils exposeront.
StyloBot Release Series
- Comportement, Non identité: pourquoi StyloBot modele les clients de façon comportementale
- Behaviour-Aware ASP.NET UI: le serveur- la surface rendue pour les applications .NET
- Trouver et rétablir une croissance sans limites dans les services longs-Running .NET: la discipline de fiabilité qui maintient le moteur borne dans la production
- Behaviour-Aware TypeScript UI: ExpressM SK1 Fastify, et composants de navigateur
- L'architecture de la Sidecar: cet article
- Apprentissage pour devenir plus rapide: le système d'apprentissage adaptatif , quatre- mémoire de niveauM SK3 et cache des verdicts
- Étudier ce qui ne va pas se tenir: la discipline de vérification : un fichier BDF conduit à la régressionM SK2 charge, et à l'étalonnage
- StyloExtract - un convertisseur HTML d'apprentissage local à Markdown: la couche de marquage HTML→ qui se joigne au détecteur , le bug lucidVIEW du fauteuil roulant qui a capté l’image
Pourquoi une voiture latérale
Un proxy inverse est le lieu évident pour faire fonctionner la détection des bots: il se trouve devant tout , voit toutes les demandes , et peut bloquer avant que n’ait été lancée une application quelconqueM SK3 Cette logique se maintient jusqu’à ce que vous demandez quelle application devrait être utilisée de faire différemment basée sur qui fait la demande. Une passerelle qui bloque tout à fait est une passerelle ; ce dont la plupart des applications ont réellement besoin, c'est un verdict qu'elles peuvent appliquer de multiples façons à la fois: tourner l'APIM SK3 personnaliser l'interface de l'U.I.
Le modèle de la chariot sidecar distingue les deux préoccupations. La passerelle demeure rapide et sans étatM SK1 La chariote sidecar maintient l’état de session, les ancrages archétypiques , l’État de dériveMSC4 et le cache des verdicts qui rendent la détection exacte MST5le type archetypique MST6le modèle d’ancrageM ST7 le système d’apprentissage à niveau perM st8le cache des vérdicts sur les empreintes digitales M ST9 et les quatre niveauxM S T 10 sont couverts par Apprentissage pour devenir plus rapide). Les deux communiquent sur le réseau local (le même hôte ou le même Pod) de sorte que l’étape rondeM SK3est de microsecondes à un seul MSC4millisecondes de chiffresMSC5 non pas celle d’un appel API éloignéMSM6msMMSC7 Ce budget de latence est ce qui rend la détection des demandes par SMC8réclamation pratique en tout
Ce n’est pas un nouveau modèle. Envoyé proxy Ce n’est pas le cas pour les services -mesh concerns (mTLSM SK2 retries, circuit breakingMSC4 Dapr a-t-il pour l'État et la pub/subM SK1 le Collecteur de télémétrie ouverte utilise-t-il pour la télémétrie?. Linkerd, Consul ConnectM SK2 et AWS App Mesh suivent tous le même modèle?
Pourquoi ne pas l’impliquer simplement comme bibliothèque?
La solution de rechange consiste à compiler la détection directement dans la passerelle . Pour Go, c'est-à-dire une réimplementation pure -Go ou une liaison CGo avec une bibliothèque C
Ce n’est pas réaliste pour un moteur de cette complexité. StyloBot a des détecteurs 49 organisés sur quatre exécutions les ondes (Les vagues subséquentes ne feront feu que lorsque les signaux antérieurs le justifient ; un certificat de crédibilité M SK2une tentative d’affaissement déclenche différents détecteurs qu’un crawl Googlebot ). Il est maintenu par session Vektors de chaîne Markov Dans un espace dimensionnel, une chaîne Markov est simplement un modèle de probabilité par rapport à la dernière chose que cette séance a faite. Détection communautaire de Leiden sur ces vecteurs: un graphique - algorithme de fragmentation qui regroupe les sessions comportant des comportements similaires, c'est ainsi que StyloBot repère le réseau d'un bot même lorsque les séances individuelles semblent parfaitesMSC3 Et il persiste tout cela à SQLite entre demandesM SK4 Cet état a besoin d'une vieillesse indépendante~. Il ne peut pas remarrer avec le processus Node ou se détruire quand la passerelle recharge sa configuration~.
Une voiture de côté permet à chaque composant de faire ce qui est bon à :
graph TD
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef async fill:none,stroke:#a855f7,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
classDef store fill:none,stroke:#f59e0b,stroke-width:2px
GW["Gateway<br/>Caddy / YARP / nginx"]:::input
SD["StyloBot Sidecar · ASP.NET Core<br/>gRPC :5090 · REST :5091<br/>≤50ms per Detect RPC"]:::async
APP["Upstream Application<br/>Node / Go / ASP.NET<br/>reads req.stylobot.verdict"]:::good
DB[("SQLite<br/>sessions · signatures · reputation")]:::store
GW --> SD
SD <--> DB
GW --> APP
La passerelle appelle le sidecar, injecte le résultat sous forme de titres HTTP , et bloque optionnellement. L'application en amont lit les titres et agit sur le verdictM SK3 Le sidecar maintient l'état entre les demandesMSC4 Le pipeline de détection fonctionne à l'intérieur du seul appel gRPC et son résultat se propage sous la forme de neuf titresHTTPMNK5
L'automobile de sidecar
Mostlylucid.BotDetection.Sidecar est un ASP minimal.Procédure de base NET. Il n’a pas d’interface M SK2 aucun service de fichier statique , et aucune routage au-delà des points finals gRPC et REST M SK4 Il démarre le moteur de détection complet et expose deux portsMSC5
- :5090: HTTPM SK1 pour les clients gRPC ( passerelles, Proxies d'acheminement
- :5091: HTTP /1.1 pour les clients de RESTM SK2 re-exportation
/api/v1/*Les points de départ sont les suivants :
gRPC
gRPC est un cadre d’appels de procédure à distance haute performance, développé par Google. Les tampons du protocole (protobuf) en tant que format de câble : un codage binaire compact qui est plus rapide à serialiser et plus petit sur le câble que JSONM SK3 gRPC fonctionne par HTTPMSC4 ce qui signifie qu'il obtient des multiplexings (multiple requests over one TCP connectionMNK6 for freeMRK7
L'interface est définie dans un .proto file. De ce fichier, les générateurs de code, produisent des articles sur le client et le serveur typés dans n'importe quelle langue supportée. .proto les fichiers, de sorte que toute langue avec une mise en œuvre gRPC peut appeler le sidecar: Go, NodeM SK2 Python , Rust
L'interface gRPC
Le service comporte trois PCR:
service DetectionService {
rpc Detect(DetectRequest) returns (DetectResponse);
rpc DetectBatch(DetectBatchRequest) returns (DetectBatchResponse);
rpc RenderWidget(RenderWidgetRequest) returns (RenderWidgetResponse);
}
Detect est le par-route chaude de la demande . Méthode d'acheminement , routeM SK3 entêtesMSC4 IP éloignéMNK5 et données optionnelles sur les empreintes digitales TLSMRK6 Il gère le pipeline des ondes MNK7seulement les détecteurs que la requête MMK8 garantit ses signaux MGK9 met à jour le vecteur de session MBK10 donne un score contre l'entrepôt de réputation MDK11 et retourne un verdictMBK12
DetectBatch exécute plusieurs demandes séquentiellement. Utilisé pour le replay du log et l'analyse hors ligneM SK1 non par-utilisation de la passerelle de demande .
RenderWidget accepte une chaîne de modèle liquide, un verdict facultatifM SK1 et une clé- carte de valeur des variables additionnelles , puis rend le serveur de templateMSC4 côté et retourne HTMLMNK5 C'est ainsi que les appelants non MST6NET produisent un botMSP7aware HTML sans mettre en place un processus distinct de renderingMSV8 détails dans la section RenderWidget ci-dessousMSSK9
Ce qui se passe à l'intérieur d'un appel de détection
Un glossaire rapide avant le diagramme, puisque ces noms apparaîtront:
- Tableau noir: un sac de valeur par - clé de demande
request.ip.is_datacenter,detection.useragent.confidence). Les détecteurs envoient des signaux à celui-ci ; les détectrices subséquentes dans la même vague les lisent. Il n'existe que pendant une seule demandeM SK3 PII brut PSK4IPMSC5 String UAMNK6 demeure dans le contexte de la demande et ne tombe jamais sur le plancher blackboard. - Contexte Http synthétique: un peuplementM SK1in
HttpContextle service gRPC est construit à partir des champs de demande proto. Le moteur de détection a été conçu pour ASP.NET middleware et attend d’être lu parHttpContext; synthétiser un permet de faire fonctionner le même moteur indépendamment à l'intérieur d'un appel gRPC - Contributions de détection / Données générées: les détecteurs de sorties ( le signal écrit des deltas de confiance
sequenceDiagram
participant GW as Gateway (Caddy)
participant SD as gRPC Service
participant ORC as BlackboardOrchestrator
participant DET as Detectors (up to 49, 4 waves)
participant DB as SQLite
GW->>SD: Detect RPC { method, path, headers, remoteIp }
SD->>ORC: DetectAsync(syntheticHttpContext)
ORC->>DET: Wave 0 - Identity + ContentSequence
ORC->>DET: Wave 1 - Fast path <1ms: UA, Header, IP, Heuristic ...
ORC->>DET: Wave 2 - Session vectors, Behavioural waveform
ORC->>DET: Wave 3 - Slow path: DNS, advanced fingerprinting
DET-->>ORC: DetectionContributions (signals, confidence deltas)
ORC->>DB: update session vector and reputation score
DB-->>ORC: ok
ORC-->>SD: AggregatedEvidence { botProbability, riskBand, ... }
SD-->>GW: DetectResponse { isBot, riskBand, recommendedAction, ... }
L’ensemble du pipeline se déroule à l’intérieur d’un seul appel gRPC. Il n’y a pas de travail async après que la réponse retourne.
Le SDK Go
Le code de passerelle dans Go ne peut pas importer l’ASP.NET sidecar. Ce qu’il peut faire, c’est l’appeler par gRPCM SK2 Le SDK Go (github.com/scottgal/stylobot-go) fournit une interface type qui cache complètement les types de protobuf générés des appelants.
Pourquoi le SDK cache les types de protobuf
Protobuf-le code généré est verbose et a un API inhabituel . Les enums sont représentés comme des integers. Les chaînes apparaissent sous les noms de proto-enums bruts M SK3RISK_BAND_HIGH, non "High"). Les noms de champ sont camelCase dans certains générateurs et serpentM SK1case dans d’autres. L’exposition des types de proto dans votre API public signifie que vos appelants doivent comprendre tout cela .
Le SDK traduit une fois à la limite (enums proto en chaînes canoniques,structures proto en structures Go simplesM SK2 et les appelants ne le voient jamaisMSC3
// the only interface you depend on: no proto imports required
type Client interface {
Detect(ctx context.Context, req DetectRequest) (*Verdict, error)
DetectBatch(ctx context.Context, reqs []DetectRequest) ([]*Verdict, error)
RenderWidget(ctx context.Context, req RenderRequest) (*RenderResponse, error)
Close() error
}
DetectRequest et Verdict sont des structures de Go simples:
type DetectRequest struct {
Method string
Path string
Headers map[string]string
RemoteIP string
Protocol string // "http" or "https"; defaults to "https" if empty
TLS *TLSInfo
}
type Verdict struct {
IsBot bool
BotProbability float32
Confidence float32
BotType string // "AiBot", "Scraper", "GoodBot", ...
BotName string
RiskBand string // "VeryLow", "Low", "Elevated", "Medium", "High", "VeryHigh"
RecommendedAction string // "Allow", "Throttle", "Challenge", "Block"
ThreatScore float32
ThreatBand string
ProcessingTimeMs float32
DetectorsRun int32
Reasons []Reason
}
Création d'un client et exploitation de la détection:
import (
stylobot "github.com/scottgal/stylobot-go"
"context"
"time"
)
client, err := stylobot.NewClient(
"localhost:5090",
stylobot.WithTimeout(50 * time.Millisecond),
stylobot.WithAPIKey(os.Getenv("SB_API_KEY")),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
verdict, err := client.Detect(ctx, stylobot.DetectRequest{
Method: r.Method,
Path: r.URL.RequestURI(),
RemoteIP: r.RemoteAddr,
Headers: extractHeaders(r),
Protocol: "https",
})
if err != nil {
// fail open: log and continue
log.Printf("stylobot detect failed: %v", err)
return next(w, r)
}
if verdict.RecommendedAction == "Block" {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
Connexion lente et sécurité de démarrage
grpc.NewClient create a client channel but does not establish a TCP connection immediately. The connection happens on the first RPC callM SK1 This means your gateway process starts successfully even if the sidecar hasn't started yet. The first request after startup may fail (and should be handled with failureMST4openMSP5 but every subsequent request works normally once the side car is runningMSC6
Cela diffère des clients HTTP, où vous connectez habituellement lors de la création. gRPC Documentation pour aller couvre le cycle de vie en détail.
Interaction de temps-out
WithTimeout sur NewClient définit un délai par -appel par défaut appliqué à chacun des appels Detect appel. Si votre code d'appel M SK1ou un outil de middleware tel que le plugin Caddy ) dérive déjà une date limite- contexte lié à la demande incombantMSC4 le SDK s'applique quels que soient les délais qui expirent le plus tôt. WithTimeout de NewClient et laisser le plug-in le contrôler. Pour l'utilisation autonome (un gestionnaire appelant directement le SDK ), la mettre en place NewClient comme il est indiqué ci-dessus.
Le plugin Caddy
Caddy est un serveur Web basé sur Go- et un proxy inverse avec HTTPS automatisé. xcaddy pour construire un binaire Caddy personnalisé qui inclut vos plugins, produisant un seul self-contained binary with no runtime dependency on shared libraries . Ceci diffère de nginxM SK3s dynamic module system MSC4.so files loaded at runtime). Le plugin StyloBot (github.com/scottgal/caddy-stylobot) enregistre un gestionnaire de middleware qui appele le Go SDK à chaque demande
Configuration du Caddyfile:
{
order stylobot before respond
}
:80 {
stylobot {
endpoint localhost:5090 # gRPC host:port of the sidecar
timeout 50ms # per-request deadline; fails open on expiry
# on_block 503 # optional: change the block status code (default: 403)
}
reverse_proxy upstream:3000
}
Le plugin injecte neuf titres de verdict sur chaque demande transmise:
| Intitulé | Champ de source MSC2 |
|---|---|
X-StyloBot-IsBot |
isBot (boolM SK1 |
X-StyloBot-Probability |
botProbability (0.0-1.0) |
X-StyloBot-Confidence |
confidence (0.0-1.0) |
X-StyloBot-BotType |
eM SK1g. AiBot, Scraper, GoodBot |
X-StyloBot-BotName |
eM SK1g. GPTBot, Googlebot |
X-StyloBot-RiskBand |
VeryLow ... VeryHigh |
X-StyloBot-Action |
Allow / Throttle / Challenge / Block |
X-StyloBot-ThreatScore |
numérique |
X-StyloBot-ThreatBand |
None ... Critical |
Demande de savoir où isBot=true et Action=Block sont arrêtés à la passerelle avec un 403 et ne parviennent jamais jusqu’à l’amont de l’embranchement. Throttle ou Challenge recommandation) est transmis avec tous les neuf titres intacts . C'est la division prévue: le passage de port agit sur des blocs dursM SK3 l'avant-marché agit en fonction des nuances
on_block modifie le code de situation utilisé lorsque la passerelle bloque (defaultM SK1 403). Set on_block 503 supprimer la logique de réessai dans les scrapers qui traitent 403 comme retryable.
Que fait le middleware à chaque demande
flowchart TD
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef async fill:none,stroke:#a855f7,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
A["1. Strip inbound X-StyloBot-* headers"]:::input
B["2. context.WithTimeout(r.Context(), 50ms)"]:::input
C["3. sbClient.Detect(ctx, DetectRequest)"]:::async
D{error?}
E["log warn - fail open<br/>forward unchanged"]:::good
F["4. injectHeaders<br/>X-StyloBot-IsBot, Probability, Confidence,<br/>BotType, BotName, RiskBand, Action,<br/>ThreatScore, ThreatBand"]:::input
I["next.ServeHTTP - forward to upstream<br/>with all verdict headers injected"]:::good
A --> B --> C --> D
D -->|yes| E --> I
D -->|no| F --> I
Étape 1, têtes d'entrée de bande . Un client qui connaît X-StyloBot-* les noms de l’en-tête pourraient eux-mêmes -injecter un verdict favorable et le faire survivre à la défaillance -pathe ouverte
Étape 2, Délai de mise en œuvre du contexteM SK1 Le temps d'arrêt est dérivé de r.Context() utilisation context.WithTimeout (qui prend une durée relative context.WithDeadline Il faut un temps absolu; ils sont équivalents ). D'après r.Context() au lieu de context.Background() est le point clef: si le client se déconnecte avant que l'appel gRPC ne soit terminé , l'annulation se propage et la voiture de sidecar cesse de traiter tôt
Étapes 3 et 4, détection et injection Les neuf champs de verdict sont devenus neuf X-StyloBot-* headers. Les en-têtes sont réglés avant la vérification des blocs. styloBotMiddleware({ mode: 'headers' }) pour toutes les demandes non bloquées-. Demandes où isBot=true et recommendedAction=Block sont retournés comme 403 à la passerelle; tout le reste avance avec les titres de verdict complets attachés
La mise en œuvre:
// from sdk/caddy/stylobot.go
func (s *StyloBot) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
for _, name := range stylobotHeaders {
r.Header.Del(name)
}
ctx, cancel := context.WithTimeout(r.Context(), s.timeout)
defer cancel()
verdict, err := s.sbClient.Detect(ctx, sb.DetectRequest{
Method: r.Method,
Path: r.URL.RequestURI(),
RemoteIP: ExtractIP(r),
Protocol: r.Proto,
Headers: ExtractHeaders(r),
})
if err != nil {
s.logger.Warn("stylobot detect failed, failing open", zap.Error(err))
return next.ServeHTTP(w, r)
}
injectHeaders(r, verdict)
if verdict.IsBot && s.OnBlock > 0 && verdict.RecommendedAction == "Block" {
http.Error(w, "Forbidden", s.OnBlock)
return nil
}
return next.ServeHTTP(w, r)
}
Établissement avec xcaddy
Les plugins Caddy doivent être compilés dans le binaire en utilisant xcaddy. Le Dockerfile dans les essais d’intégration montre le modèle
# from tests/integration/caddy-sidecar/Dockerfile
FROM caddy:2-builder AS builder
WORKDIR /build
COPY sdk/caddy/ caddy-plugin/
COPY sdk/go/ go/
WORKDIR /build/caddy-plugin
RUN xcaddy build \
--with github.com/scottgal/caddy-stylobot=/build/caddy-plugin \
--with github.com/scottgal/stylobot-go=/build/go
FROM caddy:2
COPY --from=builder /build/caddy-plugin/caddy /usr/bin/caddy
COPY tests/integration/caddy-sidecar/Caddyfile /etc/caddy/Caddyfile
La directive de remplacement xcaddy
Le plugin's go.mod contient:
replace github.com/scottgal/stylobot-go => ../go
Cela indique à la chaîne d’outils Go " quand vous voyez stylobot-go, utiliser le répertoire local au lieu de télécharger du proxy module." Il fonctionne pour go build et go test dans le répertoire des plugins.
xcaddy crée un nouveau module Go temporaire pour sa construction. Ce module ne hérite pas replace directives du plugin's go.mod. Sans la seconde --with argument, xcaddy essaiera de télécharger stylobot-go de pkg.go.dev (dans les cas où il n’est pas encore publié
L'article 5 de la Loi sur l'immigration et le statut des réfugiés --with module=path argument est l'équivalent natif de xcaddy's d'un replace directive: il représente un chemin de module vers un répertoire local au moment de la constructionM SK1 Les deux modules locaux doivent être désignés explicitement.
RenderWidget: Modèles liquides sur gRPC
RenderWidget est un RPC gRPC sur l'automobile qui accepte une chaîne de modèle liquide, la rend avec le contexte de détection , et retourne HTMLM SK2 Cela permet à tout appelant (Go proxyMSC4 Node SSR layerMST5 batch pipelineMSP6 produce botMSSK7aware HTML without running a separate render process
Formulaires sur les liquides
Liquide est un langage de templat créé par Shopify, utilisé par les thèmes de Shopify+, Jekyll+M SK2 Pages GitHub+, et bien d'autres systèmes+ . Ses propriétés clés=: sécuritaire à exploiter avec l'utilisateur+MSC6+templates fournies+MNK7+sans exécution arbitraire du code+MRK8+faible pour les développeurs non--+pour écrire+MEK10+et largement comprise+MSEK11+ Utilise StyloBot Fluid.Core, une performance élevée -une mise en œuvre NET de Liquid, pour rendre un serveur de templates
Mise en œuvre de l’automobile sidecar:
// from src/Mostlylucid.BotDetection.Sidecar/Services/DetectionGrpcService.cs
private static readonly FluidParser Parser = new(); // static, shared, compiled templates cached
public override async Task<Proto.RenderWidgetResponse> RenderWidget(
Proto.RenderWidgetRequest request, ServerCallContext context)
{
if (!Parser.TryParse(request.Template, out var template, out var error))
return new Proto.RenderWidgetResponse { Success = false, Error = error };
var ctx = new TemplateContext();
if (request.Verdict is { } v)
{
ctx.SetValue("isBot", v.IsBot);
ctx.SetValue("botProbability", (double)v.BotProbability);
ctx.SetValue("botType", v.BotType);
ctx.SetValue("botName", v.BotName);
ctx.SetValue("riskBand", v.RiskBand.ToString());
ctx.SetValue("recommendedAction", v.RecommendedAction.ToString());
ctx.SetValue("threatScore", (double)v.ThreatScore);
ctx.SetValue("threatBand", v.ThreatBand.ToString());
}
foreach (var kv in request.Vars)
ctx.SetValue(kv.Key, kv.Value);
var html = await template.RenderAsync(ctx);
return new Proto.RenderWidgetResponse { Html = html, Success = true };
}
Fluid.Core entretient un cache interne compilé de templates. FluidParser est statique et partagée par tous les appels gRPC.
Le node StyloBotGrpcClient.renderWidget() exemple et la référence complète de la variable template sont dans le Article TypeScript SDK.
En appelant de Go:
rendered, err := client.RenderWidget(ctx, stylobot.RenderRequest{
Template: `{% if isBot %}<p class="warning">Bot: {{ botType }}</p>{% endif %}`,
Verdict: verdict,
Vars: map[string]string{"locale": "en-GB"},
})
if err == nil && rendered.Success {
fmt.Fprint(w, rendered.HTML)
}
La syntaxe du modèle est identique si vous appelez RenderWidget de Go, Node, ou utiliser <sb-widget> dans le navigateur: le même moteur liquideM SK1 les mêmes noms de variables , la même voie de traduction.
Répartition de la production
graph LR
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef async fill:none,stroke:#a855f7,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
classDef store fill:none,stroke:#f59e0b,stroke-width:2px
INT([Internet])
CF["Cloudflare<br/>Tunnel / CDN"]
CA["Caddy<br/>+ caddy-stylobot"]:::input
SD["StyloBot Sidecar<br/>:5090 gRPC · :5091 REST"]:::async
WEB["Upstream App<br/>Node / Go / ASP.NET"]:::good
DB[("SQLite<br/>sessions · reputation")]:::store
INT --> CF --> CA
CA -->|"gRPC Detect<br/>≤50ms"| SD
SD <-->|"persist"| DB
CA -->|"X-StyloBot-* headers"| WEB
WEB -->|"/_stylobot/partials/render<br/>(widget rendering)"| SD
L'application en amont appelle directement le sidecar pour la représentation des widgets, parpasser la passerelle. La représentation des Widgets a besoin du contexte de verdict complet et se produit après que la demande ait déjà passé la détermination de la passerellesM SK2, il n'y a donc pas de double emploi de détection .
Défaut-ouvrir à chaque couche
Caddy plugin, Node middleware, and Go SDK all fail openM SK2 a sidecar timeout or error becomes a warning log and a permissive empty verdictMNK3 not a MMK4xxMRK5 The 50ms Caddy deadline is a coldMBK7start safety marginMKB8 the steadyMZK9state cost on a warm connection is 1–5msMGK11
Le commerce - qui encode ce message : bloque le trafic légitime parce que la détection n’est pas disponible est pire qu’un manque de trafic bot lors d’une panne d’autos secondaires.
La série de diffusion se poursuit. D’autres articles sur les dispositifs internes de détectionM SK1 Les modèles de déploiement , l’observabilité M SK3 et la topologie commerciale sont encore à venir. L’arc jusqu’à présentMSC5
- Comportement, Non identité: pourquoi la détection doit être comportementale , non identiqueM SK2 fondée
- Behaviour-Aware ASP.NET UI: transformer le verdict en Razor / politique de contrôleur
- Trouver et rétablir une croissance sans limites dans les services longs-Running .NET: la discipline de fiabilité qui maintient le moteur à l’aise dans un trafic soutenu
- Behaviour-Aware TypeScript UI: le même verdict apparaît dans ExpressM SK1 Fastify, et le navigateur
- L'architecture de la Sidecar ( cet article ): comment le moteur s'intègre à un stade quelconque par l'intermédiaire de gRPCM SK2 du Go SDK, et du Caddy plugin
Source de la mise en œuvre: github.comM SK1scottgal/stylobot. moteur en direct , tableaux de bord M SK2 et contrôles commerciaux à stylobot.net.