J'étais curieux de savoir comment fonctionne gRPC-Java, alors j'ai essayé la lecture de code

introduction

J'ai essayé le Tutoriel Java gRPC et j'étais curieux de savoir comment cela fonctionne, alors j'ai étudié diverses choses.

--GRPC-Comment utiliser Java est décrit dans le tutoriel, donc je ne vais pas l'expliquer en détail. ――C'est un résumé de ce que j'ai compris sur la façon de communiquer et sur la mise en œuvre interne détaillée.

Version confirmée

releases: gRPC-Java v1.16.1

compile 'io.grpc:grpc-netty-shaded:1.16.1'
compile 'io.grpc:grpc-protobuf:1.16.1'
compile 'io.grpc:grpc-stub:1.16.1'

À propos de gRPC

Tout d'abord, à propos de gRPC, les points sont extraits du Document officiel.

-Utilisez Protocol Buffers pour sérialiser les données à envoyer et recevoir et définir l'interface de RPC.

type Aperçu
A simple RPC Renvoie 1 réponse pour 1 requête
A server-side streaming RPC Renvoie plusieurs réponses pour une demande
A client-side streaming RPC Renvoie une réponse pour plusieurs demandes
A bidirectional streaming RPC Échangez plusieurs demandes et plusieurs réponses dans les deux sens

À propos de gRPC-Java

gRPC-Points d'implémentation Java.

À propos de Netty

Netty utilisé dans gRPC-Java est un framework qui vous permet de créer des applications d'E / S non bloquantes (NIO) en Java. (N'utilisez pas de servlet Java)

Le thread qui apparaît dans gRPC, le nom de l'événement de NIO et le traitement de Netty sont comme ceci.

--Détecte ʻOP_ACCEPT dans le thread de boss et enregistre l'événement ʻOP_READ

Personnage rôle
fil de patron
(ServerBootstrap parentGroup)
I du réseau utilisé par Netty/Un thread qui détecte O. L'un est généré par défaut au démarrage.
fil de travail
(ServerBootstrap childGroup)
J'ai utilisé par Netty/O Un thread qui traite chaque événement. La valeur par défaut estNombre de processeurs x 2
thread exécuteur Un thread qui exécute les méthodes définies dans gRPC. Généré pour chaque appel de méthode.
I/O nom de l'événement Aperçu
OP_ACCEPT Connexion du client
OP_READ Réseau I/Lire O
OP_WRITE Réseau I/Exporter O

Supplément

Pour Netty, "JJUG CCC 2018 Spring --I-7 (I) First Netty" est très utile. Devenu.

À propos de HTTP / 2

De Google Introduction à HTTP / 2, les points pour comprendre gRPC sont extraits.

Dans HTTP / 1.x, le texte brut séparé par des sauts de ligne est considéré comme une demande (ou réponse), mais dans HTTP / 2, cela est exprimé comme un message, et le message est divisé en unités de trame suivantes.

De plus, les trames peuvent être échangées en parallèle et dans les deux sens avec une seule connexion TCP. En d'autres termes, il n'est pas nécessaire d'établir une connexion TCP pour chaque demande, et plusieurs réponses et poussées de serveur peuvent être effectuées pour une demande.

Présentation du traitement gRPC-Java

À partir de là, ce sera quelque chose comme "quelle partie du code et quel processus ~", donc avant cela, je vais résumer ce que j'ai interprété à propos de la série de processus.

  1. Le serveur gRPC génère un thread boss utilisé par Netty au démarrage
  2. Le client gRPC fait une demande au serveur gRPC
  3. Lorsque le thread boss détecte l'événement d'E / S réseau ʻOP_ACCEPT, il crée un thread de travail Netty (ou le récupère du pool) et délègue le traitement de ʻOP_READ / ʻOP_WRITE`.
  4. Le thread de travail est appelé à chaque fois qu'un événement d'E / S tel que l'établissement d'une connexion TCP (prise de contact à trois, etc.), la trame HTTP / 2 HEADERS, la trame DATA, etc. se produit.
  5. Après avoir reçu le message HTTP / 2 (plusieurs trames) requis pour l'appel gRPC du client, le thread de travail génère un thread exécutable pour exécuter la méthode gRPC.
  6. Netty est un mécanisme de boucle d'événement qui fonctionne uniquement sur le thread principal et le thread de travail, mais un thread est créé à partir de là pour chaque appel de méthode gRPC.
  7. Par conséquent, il semble que les threads Netty ne sont pas bloqués même si le traitement de blocage est exécuté dans la méthode gRPC.
  8. Le thread exécuteur exécute la méthode gRPC et enregistre la réponse ʻOP_WRITE`.
  9. Le thread de travail détecte ʻOP_WRITE` et renvoie une réponse au client.
  10. Si le client continue de se connecter, il n'est pas nécessaire de rétablir une connexion TCP, de sorte que les processus «5. ~ 7.» peuvent être exécutés plusieurs fois en parallèle.
  11. Déconnectez TCP si le client se déconnecte

Lecture de code côté serveur

TODO Je l'écris pour mon propre mémo, je vais donc l'ajouter plus tard et l'organiser. (Il était difficile de suivre la création de divers threads et de créer de nouveaux threads avec des rappels, donc je serais heureux si vous pouviez me dire si j'ai fait une erreur.)

Commencez

--Exécuter RouteGuideServer # main --Obtenir une instance de ServerBuilder avec ServerBuilder # forPort --Dans ServiceProviders # loadAll, regardez ClassLoader pour déterminer s'il s'agit d'une application Android ou non.

Recevoir la demande

--Lorsque le thread de travail accepte la demande d'appel de méthode gRPC, NettyServerHandler est ServerImpl $ ServerTransportListenerImpl # streamCreated /io/grpc/netty/NettyServerHandler.java#L437) --ServerImpl $ ServerTransportListenerImpl # streamCreated [Passer une instance de StreamCreated qui hérite de ContextRunnable à SerializingExecutor qui encapsule ThreadPoolExecutor](https://github.com/grpc/grpc-java/blob/v1.16.1/core/src/ main / java / io / grpc / internal / ServerImpl.java # L495) --Cette exécution exécute la tâche exécutable suivante avec le nom de thread grpc-default-executor-% d dans ThreadFactoryBuilder $ ThreadFactory. --StreamCreated # run-> StreamCreated # runInContext est exécuté --And ServerImpl # JumpToApplicationThreadServerStreamListener $ MessagesAvailable # runInContext est appelé

getFeature:130, RouteGuideServer$RouteGuideService (grpc.routeguide)
invoke:462, RouteGuideGrpc$MethodHandlers (grpc.routeguide)
onHalfClose:171, ServerCalls$UnaryServerCallHandler$UnaryServerCallListener (io.grpc.stub)
halfClosed:283, ServerCallImpl$ServerStreamListenerImpl (io.grpc.internal)
runInContext:710, ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed (io.grpc.internal)
run:37, ContextRunnable (io.grpc.internal)
run:123, SerializingExecutor (io.grpc.internal)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:748, Thread (java.lang)

Recommended Posts

J'étais curieux de savoir comment fonctionne gRPC-Java, alors j'ai essayé la lecture de code
Java9 était inclus, j'ai donc essayé jshell.
J'étais curieux de savoir comment utiliser correctement Optional orElse () et orElseGet ().
J'étais curieux de savoir all_month et j'ai lu ActiveSupport DateAndTime :: Calculations
J'ai essayé l'analyse du code source
À propos de la question pour laquelle j'étais accro à l'utilisation de hashmap