Docs Italia beta

Documenti pubblici, digitali.

4.5. Raccomandazioni sulla robustezza

Ai fini di garantire la responsività di una API è necessario impedire a singoli fruitori di esaurire la capacità di calcolo e di banda dell’erogatore. La tecnica comunemente utilizzata in questi casi è il rate limiting (anche noto come throttling). Il rate limit fornisce ad uno specifico fruitore un numero massimo di richieste soddisfacibili all’interno di uno specifico arco temporale (es. 1000 richieste al minuto). Un numero di richieste che superi il limite imposto provoca il rifiuto di ulteriori richieste da parte di uno specifico fruitore per un intervallo di tempo predeterminato.

Sulle politiche riguardanti il numero massimo di richieste e la relativa finestra temporale, e quelle riguardanti il tempo di attesa per nuove richieste (che può essere incrementato in caso di richieste reiterate, es. con una politica di aumento esponenziale) si lascia libertà agli implementatori previa un’analisi di carico massimo sopportabile dall’erogatore.

4.5.1. [RAC_ROBUSTEZZA_001] Segnalare raggiunti limiti di utilizzo

Gli erogatori di interfacce di servizio REST DEVONO segnalare eventuali limiti raggiunti con HTTP status 429 Too Many Requests.

Le API restituiscono in ogni risposta i valori globali di throttling tramite i seguenti header [1]:

  • X-RateLimit-Limit: limite massimo di richieste per un endpoint;
  • X-RateLimit-Remaining: numero di richieste rimanenti fino al prossimo reset;
  • X-RateLimit-Reset: numero di secondi che mancano al prossimo reset.

In caso di superamento delle quote, le API DEVONO restituire anche l’header:

Nel caso di SOAP non esistono regole guida standard per la gestione del rate limit e del throttling. Si POSSONO utilizzare gli stessi header e status code HTTP visti nel caso REST.

I fruitori DEVONO:

  • rispettare gli header di throttling;
  • rispettare l’header X-RateLimit-Reset quando restituisce il numero di secondi che mancano al prossimo reset, ed eventualmente gestire l’indicazione in timestamp unix;
  • rispettare l’header HTTP header Retry-After sia nella variante che espone il numero di secondi dopo cui riprovare, sia nella variante che espone la data in cui riprovare.

4.5.2. [RAC_ROBUSTEZZA_002] Segnalare il sovraccarico del sistema o l’indisponibilità del servizio

Gli erogatori DEVONO definire ed esporre un piano di continuità operativa segnalando il sovraccarico del sistema o l’indisponibilità del servizio con HTTP status 503 Service Unavailable Service Unavailable.

In caso di sovraccarico o indisponibilità, l’erogatore DEVE ritornare anche:

I fruitori DEVONO:

  • rispettare HTTP header Retry-After sia nella variante che espone il numero di secondi dopo cui riprovare, sia nella variante che espone la data in cui riprovare.

Per REST si DEVE prevedere nella descrizione delle API l’indicazione degli header relativi al rate limiting. L’utilizzo degli header HTTP in SOAP è fuori dagli obiettivi di WSDL come Interface Definition Language.

Esempio di specifica API REST per applicazione del throttling e segnalazione del sovraccarico o dell’indisponibilità:

openapi: 3.0.1
info:
   title: RESTrobustezza
   license:
      name: Apache 2.0 License
      url: http://www.apache.org/licenses/LICENSE-2.0.html
   version: "1.0"
paths:
   /resources/{id_resource}/M:
      post:
         description: M
         operationId: PushMessage_1
         parameters:
         - name: id_resource
           in: path
           required: true
           schema:
            type: integer
            format: int32
         requestBody:
            content:
               application/json:
                 schema:
                    $ref: '#/components/schemas/MType'
         responses:
            200:
               description: Esecuzione di M avvenuta con successo
               headers: &ratelimit_headers
                  X-RateLimit-Limit:
                     $ref: '#/components/headers/X-RateLimit-Limit'
                  X-RateLimit-Remaining:
                     $ref: '#/components/headers/X-RateLimit-Remaining'
                  X-RateLimit-Reset:
                     $ref: '#/components/headers/X-RateLimit-Reset'
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/MResponseType'
            404:
               description: Identificativo non trovato
               headers:
                  <<: *ratelimit_headers
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/ErrorMessage'
            400:
               description: Richiesta malformata
               headers:
                  <<: *ratelimit_headers
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/ErrorMessage'
            429:
               description: Limite di richieste raggiunto
               headers:
                  Retry-After:
                     description: Limite massimo richieste
                     schema:
                        type: string
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/ErrorMessage'
            500:
               description: Errore interno avvenuto
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/ErrorMessage'
components:
   headers:
      Retry-After:
         description: |-
            Retry contacting the endpoint \*at least\* after seconds.
            See https://tools.ietf.org/html/rfc7231#section-7.1.3
         schema:
            format: int32
            type: integer
      X-RateLimit-Limit:
         description: The number of allowed requests in the current period
         schema:
            format: int32
            type: integer
      X-RateLimit-Remaining:
         description: The number of remaining requests in the current period
         schema:
            format: int32
            type: integer
      X-RateLimit-Reset:
         description: The number of seconds left in the current period
         schema:
            format: int32
            type: integer
   schemas:
      MType:
         type: object
         properties:
            a:
               $ref: '#/components/schemas/AComplexType'
            b:
               type: string
      MResponseType:
         type: object
         properties:
            c:
               type: string
      AComplexType:
         type: object
         properties:
            a1s:
               type: array
            items:
               type: integer
               format: int32
            a2:
               type: string
      ErrorMessage:
         type: object
         properties:
            detail:
               description: |
                  A human readable explanation specific to this occurrence of the
                  problem.
               type: string
            instance:
               description: |
                 An absolute URI that identifies the specific occurrence of the
                 problem.
                 It may or may not yield further information if dereferenced.
               format: uri
               type: string
            status:
               description: |
                  The HTTP status code generated by the origin server for this
                  occurrence
                  of the problem.
               exclusiveMaximum: true
               format: int32
               maximum: 600
               minimum: 100
               type: integer
            title:
               description: |
                  A short, summary of the problem type. Written in english and
                  readable
                  for engineers (usually not suited for non technical stakeholders
                  and not localized);
               example: Service Unavailable
               type: string
            type:
               default: about:blank
               description: |
                 An absolute URI that identifies the problem type. When
                 dereferenced,
                 it SHOULD provide human-readable documentation for the problem
                 type
                 (e.g., using HTML).
               format: uri
               type: string

Di seguito, un esempio di chiamata alle API, con risposta nel caso in cui i limiti non siano ancora stati raggiunti e nel caso in cui invece il fruitore debba attendere per presentare nuove richieste.

Endpoint

https://api.ente.example/rest/nome-api/v1/resources/1234/M

  1. Request
POST /rest/nome-api/v1/resources/1234/M HTTP/1.1
Host: api.ente.example
Content-Type: application/json

{
"a": {
        "a1": [1, "...", 2],
        "a2": "RGFuJ3MgVG9vbHMgYXJlIGNvb2wh"
        },
"b": "Stringa di esempio"
}
  1. Response 200 con rate limiting
HTTP/1.1 200 OK
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 11
X-RateLimit-Reset: 44

{"c" :"risultato"}
  1. Response 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 60

{
"status": 429,
"title": "Hai superato la quota di richieste."
}
  1. Response 503 Service Unavailable
HTTP/1.1 503 Service Unavailable
Content-Type: application/problem+json
Retry-After: 3600

{
"status": 503,
"title": "Servizio in manutenzione."
}

4.5.3. [RAC_ROBUSTEZZA_003] Uniformità di Indicatori ed Obiettivi di Servizio

Gli SLI pubblicati DEVONO:

  • utilizzare unità di misure referenziate dal Sistema Internazionale (ad esempio, secondi o bytes);
  • indicare nel nome identificativo l’eventuale periodo di aggregazione con i soli suffissi s (secondi), m (minuti), d (giorni) e y (anni), utilizzando al posto dei mesi il numero di giorni;
  • includere la latenza aggiuntiva dovuta ad eventuali componenti infrastrutturali e di rete (ad esempio, proxy o gateway).

Gli SLO e gli SLA DOVREBBERO essere in relazione diretta con i valori associati (ad esempio, indicare il success rate anziché l’error rate), in modo che a valori più alti corrispondano risultati positivi.

Alcuni esempi di indicatori a cui è possibile associare degli obiettivi o degli accordi:

  • dimensione massima di ogni richiesta accettata. Le richieste più grandi possono essere rifiutate
  • latenza al 90º percentile. Utilizzata per calcolare la responsività
  • percentuale di minuti negli ultimi 30 giorni in cui l’interfaccia di servizio è stata disponibile
  • valori a 30 giorni del success rate, ovvero il numero di chiamate terminate con successo rispetto al numero totale di chiamate
  • Application Performance inDEX [3], indice su scala percentuale di qualità del servizio misurato a 30 giorni
  • tempo di risposta medio delle richieste totali (includendo le richieste rifiutate a causa del throttling) negli ultimi 30 giorni
  • throughput misurato in byte/s
[1]È in corso il processo di standardizzazione dell’utilizzo degli header indicati https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/
[2]Cfr. RFC 7231 prevede che l’header HTTP header Retry-After possa essere utilizzato sia in forma di data che di secondi
[3]Cf. https://en.wikipedia.org/wiki/Apdex