Cet article vous amène à comprendre en détail la spécification de conception Open API

Ecrit devant :

La spécification OpenAPI (OAS) définit une spécification d'interface API RESTful standard, indépendante du langage, qui permet aux développeurs et aux systèmes d'exploitation de visualiser et de comprendre la fonctionnalité d'un service sans accès au code source, à la documentation ou à l'inspection du trafic réseau (à la fois. pratique pour les humains à apprendre et à lire, et il est également pratique pour les machines à lire). Lorsqu'un OAS est correctement défini, les développeurs peuvent comprendre et interagir avec des services distants avec une logique d'implémentation minimale.

De plus, l'outil de génération de documents peut utiliser la spécification OpenAPI pour générer la documentation de l'API, et l'outil de génération de code peut générer du code côté serveur et côté client, du code de test et d'autres cas d'utilisation dans divers langages de programmation.

insérez la description de l'image ici

arrière-plan

L'Open API, comme la page d'accueil, a toujours été la façade du produit, si l'Open API n'est pas standardisée, cela réduira le professionnalisme du produit. Dans le scénario cloud, de nombreux utilisateurs choisiront de créer leurs propres portails pour se connecter à l'Open API des produits cloud, ce qui nous pousse à construire un mécanisme Open API mature.

D'un point de vue commercial, il existe quelques principes directeurs pour nous guider dans l'amélioration du mécanisme Open API :

  • L'interface utilisée par la page frontale et l'interface fournie par l'Open API sont le même ensemble d'interfaces
  • Toute interface de page frontale doit avoir une API ouverte correspondante

Récemment, en raison de besoins commerciaux, le produit cloud CSB, j'ai participé à des besoins de recherche et développement pour ouvrir l'API ouverte au monde extérieur.Ce n'était pas difficile au début, car le mécanisme d'ouverture de l'API ouverte à l'intérieur d'Alibaba Cloud est très mature, et je pas besoin de le concevoir du tout, mais cette fois la demande est principalement Pour certains scénarios de déploiement indépendants, nous devons concevoir nous-mêmes un ensemble de spécifications, ce qui signifie que nous devons imposer certaines contraintes normatives sur Open API. D'un point de vue technique, Alibaba Cloud a de nombreuses normes ouvertes d'API pour notre référence.Certaines open source La documentation Open API du produit est également très complète.

Bref, d'une part, je vais prendre son essence, et d'autre part, je dois considérer la particularité de la forme de sortie de mes propres produits. Cet article tentera de discuter d'une spécification Open API appropriée autour de nombreux facteurs.

Considérations relatives à la conception d'une API ouverte

Que doit exactement réglementer une spécification Open API complète ?

Du point de vue de la conception, vous devez prendre en compte : la spécification de dénomination, la spécification de composition, la spécification de chemin, la spécification de paramètres d'entrée et de sortie, la spécification de type de données, la spécification de valeur de retour unifiée, la spécification de code d'erreur et la spécification de pagination.

Du point de vue de l'équipe, si le développement primaire et intermédiaire back-end et la R&D front-end de l'équipe ont suffisamment d'expérience pour comprendre et mettre en œuvre la spécification API formulée. En même temps, avec le flux de personnel, si cette spécification Open API peut être bien transmise.

Du point de vue de l'industrie, il est nécessaire de déterminer si le marché des produits qui fournissent une API ouverte est mature et si le style d'API peut déjà avoir une spécification correspondante.

D'un point de vue produit, le style d'API adapté à chaque produit est différent, et ce qui suit se concentrera sur ce point de vue.

Bref, la conception de l'Open API est difficile à conclure.Avant de présenter la spécification Open API que mon produit adopte finalement, je vais d'abord parler de quelques concepts familiers, comme reposant.

La guerre des spécifications reposante

Là où il y a des gens, il y aura des rivières et des lacs.

Il en est de même là où il y a du code.

Si vous êtes dans le cercle du code, vous devez avoir entendu parler de la spécification reposante :

  • CRUD doit être déclaré comme suit : POST, DELETE, PUT, PATCH, GET

  • Les verbes ne doivent pas apparaître et les verbes sont représentés uniformément par la méthode HTTP

  • Reflète l'abstraction des "ressources"

  • Utilisez pathVariable, queryParam, header, statusCode pour exprimer de nombreuses sémantiques métier

La spécification reposante semble belle, mais si vous essayez vraiment de l'implémenter, vous rencontrerez certainement des problèmes similaires :

  • En prenant l'interface de connexion utilisateur comme exemple, il est difficile de mapper ce type d'interface à l'ajout, la suppression, la modification et la requête de ressources
  • Prenons l'exemple de l'interrogation du taux d'erreur des requêtes d'interface au cours des 7 dernières heures. Les scénarios de requête complexes tels que graphQL nécessitent souvent une structure json, qui ne peut pas être obtenue par GET, et seul POST peut être transmis.

Sur cette base, la spécification reposante a progressivement des voix d'opposition :

  • Forcer toutes les choses à « ressourcer » va à l'encontre du bon sens du développement, et l'interface peut ne pas être mappée par simple ajout, suppression, modification et requête
  • La sémantique des requêtes complexes n'est pas nécessairement exprimable avec GET

De nombreux partisans du style reposant critiquent ces objections. Dans la communauté, il est inévitable que "ceux qui rejettent le style reposant soient principalement des architectes de bas niveau et des programmeurs front-end et back-end qui ne veulent pas faire C'est un problème humain de ne pas savoir concevoir. En même temps, reposant est sublimé : la récupération de paramètres complexes devrait être classée comme post dans la sémantique reposante, car ce comportement n'est pas le positionnement des ressources (GET), mais la récupération des ressources (POST)

Cela a évidemment stimulé les nerfs des adversaires du style reposant, et a dit avec dédain : Oh, stupides fondamentalistes reposants.

Je ne sais pas si vous êtes un partisan ou un adversaire du repos ? Ou, neutre.

Le débat de repos est terminé pour le moment, ce débat est purement fictif et les juges n'ont pas à s'en préoccuper. Peu importe comment vous regardez reposant, vous pouvez agir en tant que personne neutre dans ma discussion ci-dessous, sinon l'effet sera réduit de moitié.

ROA et RPC

La conception d'API n'a pas seulement une spécification de repos. D'un point de vue plus large, les styles de conception d'API courants peuvent en fait être divisés en

  • Conception orientée ressources, à savoir ROA (architecture orientée ressources)
  • Conception orientée processus, c'est-à-dire RPC (Remote Procedure Call)

Restful est un exemple typique de style ROA, tandis que le style RPC est relativement moins connu, mais en fait, la plupart des interfaces système peuvent être de style RPC, mais le concept de style RPC n'est pas bien connu.

En prenant le CRUD du module utilisateur comme exemple, comparez les deux styles suivants :

Style ROA

CRÉER UN UTILISATEUR (POST)

Request:
POST /users

{
    
    "name": "kirito", "age": 18}

Response:
HTTP 201 Created

{
    
    "id": 1, "name": "kirito", "age": 18}

Interroger les utilisateurs (GET)

Request:
GET /users/1

Response:
HTTP 200 OK

{
    
    "id": 1, "name": "kirito", "age": 18}

Interroger la liste des utilisateurs (GET)

Request:
GET /users

Response:
HTTP 200 OK

{
    
    [{
    
    "id": 1, "name": "kirito", "age": 18}], "next": "/users?offset=1"}

Créer/modifier un utilisateur (PUT)

Request:
PUT /users/1

{
    
    "name": "kirito", "age": 19}

Response:
HTTP 200 OK

{
    
    "id": 1, "name": "kirito", "age": 19}

Modifier l'utilisateur (PATCH)

Request:
PATCH /users/1

{
    
    "age": 20}

Response:
HTTP 200 OK

{
    
    "id": 1, "name": "kirito", "age": 20}

supprimer l'utilisateur (DELETE)

Request:
DELETE /users/1

Response:
HTTP 204 No Content

Le style ROA et la spécification restful décrivent la même chose.Pour faciliter la comparaison avec l'interface de style RPC, voici quelques points remarquables de l'exemple ci-dessus :

  • Utilisez les codes de réponse HTTP (200, 201, 204) pour compléter le mappage entre la sémantique HTTP et la sémantique métier, et les flux d'exception apparaissent également 404, 401, etc. (Pour des considérations d'espace, cet article n'introduit pas de flux d'exception)
  • La partie PATCH modifie la ressource, et le corps de la requête est le contenu de la partie modifiée ; PUT crée/modifie la ressource, et le corps de la requête est le contenu entier de la nouvelle ressource
  • id est un localisateur de ressources, tandis que l'âge et le nom sont des attributs

Style RPC

CRÉER UN UTILISATEUR (POST)

Request:
POST /user/createUser

{
    
    "name": "kirito", "age": 18}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 18}}

interroger l'utilisateur (POST)

Request:
POST /user/getUser

{
    
    "id": 1}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 18}}

Interroger la liste des utilisateurs (POST)

Request:
POST /user/listUsers

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "user": [{
    
    "id": 1, "name": "kirito", "age": 18}], "next": "/user/listUsers?offset=1"}}

modifier l'utilisateur (POST)

Request:
POST /user/modifyUser

{
    
    "id": 1, "name": "kirito", "age": 19}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 19}}

Modifier le nom d'utilisateur (POST)

Request:
POST /user/modifyUserAge

{
    
    "id": 1, "age": 20}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 20}}

supprimer l'utilisateur (DELETE)

Request:
POST /user/deleteUser

{
    
    "id": 1}

Response:
{
    
    "code": 0, "message": ""}

Le style RPC n'est pas comme le style ROA reposant. Il existe certaines conventions et spécifications. Chaque système d'entreprise a des différences lors de sa mise en œuvre. Par conséquent, ce n'est que l'expérience personnelle de l'auteur. J'espère que les lecteurs pourront rechercher un terrain d'entente tout en réservant les différences :

  • user est le nom du module, pas besoin d'utiliser la forme plurielle comme le style ROA
  • Utilisez une structure verbe-objet claire au lieu de mapper CRUD à la méthode HTTP, la méthode HTTP utilise POST de manière uniforme et les scénarios de requête peuvent également utiliser GET
  • La valeur de retour contient du code, un message et des données pour mapper l'état de la réponse et les informations de réponse. Généralement, vous pouvez définir vous-même le code d'état du code. Dans cet article, 0 est utilisé pour indiquer que la demande a abouti. Le message est uniquement significatif lorsque la réponse commerciale échoue, et les données représentent le résultat de la réponse commerciale

Comment choisir RPC et ROA doit être décidé en fonction de la situation commerciale du produit lui-même. Il existe les principes directeurs suivants :

  • Pour les API avec une logique métier complexe, le style RPC doit être utilisé lorsque de simples descriptions d'ajout, de suppression, de modification et de requête ne peuvent pas être utilisées.
  • Si la norme industrielle de l'entreprise nécessite une API ou une ROA de style reposant pour répondre aux besoins de l'entreprise, le style ROA doit être utilisé.

AWS adopte principalement le style RPC, Azure et Google adoptent principalement le style ROA (repos), et Alibaba Cloud OpenAPI prend en charge à la fois RPC et ROA, avec RPC comme méthode principale.

Bien que la spécification soit innocente, j'ai vu de nombreux "pièges" dans la pratique du style ROA :

  • Nécessite d'abord des ressources, c'est-à-dire des ressources de conception d'abord, puis une interface de conception, qui a des exigences plus élevées pour le processus de développement logiciel
  • Mauvais cas de conception ROA 1 : lors du traitement de la requête HTTP de la méthode DELETE, les serveurs d'applications tels que tomcat n'autorisent pas le corps de la requête à être transporté par défaut et doivent être explicitement activés, ce qui entraîne un échec de la suppression. (Ce cas est un problème pour le concepteur. Pour les scénarios de suppression complexes, il ne doit pas être mappé sur DELELE, mais doit être remplacé par POST. DELETE ne doit pas comporter de corps de requête.)
  • Mauvais cas de conception ROA 2 : les paramètres transportés dans le chemin reposant peuvent causer des problèmes de correspondance réguliers, tels que l'utilisation par erreur de la boîte aux lettres comme paramètre de chemin, ou le problème de conflit de correspondance de chemin à plusieurs niveaux (ce cas est le problème du concepteur, scénario de requête complexe, il ne doit pas être mappé sur GET, mais doit être remplacé par POST, seuls les localisateurs de ressources doivent apparaître dans le chemin et les attributs ne doivent pas être transportés)
  • Lorsque le code de réponse est 404, il est difficile de distinguer si le chemin réel n'existe pas ou si la ressource n'existe pas
  • Il n'est pas propice aux scénarios où le routage et le transfert doivent être configurés, comme la connexion à une passerelle

CSBLa spécification Open API espère répondre aux exigences suivantes :

  • Lors du développement et de la conception d'interfaces à l'arrière, il y a une idée de conception claire, de sorte que vous ne soyez pas empêtré de savoir si une interface est implémentée avec POST ou GET, et vous n'avez pas besoin de passer trop de temps sur l'abstraction des ressources (cela ne signifie pas que les ressources n'ont pas besoin d'être conçues)
  • Lorsque le front-end développe l'interface d'accueil, il peut rapidement coopérer avec le back-end et faciliter l'encapsulation de l'interface front-end
  • Lorsque les utilisateurs se connectent à l'Open API, le style général est cohérent et les modules sont clairs

Pour résumer, en termes de sélection de style de conception, je prévois d'adopter la spécification de conception RPC. Pour résumer les avantages du style RPC :

  • La conception d'API est moins difficile et facile à mettre en œuvre
  • La plupart des produits de couche IAAS matures d'Alibaba Cloud utilisent la spécification RPC
  • Adapté aux scénarios commerciaux complexes

Un exemple détaillé d'un document d'interface RPC

créer un service

paramètres de requête

numéro de série Nom chinois du champ Nom anglais du champ type de données requis illustrer
1 nom nom chaîne Oui Afficher un nom
2 protocole protocole chaîne Oui Feuilles : http/grpc/webservice
3 l'équilibrage de charge kg chaîne Oui Valeur d'énumération : random/roundrobin
4 type amont TypeAmont chaîne Oui Valeur d'énumération : fixe/découverte
5 liste de nœuds nœuds déployer Non Requis quand amontType=fixe, exemple : [{"host": "1.1.1.1", "port": "80", "weight": "1"}]
6 identifiant source ID d'origine chaîne Non
7 Nom du service Nom du service chaîne Non Le nom dans le registre, requis lorsque uploadType=discovery
8 Description du service description chaîne Non
9 ID-passerelle gatewayId chaîne Oui

paramètre de retour

numéro de série Nom chinois du champ Nom anglais du champ type de données illustrer
1 Code de réponse code entier 0
2 message de réponse message chaîne
3 résultat de la réponse données chaîne renvoyer l'identifiant du service

exemple de demande

POST /service/createService

Request:
{
    
    
  "name": "httpbin",
  "protocol": "http",
  "lb": "random",
  "upstreamType": "fixed",
  "nodes": [
    {
    
    
      "host": "httpbin.org",
      "port": "80",
      "weight": "1"
    }
  ],
  "gatewayId": "gw-1qw2e3e4"
}

Response:
{
    
    
  "code": 0,
  "message": "",
  "serviceId": "s-1qw2e3e4"
}

Convention de nommage des API

  • L'API doit utiliser l'anglais avec une orthographe correcte et se conformer aux normes grammaticales, y compris les conventions du singulier et du pluriel, des temps et de la langue

  • Il ne peut pas y avoir plusieurs API avec des significations similaires mais aucune différence réelle de fonction, comme la présence de /user/getUser et /user/describeUser en même temps

  • Habitudes linguistiques : le pinyin est interdit

  • Les règles de nommage des scénarios courants suivants sont fixes

    • Les paramètres de type datetime doivent être nommés XxxxTime. Par exemple:CreateTime
  • Spécification commune du nom d'opération

    • create:créer
    • modify:changement
    • delete:supprimer
    • get: Obtenir les détails d'une seule ressource
    • list: obtenir la liste des ressources
    • establishRelation: Créer une relation de ressource
    • destroyRelation: détruire la relation de ressource

Résumer

Lorsque nous discutons de ces normes, nous devons continuer à réfléchir à leur objectif et à leur contexte. Dans un environnement de production réel, nous devons faire face à une grande quantité de code et à une demande croissante. Nous devons donc trouver un moyen d'améliorer l'efficacité de la collaboration et la fiabilité du code pour nous assurer que nous pouvons mieux répondre aux besoins des clients.

L'utilisation de l'interface POST est une méthode d'interface courante et standard , qui peut minimiser les coûts de communication entre les utilisateurs et les développeurs, réduire le besoin de compréhension supplémentaire de l'interface et également éviter l'interface "GET" qui peut entraîner des problèmes de sécurité.

De plus, cette méthode d'interface standardisée peut également permettre une meilleure maintenabilité, car toutes les interfaces du système suivent la même norme, les développeurs peuvent facilement comprendre et modifier ces interfaces, afin de localiser et de résoudre le problème.

En résumé, utiliser l'interface POST est une pratique rassurante et potentiellement rentable. Pour les développeurs, cette approche standardisée leur permettra de suivre plus facilement les spécifications de conception d'interface et de réduire la charge de travail inutile pour mieux accomplir les tâches de travail. Pour le système et l'entreprise, cette approche peut également améliorer l'efficacité du système, réduire les coûts de maintenance et de positionnement des erreurs, rendant ainsi toute l'équipe plus efficace et compétitive.

Je suppose que tu aimes

Origine blog.csdn.net/m0_68089732/article/details/129849511
conseillé
Classement