web-dev-qa-db-fra.com

Comment apporter une API définie par gRPC au navigateur Web

Nous voulons construire un gui Javascript/HTML pour nos microservices gRPC. Étant donné que gRPC n'est pas pris en charge du côté du navigateur, nous avons envisagé d'utiliser des sockets Web pour se connecter à un serveur node.js, qui appelle le service cible via grpc. Nous avons du mal à trouver une solution élégante pour le faire. En particulier, puisque nous utilisons des flux gRPC pour transmettre des événements entre nos micro-services ..__ Il semble que nous ayons besoin d’un deuxième système RPC, juste pour communiquer entre le serveur frontal et le serveur node.js. Cela semble être beaucoup de frais généraux et de code supplémentaire qui doit être maintenu.

Quelqu'un at-il de l'expérience dans ce domaine ou a-t-il une idée de la façon dont cela pourrait être résolu?

56
Oliver

Edit: Depuis le 23 oct.2018, le projet gRPC-Web est GA , ce qui pourrait être la manière la plus officielle/normalisée de résoudre votre problème. (Même si nous sommes déjà en 2018 ...;))

Depuis GA-Blog: "gRPC-Web, comme gRPC, vous permet de définir le" contrat "de service entre le client (Web) et les services gRPC dorsaux à l'aide de tampons de protocole. Le client peut ensuite être généré automatiquement. [ ...] "

Nous avons récemment créé gRPC-Web ( https://github.com/improbable-eng/grpc-web ) - un wrapper client et serveur de navigateur qui suit le protocole proposé par gRPC-Web. L’exemple de ce référentiel devrait constituer un bon point de départ.

Si vous utilisez Golang, il nécessite un proxy autonome ou un wrapper pour votre serveur gRPC. Le proxy/wrapper modifie la réponse pour conditionner les bandes-annonces dans le corps de la réponse afin qu'elles puissent être lues par le navigateur.

Divulgation: Je suis un mainteneur du projet.

24
Marcus

Malheureusement, il n'y a pas encore de bonne réponse pour vous.

La prise en charge des RPC en continu à partir du navigateur nécessite que les navigateurs prennent en charge les bandes-annonces HTTP2, et au moment de la rédaction de cette réponse, elles ne le sont pas.

Voir ce numéro pour la discussion sur le sujet.

Sinon, oui, vous auriez besoin d'un système de traduction complet entre WebSockets et gRPC. Peut-être que l'inspiration de grpc-gateway pourrait être le début d'un tel projet, mais cela reste un très long plan.

15
Nicolas Noble

Une implémentation officielle de grpc-web (beta) a été publiée le 23/03/2018. Vous pouvez le trouver à

https://github.com/grpc/grpc-web

Les instructions suivantes sont extraites du fichier README:

Définissez votre service gRPC:

service EchoService {
  rpc Echo(EchoRequest) returns (EchoResponse);

  rpc ServerStreamingEcho(ServerStreamingEchoRequest)
      returns (stream ServerStreamingEchoResponse);
}

Construisez le serveur dans la langue de votre choix.

Créez votre client JS pour passer des appels depuis le navigateur:

var echoService = new proto.grpc.gateway.testing.EchoServiceClient(
  'http://localhost:8080');

Faire un appel unaire RPC

var unaryRequest = new proto.grpc.gateway.testing.EchoRequest();
unaryRequest.setMessage(msg);
echoService.echo(unaryRequest, {},
  function(err, response) {
    console.log(response.getMessage());
  });

Les flux du serveur au navigateur sont pris en charge:

var stream = echoService.serverStreamingEcho(streamRequest, {});
stream.on('data', function(response) {
  console.log(response.getMessage());
});

Les flux bidirectionnels ne sont PAS supportés:

Ceci est un travail en cours et sur la grpc-web roadmap . Bien qu'il existe un exemple protobuf montrant le streaming bidi, ce commentaire précise que cet exemple ne fonctionne pas encore.

Espérons que cela va bientôt changer. :)

9
Cody A. Ray

Les personnes de grpc sur https://github.com/grpc/ construisent actuellement un js implementation .

La repro est à la https://github.com/grpc/grpc-web (donne 404 ->) qui est actuellement (début 2016-20-20) en accès anticipé, vous devez donc demander l'accès .

7
RickyA

https://github.com/tmc/grpc-websocket-proxy semble pouvoir répondre à vos besoins. Cela traduit json sur les sockets web en grpc (couche au-dessus de grpc-gateway).

6
tmc

C'est exactement ce que fait le proxy WebSocket Proxy de GRPC en envoyant un proxy à tous les appels GRPC via une connexion WebSocket pour obtenir un résultat très similaire à l'API Node GRPC du navigateur. Contrairement à GRPC-Gateway, il fonctionne avec les demandes et les réponses en continu, ainsi que les appels non en continu. 

Il existe à la fois un composant serveur et un composant client . Le serveur proxy WebSocket GRPC Bus peut être exécuté avec Docker en effectuant docker run gabrielgrant/grpc-bus-websocket-proxy.

Du côté du navigateur, vous devez installer le client proxy GRPS Bus WebSocket avec npm install grpc-bus-websocket-client.

puis créez un nouvel objet GBC avec: new GBC(<grpc-bus-websocket-proxy address>, <protofile-url>, <service map>)

Par exemple:

var GBC = require("grpc-bus-websocket-client");

new GBC("ws://localhost:8080/", 'helloworld.proto', {helloworld: {Greeter: 'localhost:50051'}})
  .connect()
  .then(function(gbc) {
    gbc.services.helloworld.Greeter.sayHello({name: 'Gabriel'}, function(err, res){
      console.log(res);
    });  // --> Hello Gabriel
  });

La bibliothèque client s'attend à pouvoir télécharger le fichier .proto avec une requête AJAX. Le service-map fournit les URL des différents services définis dans votre fichier proto tels que vus par le serveur proxy.

Pour plus de détails, voir le client du proxy WebSocket Proxy GRPC README

1
Gabriel Grant

Je vois que beaucoup de réponses n'indiquent pas une solution bidirectionnelle via WebSocket, car l'OP a demandé l'assistance du navigateur.

Vous pouvez utiliser JSON-RPC au lieu de gRPC pour obtenir un RPC bidirectionnel sur WebSocket, qui en prend beaucoup plus, y compris WebRTC (navigateur à navigateur).

Je suppose que cela pourrait être modifié pour prendre en charge gRPC si vous avez vraiment besoin de ce type de sérialisation.

Toutefois, pour chaque onglet de navigateur, les objets de requête ne sont pas sérialisés, ils sont transférés en mode natif et il en va de même avec les travailleurs de grappe ou de threads NodeJS, qui offrent beaucoup plus de performances.

En outre, vous pouvez transférer des "pointeurs" vers SharedArrayBuffer, au lieu de les sérialiser via le format gRPC.

La sérialisation et la désérialisation JSON dans V8 sont également imbattables.

https://github.com/bigstepinc/jsonrpc-bidirectional

0
Tiberiu-Ionuț Stan

En regardant les solutions actuelles avec gRPC sur le web, voici ce qui est disponible au moment de la rédaction de ce document (et ce que j'ai trouvé):

Je souhaite également connecter sans vergogne ma propre solution que j'ai écrite pour mon entreprise et qui est utilisée en production pour adresser des requêtes à un service gRPC qui ne comprend que des appels en flux unaire et serveur:

Chaque pouce du code est couvert par des tests. C'est un middleware Express, il ne nécessite donc aucune modification supplémentaire de votre configuration gRPC. Vous pouvez également déléguer l'authentification HTTP à Express (par exemple, avec Passport).

0
Sepehr