Heim  >  Artikel  >  Java  >  Detaillierte Beispiele des RPC-Frameworks

Detaillierte Beispiele des RPC-Frameworks

零下一度
零下一度Original
2017-07-17 14:07:562256Durchsuche

1. Hintergrund

Mit der Entwicklung des Internets nimmt der Umfang der Website-Anwendungen weiter zu und die herkömmliche vertikale Anwendungsarchitektur kann nicht mehr genutzt werden Eine zentralisierte Servicearchitektur und eine Mobile-Computing-Architektur sind zwingend erforderlich, und ein Governance-System ist dringend erforderlich, um die geordnete Entwicklung der Architektur sicherzustellen

Einzelanwendungsarchitektur

Wenn der Website-Verkehr sehr gering ist, ist nur eine Anwendung erforderlich, um alle Funktionen zusammen bereitzustellen, um Bereitstellungsknoten und Kosten zu reduzieren

Zu diesem Zeitpunkt Daten Der Zugriff wird verwendet, um den Arbeitsaufwand beim Hinzufügen, Löschen, Ändern und Überprüfen zu vereinfachen. Framework (ORM) ist der Schlüssel

Vertikale Anwendungsarchitektur

Wann Die Anzahl der Besuche nimmt allmählich zu und die durch das Hinzufügen von Maschinen zu einer einzelnen Anwendung verursachte Beschleunigung wird immer größer. Je kleiner sie ist, desto mehr wird die Anwendung in mehrere unabhängige Anwendungen aufgeteilt, um die Effizienz zu verbessern

Hierbei Gleichzeitig ist das Web-Framework (MVC), das zur Beschleunigung der Front-End-Seitenentwicklung verwendet wird, der Schlüssel

Verteilte Servicearchitektur

Aufgeteilt nach Geschäftsbereichen

RPC-Missbrauch stoppen, vertikalen Unternehmen Vorrang einräumen Durch lokale JAR-Aufrufe werden RPC-Aufrufe unternehmensübergreifend verwendet

, um den Besitz von richtig zu identifizieren Geschäftslogik, maximieren Sie den Zusammenhalt jedes Moduls und reduzieren Sie die Kopplung in Bezug auf Leistung, Verfügbarkeit und Wartbarkeit

Stellen Sie nur einige Server für jede Version bereit

Jeder Knoten kann je nach Bedarf skaliert und erweitert werden

Aktualisierung, Bereitstellung und Ausführung zwischen den einzelnen Anwendungen haben keinen Einfluss auf

Bereitstellungstrennung


Teamtrennung

Datentrennung

Wann Es gibt immer mehr vertikale Anwendungen, Interaktionen zwischen Anwendungen sind unvermeidlich, und das Kerngeschäft wird als unabhängige Dienste extrahiert, wodurch nach und nach ein stabiles Servicecenter entsteht, das es Front-End-Anwendungen ermöglicht, schneller auf sich ändernde Marktanforderungen zu reagieren

Derzeit wird ein verteiltes Service-Framework verwendet, um die geschäftliche Wiederverwendung und Integration (RPC) zu verbessern.

Distributed Service RPC-Framework


Flow-Computing-Architektur


Wenn es immer mehr Dienste gibt, treten Probleme wie z Da es allmählich zu einer Kapazitätsbewertung und Verschwendung kleiner Serviceressourcen kommt, ist es notwendig, ein Versandzentrum für die Echtzeitverwaltung basierend auf der Zugriffsdruckkapazität hinzuzufügen, um die Clusterauslastung zu verbessern 🎜>Derzeit ist das Ressourcenplanungs- und Governance-Center (SOA) zur Verbesserung der Maschinenauslastung der Schlüssel

Netty-Thread-ModellNettys Threading-Modell basiert hauptsächlich auf React, und hat sich aufgrund unterschiedlicher Anwendungsszenarien zu mehreren Versionen entwickelt.

Single-Threaded-Modus

Das heißt, der Empfang von Dienstanfragen und die Ausführung von E/A-Vorgängen werden alle von einem Thread ausgeführt In kleinen Fällen kann der Single-Threaded-Modus auch einige Szenenprobleme lösen.

Einzelner empfangender Multi-Worker-Thread-Modus

Wenn die Anzahl der Anforderungen zunimmt, wird der ursprüngliche Thread, der alle E/A-Vorgänge verarbeitet, immer unerträglicher. Entsprechende Leistungsindikatoren, Daher wird das Konzept eines Arbeits-Thread-Pools erwähnt. Zu diesem Zeitpunkt ist der Empfang der Dienstanforderung immer noch ein Thread. Nach dem Empfang der Anforderung wird der Thread, der die Anforderung empfängt, dem nachfolgenden Arbeits-Thread-Pool anvertraut und erhält einen Thread vom Thread Pool zur Ausführung.

Multiple-Empfangs- und Multi-Worker-Thread-Modus

Wenn das Anforderungsvolumen weiter zunimmt, kann ein einzelner Thread, der Serviceanfragen empfängt, nicht alle Clientverbindungen verarbeiten Der Thread-Pool, der Serviceanfragen empfängt, wird ebenfalls erweitert, und mehrere Threads sind für den gleichzeitigen Empfang von Clientverbindungen verantwortlich.

RPC-Geschäftsthread

Bei den oben genannten handelt es sich um Nettys eigenes Thread-Modell, Optimierungsstrategien, die mit der Zunahme des Anfragevolumens kontinuierlich weiterentwickelt wurden. Bei RPC-Anfragen ist die Verarbeitung der Geschäftslogik das Wichtigste für Anwendungssysteme, und diese Art von Geschäft kann rechenintensiv oder IO-intensiv sein. Beispielsweise werden die meisten Anwendungen von Datenbankoperationen, Redis oder anderen Netzwerkdiensten begleitet , usw. Wenn die Geschäftsanforderung solche zeitaufwändigen E/A-Vorgänge enthält, wird empfohlen, die Aufgabe der Verarbeitung der Geschäftsanforderung einem unabhängigen Thread-Pool zuzuweisen, da sonst die eigenen Threads von netty blockiert werden können.

Arbeitsteilung zwischen dem Anforderungsthread und dem Worker-Thread

  • Der Anforderungsthread ist hauptsächlich für die Erstellung des Links und die anschließende Delegierung der Anforderung an den Worker verantwortlich Thread

  • Der Arbeitsthread ist für die Kodierung, Dekodierung, das Lesen von E/A und andere Vorgänge verantwortlich

Lösungsimplementierung

Der RPC Ich verwende derzeit den Multi-Receiver-Multi-Worker-Thread-Modus. Der Port ist auf der Serverseite wie folgt gebunden:

public void bind(ServiceConfig serviceConfig) {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(this.rpcServerInitializer)
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
            ;try {ChannelFuture channelFuture = bootstrap.bind(serviceConfig.getHost(),serviceConfig.getPort()).sync();//...channelFuture.channel().closeFuture().sync();


            } catch (InterruptedException e) {throw new RpcException(e);
            }
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

boosGroup ist eine Gruppe, die zum Empfangen verwendet wird Serviceanfragen.
workerGroup ist eine Gruppe, die speziell für IO-Operationen verantwortlich ist.

Um Geschäftsthreads hinzuzufügen, müssen Sie nur den Handle-Vorgang weiter an den Thread-Pool delegieren Definieren Sie hier eine Schnittstelle:

Definieren Sie die Thread-Pool-Schnittstelle

public interface RpcThreadPool {Executor getExecutor(int threadSize,int queues);
}

Implementieren eines Thread-Pools fester Größe

Verwiesen auf den Dubbo-Thread pool

@Qualifier("fixedRpcThreadPool")@Componentpublic class FixedRpcThreadPool implements RpcThreadPool {private Executor executor;@Overridepublic Executor getExecutor(int threadSize,int queues) {if(null==executor) {synchronized (this) {if(null==executor) {
                    executor= new ThreadPoolExecutor(threadSize, threadSize, 0L, TimeUnit.MILLISECONDS,
                            queues == 0 ? new SynchronousQueue<Runnable>() :(queues < 0 ? new LinkedBlockingQueue<Runnable>(): new LinkedBlockingQueue<Runnable>(queues)),new RejectedExecutionHandler() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {                                   //...}
                            });
                }
            }
        }return executor;
    }
}

Kleines Zwischenspiel:
Ich erinnere mich, dass einmal ein Freund plötzlich fragte, was die coreSize im Java-Thread-Pool bedeute? Ich war plötzlich kurzgeschlossen, weil ich normalerweise kein Multithreading schreibe. Wenn ich an den Datenbank-Thread-Pool denke, den ich normalerweise häufig verwende, bin ich von den darin enthaltenen Parametern ziemlich beeindruckt, kann mich aber einfach nicht erinnern coreSize. Später habe ich mir einige Parameter des Thread-Pools genauer angesehen. Jetzt kann ich die Gelegenheit nutzen, genauer hinzuschauen, um einen erneuten Kurzschluss zu vermeiden.

Thread-Pool-Factory

Wenn mehrere Thread-Pool-Implementierungen vorhanden sind, wird der Thread-Pool dynamisch anhand des Thread-Pool-Namens ausgewählt.

@Componentpublic class RpcThreadPoolFactory {@Autowiredprivate Map<String,RpcThreadPool> rpcThreadPoolMap;public RpcThreadPool getThreadPool(String threadPoolName){return this.rpcThreadPoolMap.get(threadPoolName);
    }
}

Ändern Sie die Methode „channelRead0“ von ChannelHandle.

Verpacken Sie den Methodenkörper in eine Aufgabe und übergeben Sie ihn zur Ausführung an den Thread-Pool.

@Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest) {this.executor.execute(new Runnable() {@Overridepublic void run() {RpcInvoker rpcInvoker=RpcServerInvoker.this.buildInvokerChain(RpcServerInvoker.this);RpcResponse response=(RpcResponse) rpcInvoker.invoke(RpcServerInvoker.this.buildRpcInvocation(rpcRequest));
            channelHandlerContext.writeAndFlush(response);
        }
    });

}

Problem

Es fehlen derzeit Stresstests, daher gibt es noch keinen eindeutigen Datenvergleich.

Das obige ist der detaillierte Inhalt vonDetaillierte Beispiele des RPC-Frameworks. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn