1. Contexte
Avec le développement d'Internet, l'échelle des applications de sites Web continue de s'étendre et l'architecture d'application verticale conventionnelle ne peut plus ne peut plus faire face à la distribution. Une architecture de services centralisée et une architecture informatique mobile sont impératives, et un système de gouvernance est nécessaire de toute urgence pour garantir l'évolution ordonnée de l'architecture
Architecture d'application unique
Lorsque le trafic du site Web est très faible, une seule application est nécessaire pour déployer toutes les fonctions ensemble afin de réduire les nœuds de déploiement et les coûts
À l'heure actuelle, les données l'accès est utilisé pour simplifier la charge de travail d'ajout, de suppression, de modification et de vérification du Framework (ORM) est la clé
Architecture d'application verticale
Lorsque le nombre de visites augmente progressivement, l'accélération provoquée par l'ajout de machines à une seule application devient de plus en plus petite, divisez l'application en plusieurs applications indépendantes pour améliorer l'efficacité
À ce moment , le framework Web (MVC) utilisé pour accélérer le développement des pages front-end est la clé
Architecture de services distribués
Répartie par secteur d'activité
Arrêtez les abus RPC, donnez la priorité aux entreprises verticales Grâce aux appels jar locaux, les appels RPC sont utilisés dans toutes les entreprises
pour identifier correctement la propriété de l'entreprise logique, maximiser la cohésion de chaque module, et réduire le couplage en termes de performances, de disponibilité et de maintenabilité
Ne déployer que quelques serveurs pour chaque version
Chaque nœud peut être mis à l'échelle et étendu en fonction de différents besoins
La mise à jour, le déploiement et l'exécution entre chaque application n'affecteront pas
Séparation du déploiement
Séparation des équipes
Séparation des données
Quand il y a sont de plus en plus d'applications verticales, les interactions entre les applications sont inévitables et le cœur de métier est extrait en tant que services indépendants, formant progressivement un centre de services stable, permettant aux applications frontales de répondre plus rapidement aux demandes changeantes du marché
À l'heure actuelle, un cadre de services distribués est utilisé pour améliorer la réutilisation et l'intégration métier (RPC) est la clé
Cadre RPC de services distribués
Architecture de Flow computing
Quand il y a de plus en plus de services, des problèmes tels que L'évaluation de la capacité et le gaspillage des petites ressources de service apparaissent progressivement. À l'heure actuelle, il est nécessaire d'ajouter un centre de répartition pour une gestion en temps réel basée sur la pression d'accès, et d'améliorer l'utilisation du cluster
À l'heure actuelle, le centre de planification et de gouvernance des ressources (SOA) utilisé pour améliorer l'utilisation des machines est la clé
Modèle de thread NettyLe modèle de thread de Netty est principalement basé sur React, et a évolué vers plusieurs versions en raison de différents scénarios d'application. Mode monothreadC'est-à-dire que la réception des demandes de service et l'exécution des opérations d'E/S sont toutes effectuées par un seul thread, puisque des opérations d'E/S non bloquantes telles que le multiplexage d'E/S sont utilisées, le nombre de demandes. augmente Dans les petits cas, le mode monothread peut également résoudre certains problèmes de scène. Mode thread multi-travailleur à réception uniqueLorsque le nombre de requêtes augmente, le thread d'origine traitant toutes les opérations d'E/S devient de plus en plus insupportable Indicateurs de performance correspondants, Ainsi, le concept de pool de threads de travail est mentionné.À ce stade, la réception de la demande de service est toujours un thread.Après avoir reçu la demande, le thread recevant la demande sera confié au pool de threads de travail suivant et obtiendra un thread du thread. pool pour exécution. Mode de thread de réception multiple et multi-travailleurLorsque le volume de requêtes augmente encore, un seul thread qui reçoit les demandes de service ne peut pas gérer toutes les connexions client, donc Le pool de threads qui reçoit les demandes de service est également étendu et plusieurs threads sont chargés de recevoir les connexions client en même temps. Fil métier RPC Les éléments mentionnés ci-dessus sont les propres modèles de thread de Netty, des stratégies d'optimisation qui ont été continuellement développées avec l'augmentation du volume de demandes. Pour les systèmes d'application, les requêtes RPC concernent principalement le traitement de la logique métier, et ce type d'activité peut nécessiter beaucoup de calculs ou d'E/S. Par exemple, la plupart des applications sont accompagnées d'opérations de base de données, de redis ou d'autres services réseau, etc. S'il y a de telles opérations d'E/S fastidieuses dans la demande commerciale, il est recommandé d'attribuer la tâche de traitement de la demande commerciale à un pool de threads indépendant, sinon les propres threads de netty pourraient être bloqués.Division du travail entre le fil de requête et le fil de travail
Le fil de demande est principalement responsable de la création du lien puis de la délégation de la demande au travailleur thread
Le thread de travail est responsable de l'encodage, du décodage, de la lecture des IO et d'autres opérations
Le RPC J'implémente actuellement le mode thread multi-récepteur multi-worker Le port est lié comme ceci côté serveur :
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 est un groupe utilisé pour recevoir. demandes de service.
workerGroup est un groupe spécifiquement responsable des opérations d'E/S
Pour ajouter un thread métier, il vous suffit de déléguer davantage l'opération de handle au pool de threads. pour définir une interface ici :
public interface RpcThreadPool {Executor getExecutor(int threadSize,int queues); }
Référence au dubbo pool de threads
@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; } }
Petit interlude :
Je me souviens d'une fois, un ami m'a soudainement demandé ce que signifiait la taille de noyau dans le pool de threads Java ? J'ai été soudainement court-circuité, car je n'écris généralement pas en multithread. Quand je pense au pool de threads de base de données que j'utilise habituellement, je suis assez impressionné par les paramètres qu'il contient, mais je ne m'en souviens tout simplement pas. coreSize. Plus tard, j'ai examiné de plus près certains paramètres du pool de threads. Je peux désormais en profiter pour y regarder de plus près afin d'éviter à nouveau un court-circuit.
Lorsqu'il existe plusieurs implémentations de pool de threads, le pool de threads est sélectionné dynamiquement par le nom du pool de threads.
@Componentpublic class RpcThreadPoolFactory {@Autowiredprivate Map<String,RpcThreadPool> rpcThreadPoolMap;public RpcThreadPool getThreadPool(String threadPoolName){return this.rpcThreadPoolMap.get(threadPoolName); } }
Enveloppez le corps de la méthode dans une tâche et remettez-le au pool de threads pour exécution.
@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); } }); }
Il y a actuellement un manque de tests de résistance, il n'y a donc pas encore de comparaison claire des données.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!