La nostra esperienza nella creazione di API Gateway

Alcune aziende, tra cui il nostro cliente, sviluppano il prodotto attraverso una rete di partner. Ad esempio, i grandi negozi online sono integrati con il servizio di consegna: ordini un prodotto e presto ricevi un numero di tracciamento per il pacco. Un altro esempio è quando acquisti un'assicurazione o un biglietto Aeroexpress insieme al tuo biglietto aereo.

Per questo, viene utilizzata un'API, che deve essere rilasciata ai partner tramite API Gateway. Abbiamo risolto questo problema. In questo articolo vi diremo i dettagli.

Dato: un ecosistema e un portale API con un'interfaccia in cui gli utenti sono registrati, ricevono informazioni, ecc. Dobbiamo creare un gateway API conveniente e affidabile. Nel processo, dovevamo fornire

  • registrazione,
  • Controllo della connessione API,
  • monitorare come gli utenti utilizzano il sistema finale,
  • contabilizzazione degli indicatori aziendali.

La nostra esperienza nella creazione di API Gateway

Nell'articolo parleremo della nostra esperienza nella creazione di API Gateway, durante la quale abbiamo risolto i seguenti compiti:

  • autenticazione utente,
  • autorizzazione dell'utente,
  • modifica della richiesta originaria,
  • richiesta delega,
  • post-elaborazione della risposta.


Esistono due tipi di gestione API:

1. Standard, che funziona come segue. Prima di connettersi, l'utente testa le funzionalità, quindi paga e incorpora nel suo sito. Molto spesso vengono utilizzati nelle piccole e medie imprese.

2. Gestione delle API B2B di grandi dimensioni, quando l'azienda decide per la prima volta di connettersi, diventa un partner dell'azienda con un obbligo contrattuale e quindi si connette all'API. E dopo che tutte le formalità sono state risolte, l'azienda riceve l'accesso ai test, supera i test ed entra in produzione. Ma questo non è possibile senza una decisione del management di connettersi.

La nostra esperienza nella creazione di API Gateway

La nostra soluzione

In questa parte parleremo della creazione di un gateway API.

Gli utenti finali del gateway API creato sono partner del nostro cliente. Abbiamo già i contratti necessari per ognuno di loro. Dovremo solo estendere la funzionalità contrassegnando l'accesso concesso al gateway. Di conseguenza, è necessario un processo di connessione e gestione controllato.

Naturalmente, è stato possibile prendere una soluzione già pronta per risolvere il problema della gestione delle API e creare in particolare un gateway API. Ad esempio, questo potrebbe essere Gestione API di Azure. Non ci andava bene, perché nel nostro caso avevamo già un portale API e un enorme ecosistema costruito attorno ad esso. Tutti gli utenti sono già stati registrati, hanno già capito dove e come possono ottenere le informazioni necessarie. Le interfacce necessarie esistevano già nel portale API, avevamo solo bisogno dell'API Gateway. In realtà, siamo impegnati nel suo sviluppo.

Ciò che chiamiamo API Gateway è una sorta di proxy. Anche qui abbiamo avuto una scelta: puoi scrivere il tuo proxy o puoi scegliere qualcosa di già pronto. In questo caso, abbiamo scelto la seconda strada e abbiamo scelto il pacchetto nginx + Lua. Perché? Avevamo bisogno di un software affidabile e testato che supporti il ​​ridimensionamento. Dopo l'implementazione, non volevamo controllare sia la correttezza della business logic che la correttezza del proxy.

Ogni server web ha una pipeline di elaborazione delle richieste. Nel caso di nginx, assomiglia a questo:

La nostra esperienza nella creazione di API Gateway

(schema da GitHub Lua Nginx)

Il nostro obiettivo era inserirci in questa pipeline in un punto in cui possiamo modificare la richiesta originale.

Vogliamo creare un proxy trasparente in modo che la richiesta rimanga funzionalmente uguale a come è arrivata. Controlliamo solo l'accesso all'API finale, aiutiamo la richiesta ad arrivarci. Nel caso in cui la richiesta fosse errata, l'API finale dovrebbe mostrare l'errore, ma non noi. L'unico motivo per cui possiamo rifiutare una richiesta è perché il client non ha accesso.

Esiste già per nginx estensione su prendere. Lua è un linguaggio di scripting, è molto leggero e facile da imparare. Pertanto, abbiamo implementato la logica necessaria utilizzando Lua.

La configurazione nginx (un'analogia con il percorso dell'applicazione), dove viene svolto tutto il lavoro, è abbastanza comprensibile. Degno di nota qui è l'ultima direttiva - post_action.

location /middleware {
      more_clear_input_headers Accept-Encoding;
      lua_need_request_body on;
      rewrite_by_lua_file 'middleware/rewrite.lua';
      access_by_lua_file 'middleware/access.lua';
      proxy_pass https://someurl.com;
      body_filter_by_lua_file 'middleware/body_filter.lua';
      post_action /process_session;
}

Considera cosa succede in questa configurazione:
more_clear_input_headers — cancella il valore delle intestazioni specificate dopo la direttiva.
lua_need_request_body - controlla se il corpo della richiesta originale deve essere letto o meno prima di eseguire le direttive rewrite/access/access_by_lua. Per impostazione predefinita, nginx non legge il corpo di una richiesta client e, se è necessario accedervi, questa direttiva dovrebbe essere impostata su on.
rewrite_by_lua_file - il percorso dello script, che descrive la logica per modificare la richiesta
access_by_lua_file — il percorso dello script, che descrive la logica che controlla l'accesso alla risorsa.
proxy_pass — url a cui verrà inoltrata la richiesta.
body_filter_by_lua_file — il percorso dello script, che descrive la logica per filtrare la richiesta prima di restituirla al client.
E, infine, post_azione - una direttiva ufficialmente non documentata, con la quale è possibile eseguire alcune altre azioni dopo che la risposta è stata data al client.

Successivamente, descriveremo in ordine come abbiamo risolto i nostri problemi.

Autorizzazione/autenticazione e richiesta modifica

Autorizzazione

Abbiamo creato l'autorizzazione e l'autenticazione utilizzando l'accesso tramite certificato. C'è un certificato radice. Ad ogni nuovo client del cliente viene generato il suo certificato personale, con il quale può accedere all'API. Questo certificato è configurato nella sezione server delle impostazioni nginx.

ssl on;
ssl_certificate /usr/local/openresty/nginx/ssl/cert.pem;
ssl_certificate_key /usr/local/openresty/nginx/ssl/cert.pem;
ssl_client_certificate /usr/local/openresty/nginx/ssl/ca.crt;
ssl_verify_client on;

modifica

Potrebbe sorgere una domanda lecita: cosa fare con un client certificato se improvvisamente vogliamo disconnetterlo dal sistema? Non riemettere certificati per tutti gli altri client.

Quindi ci siamo avvicinati senza problemi all'attività successiva: modificare la richiesta originale. La richiesta iniziale del cliente, in generale, non è valida per il sistema finale. Uno dei compiti è aggiungere le parti mancanti alla richiesta per renderla valida. Il punto è che i dati mancanti sono diversi per ogni cliente. Sappiamo che un cliente viene da noi con un certificato da cui possiamo prendere un'impronta digitale ed estrarre i dati del cliente necessari dal database.

Se a un certo punto devi disconnettere il cliente dal nostro servizio, i suoi dati scompariranno dal database e non potrà fare nulla.

Lavorare con i dati dei clienti

Avevamo bisogno di rendere la soluzione altamente disponibile, in particolare il modo in cui otteniamo i dati dei clienti. La difficoltà è che la fonte primaria di questi dati è un servizio di terze parti che non garantisce una velocità ininterrotta e sufficientemente elevata.

Pertanto, dovevamo garantire un'elevata disponibilità dei dati dei clienti. Come strumento, abbiamo scelto Nocciolache ci fornisce:

  • rapido accesso ai dati
  • la capacità di organizzare un cluster di più nodi con dati replicati su nodi diversi.

Abbiamo scelto la strategia più semplice per fornire i dati alla cache:

La nostra esperienza nella creazione di API Gateway

Il lavoro con il sistema finale avviene all'interno delle sessioni e c'è un limite al numero massimo. Se il cliente non ha chiuso la sessione, dovremo farlo.

I dati della sessione aperta provengono dal sistema finale e vengono inizialmente elaborati dal lato Lua. Abbiamo deciso di utilizzare Hazelcast per archiviare questi dati con un processo .NET. Poi, ad alcuni intervalli, controlliamo il diritto alla vita delle sessioni aperte e chiudiamo quelle marce.

Accesso a Hazelcast sia da Lua che da .NET

Non ci sono client Lua con cui lavorare con Hazelcast, ma Hazelcast ha un'API REST, che abbiamo deciso di utilizzare. Per .NET c'è cliente, attraverso il quale abbiamo pianificato di accedere ai dati Hazelcast sul lato .NET. Ma non c'era.

La nostra esperienza nella creazione di API Gateway

Durante l'archiviazione dei dati tramite REST e il recupero dei dati tramite un client .NET, vengono utilizzati diversi serializzatori e deserializzatori. Pertanto, è impossibile inserire i dati tramite REST, ma ottenerli tramite il client .NET e viceversa.

Se sei interessato, ti diremo di più su questo problema in un articolo separato. Spoiler - sullo schema.

La nostra esperienza nella creazione di API Gateway

Registrazione e monitoraggio

Il nostro standard aziendale per la registrazione tramite .NET è Serilog, tutti i registri finiscono in Elasticsearch e li analizziamo tramite Kibana. Vorrei fare qualcosa di simile in questo caso. L'unico cliente lavorare con Elastic su Lua, che è stato trovato, si è rotto al primo bisogno. E abbiamo usato Fluentd.

fluente - soluzione open source per fornire un singolo livello di registrazione delle applicazioni. Consente di raccogliere registri da diversi livelli dell'applicazione e quindi trasmetterli in un'unica origine.

API Gateway funziona in K8S, quindi abbiamo deciso di aggiungere un contenitore con fluentd nello stesso pody per scrivere i log sulla porta tcp aperta esistente fluentd.

Abbiamo anche esplorato come si comporterebbe fluente se non avesse alcuna connessione con Elasticsearch. Per due giorni, le richieste sono state continuamente inviate al gateway, i log sono stati inviati a fluentd, ma fluentd è stato bandito da IP Elastic. Dopo che la connessione è stata ripristinata, fluent ha superato perfettamente tutti i log in Elastic.

conclusione

L'approccio scelto per l'implementazione ci ha permesso di fornire un prodotto realmente funzionante all'ambiente di combattimento in soli 2.5 mesi.

Se un giorno ti capita di fare cose del genere, ti consigliamo di capire prima di tutto chiaramente quale problema stai risolvendo e quali risorse hai già. Sii consapevole delle complessità dell'integrazione con i sistemi di gestione delle API esistenti.

Comprendi tu stesso cosa svilupperai esattamente: solo la logica aziendale per l'elaborazione delle richieste o, come potrebbe essere nel nostro caso, l'intero proxy. Non dimenticare che tutto ciò che fai da solo deve essere accuratamente testato in seguito.

Fonte: habr.com

Aggiungi un commento