[Java Sharing Inn] Die Parameter des SpringBoot-Thread-Pools durchsuchen eine Menge Informationen und können immer noch nicht übereinstimmen. Ich verbringe einen Tag mit Tests, damit Sie es in diesem Leben verstehen.

I. Einleitung

  Wenn Sie beschäftigt sind und vorbeikommen, können Sie es zunächst mit einem Lesezeichen versehen und es dann lesen, wenn Sie Zeit haben oder es verwenden. Ich glaube, dass viele Leute

  eine Verwirrung haben werden, die dieselbe ist wie meine zuvor, nämlich die Thread-Pool. Es ist sehr groß, sehr modisch zu verwenden und es gibt kein Problem beim Debuggen in der Testumgebung der lokalen Umgebung, aber es treten Probleme auf, sobald es online geht.

  Dann hat Baidu viele Informationen erhalten und festgestellt, dass es um die Notwendigkeit geht, den Thread-Pool und verschiedene Konfigurationsparameter anzupassen.

  Letztendlich liegt die Ursache darin, dass die Konfigurationsparameter des benutzerdefinierten Thread-Pools nicht bekannt sind. In diesem Artikel wird ein sehr einfacher Fall verwendet, um die Konfiguration des Thread-Pools und die Konfiguration der Online-Umgebung zu verdeutlichen.


Zweitens der Fall

1. Schreiben Sie einen Fall

Passen Sie einen Thread-Pool an und fügen Sie eine Erstkonfiguration hinzu.

Die Anzahl der Kernthreads beträgt 10, die maximale Anzahl von Threads beträgt 50, die Warteschlangengröße beträgt 200, das Präfix des benutzerdefinierten Thread-Poolnamens lautet my-executor- und die Thread-Pool-Ablehnungsrichtlinie lautet AbortPolicy, was auch die Standardeinstellung ist Richtlinie, die angibt, dass die Aufgabe direkt abgebrochen wird.

package com.example.executor.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
@EnableScheduling
@Slf4j
public class AsyncConfiguration {
    
    

   /**
    * 自定义线程池
    */
   @Bean(name = "myExecutor")
   public Executor getNetHospitalMsgAsyncExecutor() {
    
    
      log.info("Creating myExecutor Async Task Executor");
      ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
      executor.setCorePoolSize(10);
      executor.setMaxPoolSize(50);
      executor.setQueueCapacity(200);
      executor.setThreadNamePrefix("my-executor-");
      // 拒绝策略:直接拒绝抛出异常
      executor.setRejectedExecutionHandler(
            new ThreadPoolExecutor.AbortPolicy());
      return executor;
   }
}

Als Nächstes schreiben wir einen asynchronen Dienst, verwenden diesen benutzerdefinierten Thread-Pool direkt und simulieren einen Nachrichtenversanddienst, der 5 Sekunden dauert.

package com.example.executor.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 异步服务
 * </p>
 *
 * @author 福隆苑居士,公众号:【Java分享客栈】
 * @since 2022/4/30 11:41
 */
@Service
@Slf4j
public class AsyncService {
    
    

   /**
    * 模拟耗时的发消息业务
    */
   @Async("myExecutor")
   public void sendMsg() throws InterruptedException {
    
    
      log.info("[AsyncService][sendMsg]>>>> 发消息....");
      TimeUnit.SECONDS.sleep(5);
   }
}

Dann schreiben wir einen TestService, rufen mit dem mit Hutools gelieferten Parallelitätstool den oben genannten Messaging-Dienst auf und setzen die Anzahl der Parallelitäten auf 200, dh öffnen 200 Threads gleichzeitig, um das Geschäft auszuführen.

package com.example.executor.service;

import cn.hutool.core.thread.ConcurrencyTester;
import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 测试服务
 * </p>
 *
 * @author 福隆苑居士,公众号:【Java分享客栈】
 * @since 2022/4/30 11:45
 */
@Service
@Slf4j
public class TestService {
    
    

   private final AsyncService asyncService;

   public TestService(AsyncService asyncService) {
    
    
      this.asyncService = asyncService;
   }

   /**
    * 模拟并发
    */
   public void test() {
    
    
      ConcurrencyTester tester = ThreadUtil.concurrencyTest(200, () -> {
    
    
         // 测试的逻辑内容
         try {
    
    
            asyncService.sendMsg();
         } catch (InterruptedException e) {
    
    
            log.error("[TestService][test]>>>> 发生异常: ", e);
         }
      });

      // 获取总的执行时间,单位毫秒
      log.info("总耗时:{}", tester.getInterval() + " ms");
   }
}

Schreiben Sie abschließend eine Testschnittstelle.

package com.example.executor.controller;

import com.example.executor.service.TestService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 测试接口
 * </p>
 *
 * @author 福隆苑居士,公众号:【Java分享客栈】
 * @since 2022/4/30 11:43
 */
@RestController
@RequestMapping("/api")
public class TestController {
    
    

   private final TestService testService;

   public TestController(TestService testService) {
    
    
      this.testService = testService;
   }

   @GetMapping("/test")
   public ResponseEntity<Void> test() {
    
    
      testService.test();
      return ResponseEntity.ok().build();
   }
}

2. Ausführungsreihenfolge

Nachdem der Fall abgeschlossen ist, beginnen wir mit dem Test des Aufrufs des Thread-Pools. Zuvor möchte ich Ihnen jedoch erklären, wie die Konfiguration des benutzerdefinierten Thread-Pools während des laufenden Prozesses ausgeführt wird und in welcher Reihenfolge dies geschieht klar, Sie werden nicht verwirrt sein, wenn Sie die Parameter später anpassen.

Anzahl der Kernthreads (CorePoolSize) —> (wenn alle belegt sind) —> in die Warteschlange stellen (QueueCapacity) —> (wenn alle belegt sind) —> einen neuen Thread entsprechend der maximalen Anzahl an Threads (MaxPoolSize) erstellen —> (wenn die maximale Anzahl von Threads überschritten wird) -> Ausführung der Ablehnungsrichtlinie starten (RejectedExecutionHandler)

Schauen Sie es sich dreimal hintereinander an, und dann werden Sie es tun.


3. So konfigurieren Sie die Anzahl der Kernthreads

Lassen Sie uns zunächst das Programm ausführen. Hier werden wir die wichtigen Hinweise des oben genannten Falls noch einmal erklären, damit jeder sie hören kann.

1) Die Anzahl der Kernthreads im Thread-Pool beträgt 10, die maximale Anzahl der Threads beträgt 50 und die Warteschlange beträgt 200; 2) Das

Senden von Nachrichten dauert 5 Sekunden;

3) Die Anzahl der gleichzeitigen Toolausführungsthreads beträgt 200.

Wie Sie in der Abbildung unten sehen können, wurden alle 200 Threads ausgeführt. Sie können die Zeit auf der linken Seite beobachten und alle 5 Sekunden werden 10 Threads ausgeführt. Ich kann deutlich feststellen, dass die Ausführung aller 200 Threads sehr langsam ist der Hintergrundbetrieb.

Es ist ersichtlich, dass zuerst 10 Kernthreads ausgeführt werden und die restlichen 190 in die Warteschlange gestellt werden. Unsere Warteschlangengröße beträgt 200, sodass die maximale Anzahl von Threads nicht funktioniert.

111.png

Denken Sie: Wie kann die Ausführungseffizienz von 200 Threads verbessert werden? Die Antwort liegt auf der Hand, denn unser Geschäft ist ein zeitaufwändiges Geschäft, das 5 Sekunden dauert. Wenn die Anzahl der Kernthreads geringer konfiguriert ist, ist die Ausführung aller 200 Threads sehr langsam, sodass wir nur die Anzahl erhöhen müssen Kernfäden. .

Wir passen die Anzahl der Kernthreads auf 100 an

@Bean(name = "myExecutor")
   public Executor getNetHospitalMsgAsyncExecutor() {
    
    
      log.info("Creating myExecutor Async Task Executor");
      ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
      executor.setCorePoolSize(100);
      executor.setMaxPoolSize(50);
      executor.setQueueCapacity(200);
      executor.setThreadNamePrefix("my-executor-");
      // 拒绝策略:直接拒绝抛出异常
      executor.setRejectedExecutionHandler(
            new ThreadPoolExecutor.AbortPolicy());
      // 拒绝策略:调用者线程执行
//    executor.setRejectedExecutionHandler(
//          new ThreadPoolExecutor.CallerRunsPolicy());
      return executor;
   }

Schauen Sie sich den Effekt an: Huh? Einen Fehler gemeldet?

222.png

Schauen Sie sich einfach den Quellcode an.

333.png

Es stellt sich heraus, dass bei der Initialisierung des Thread-Pools interne Beurteilungen vorgenommen werden. Wenn die maximale Anzahl von Threads kleiner als die Anzahl der Kern-Threads ist, wird diese Ausnahme ausgelöst, daher müssen wir beim Festlegen besonders darauf achten, zumindest auf die Anzahl Die Anzahl der Kernthreads muss größer oder gleich der maximalen Anzahl von Threads sein.

Ändern wir die Konfiguration: Die Anzahl der Kernthreads und die maximale Anzahl der Threads sind beide auf 100 festgelegt.

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("my-executor-");

Schauen Sie sich den Effekt an: Während des Hintergrundlaufprozesses kann festgestellt werden, dass die Laufgeschwindigkeit sehr hoch ist, mindestens zehnmal höher als zuvor, und die Ausführung von 200 Threads wird nach einiger Zeit beendet sein.

444.png

Grund: Wir haben das zeitaufwändige Geschäft auf 5 Sekunden eingestellt und die Anzahl der Kernthreads beträgt nur 10. Dann führen die in der Warteschlange wartenden Threads das zeitaufwändige Geschäft stapelweise aus, und jeder Stapel von 5 Sekunden ist sehr langsam . Wenn wir den Kern einsetzen Nachdem die Anzahl der Threads erhöht wurde, entspricht dies der Ausführung von nur einem oder zwei Stapeln, um das 5-Sekunden-Geschäft abzuschließen, und die Geschwindigkeit wird natürlich verdoppelt.

Hier können wir das erste Fazit ziehen:

Wenn Ihr Unternehmen zeitaufwändig ist, sollte die Anzahl der Kernthreads in der Thread-Pool-Konfiguration erhöht werden.

Denken Sie eine Weile nach:

Welche Art von Unternehmen eignet sich für die Konfiguration einer kleineren Anzahl von Kernthreads und einer größeren Warteschlange?


4. So konfigurieren Sie die maximale Anzahl von Threads

Schauen wir uns als Nächstes die maximale Anzahl an Threads an. Das ist interessant. Viele Informationen im Internet sind falsch.

Im vorherigen Fall passen wir der Übersichtlichkeit halber die Konfigurationsparameter an: Die Anzahl der Kernthreads beträgt 4, die maximale Anzahl der Threads beträgt 8 und die Warteschlange beträgt nur 1.

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(8);
executor.setQueueCapacity(1);
executor.setThreadNamePrefix("my-executor-");

Dann haben wir die Anzahl der gleichzeitigen Tests auf 10 geändert.

ConcurrencyTester tester = ThreadUtil.concurrencyTest(10, () -> {
    
    
   // 测试的逻辑内容
   try {
    
    
      asyncService.sendMsg();
   } catch (InterruptedException e) {
    
    
      log.error("[TestService][test]>>>> 发生异常: ", e);
   }
});

Starten, testen:

Überraschende Entdeckung, oder? Es gibt 10 gleichzeitige Zahlen. Wie kommt es, dass nur 9 ausgeführt werden, und wohin geht die andere?

555.png
Ändern wir die maximale Anzahl an Threads auf 7 und versuchen es erneut

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(7);
executor.setQueueCapacity(1);
executor.setThreadNamePrefix("my-executor-");

Schauen Sie es sich noch einmal an und stellen Sie fest, dass nur 8 von ihnen hingerichtet wurden. Jetzt, wo es erledigt ist, sind 2 von ihnen verschwunden ...

666.png

Warum, ich werde den spezifischen Demonstrationseffekt in der folgenden Ablehnungsstrategie demonstrieren und Ihnen hier direkt die Schlussfolgerung mitteilen:

  Was bedeutet die maximale Anzahl von Threads im Thread-Pool? Ja, das bedeutet wörtlich. Wenn die Anzahl der Kernthreads voll ist, ist auch die Warteschlange voll, und die verbleibenden Threads führen Aufgaben über neue Threads aus, die von der maximalen Anzahl von Threads erstellt wurden. Dieser Prozess wurde zu Beginn für alle geklärt.

  Aber hören Sie genau zu, denn es handelt sich um die maximale Anzahl von Threads, sodass der Ausführungsthread diese Anzahl nicht überschreitet. Wenn er diese Anzahl überschreitet, wird er von der Ablehnungsrichtlinie abgelehnt.

  Lassen Sie uns es nun anhand der Konfigurationsparameter am Anfang dieses Abschnitts noch einmal sortieren: 10 gleichzeitige Zahlen, 4 belegen Kernthreads, 1 tritt in die Warteschlange ein und die maximale Anzahl von Threads ist auf 8 konfiguriert. In den aktuellen 2 Sekunden Während der Geschäftszeit beträgt die Gesamtzahl der aktiven Threads:

  Anzahl der Kernthreads (4) + Anzahl neu erstellter Threads (?) = maximale Anzahl von Threads (8). Daraus ist

  ersichtlich, dass die maximale Anzahl von Threads so konfiguriert ist 8. Nachdem die Anzahl der Kernthreads und Warteschlangen voll ist, wird die Anzahl der neu erstellten Threads nur 8-4 = 4 betragen. Die endgültige Ausführung lautet also:

  Anzahl der Kernthreads (4) + Anzahl neu erstellter Threads (4) + Anzahl der Threads in der Warteschlange (1) = 9 Es

  liegt überhaupt kein Problem vor, und die verbleibenden Threads überschreiten die maximale Anzahl von Threads 8 und werden von der Ablehnungsrichtlinie abgelehnt.

Schließlich gibt Ihnen ein Bild ein klares Bild. Achten Sie auf die Zeit auf der linken Seite. Sie werden wissen, dass der letzte Thread der Thread ist, der nach 2 Sekunden in der Warteschlange ausgeführt wird.

777.png

Hier können wir auch die zweite Schlussfolgerung ziehen:

Die maximale Anzahl von Threads ist die wörtliche Bedeutung. Der aktuell aktive Thread kann dieses Limit nicht überschreiten. Wenn er dieses Limit überschreitet, wird er von der Ablehnungsrichtlinie abgelehnt.


5. So konfigurieren Sie die Warteschlangengröße

Die ersten beiden sind verstanden, und die Warteschlangengröße kann tatsächlich mit einem einfachen Test verstanden werden.
Wir ändern die vorherige Thread-Pool-Konfiguration:

Die Anzahl der Kernthreads beträgt 50, die maximale Anzahl der Threads beträgt 50, die Warteschlange beträgt 100 und die Geschäftszeit wird auf 1 Sekunde geändert, um das Testen zu erleichtern.

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("my-executor-");

Die Anzahl der Parallelitäten ist auf 200 festgelegt

ConcurrencyTester tester = ThreadUtil.concurrencyTest(200, () -> {
    
    
   // 测试的逻辑内容
   try {
    
    
      asyncService.sendMsg();
   } catch (InterruptedException e) {
    
    
      log.error("[TestService][test]>>>> 发生异常: ", e);
   }
});

Testen Sie den Effekt: Es ist ersichtlich, dass am Ende nur 150 der 200 gleichzeitigen Zahlen ausgeführt werden. Die maximale Anzahl von Threads im spezifischen Algorithmus wurde im vorherigen Abschnitt erwähnt und wird nicht wiederholt.

888.png

Hier machen wir hauptsächlich klar, dass die maximale Anzahl von Threads verwendet wird, um neue Threads zu berechnen und zu erstellen, um das Geschäft auszuführen, nachdem die aktuelle Anzahl von Threads die Warteschlangengröße überschreitet. Dann können wir genauso gut darüber nachdenken, ob die Festlegung ausreicht Die Warteschlange muss größer sein, damit sie nicht erneut die maximale Anzahl an Threads annimmt.

Um dies zu sehen, passen wir die Warteschlangengröße von 100 auf 500 an

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("my-executor-");

Testergebnisse: Wie Sie sehen, wurden alle 200 ausgeführt, was zeigt, dass unsere Annahme richtig ist.

999.png

Eine dritte Schlussfolgerung lässt sich hier ziehen:

Wenn die Warteschlangengröße angemessen eingestellt ist, besteht keine Notwendigkeit, die maximale Anzahl von Threads zu verwenden, um zusätzlichen Overhead zu verursachen. Daher besteht die beste Möglichkeit zum Konfigurieren des Thread-Pools darin, die Anzahl der Kernthreads an die Warteschlangengröße anzupassen.


6. So passen Sie die Ablehnungsstrategie an

Im vorherigen Abschnitt zum Konfigurieren der maximalen Anzahl von Threads wurde nach dem Testen festgestellt, dass einige Threads nach Überschreiten der maximalen Anzahl von Threads direkt abgelehnt werden, da wir zu Beginn eine Ablehnungsrichtlinie konfiguriert haben. Diese Richtlinie ist die Standardrichtlinie des Thread-Pools, was eine direkte Ablehnung bedeutet.

// 拒绝策略:直接拒绝抛出异常
executor.setRejectedExecutionHandler(
      new ThreadPoolExecutor.AbortPolicy());

Woher wissen wir also, dass diese Threads tatsächlich abgelehnt werden? Hier stellen wir die Parameterkonfiguration im Abschnitt mit der maximalen Anzahl von Threads wieder her.

Ändern Sie dann die Standardrichtlinie in eine andere Richtlinie: CallerRunsPolicy. Dies bedeutet, dass der Aufrufer-Thread nach der Ablehnung weiterhin ausgeführt wird.

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(7);
executor.setQueueCapacity(1);
executor.setThreadNamePrefix("my-executor-");
// 拒绝策略:调用者线程执行
executor.setRejectedExecutionHandler(
      new ThreadPoolExecutor.CallerRunsPolicy());
return executor;

Die Anzahl der Parallelitäten wird auf 10 geändert

ConcurrencyTester tester = ThreadUtil.concurrencyTest(10, () -> {
    
    
   // 测试的逻辑内容
   try {
    
    
      asyncService.sendMsg();
   } catch (InterruptedException e) {
    
    
      log.error("[TestService][test]>>>> 发生异常: ", e);
   }
});

Testergebnisse:

  Es ist ersichtlich, dass alle 10 gleichzeitigen Nummern ausgeführt wurden und im Abschnitt über die maximale Anzahl von Threads 2 Threads von der Standardstrategie abgelehnt wurden, als wir sie getestet haben, da die Strategie jetzt geändert wurde, um den Aufrufer-Thread fortfahren zu lassen Führen Sie die Aufgabe aus, sodass die beiden Threads sie zwar ablehnen, aber dennoch vom aufrufenden Thread ausführen.

  Sie können sehen, dass sich die Namen der beiden Threads in der roten Linie in der Abbildung offensichtlich von denen des benutzerdefinierten Threads unterscheiden, bei dem es sich um den auszuführenden Aufrufer-Thread handelt.

1010.png

  Ist diese Strategie also so human, dass sie gut sein muss?

  NEIN! Diese Strategie ist unkontrollierbar. Wenn es sich um ein Internetprojekt handelt, kann man online leicht einen Fehler machen. Der Grund ist ganz einfach.

  Was der Thread-Pool belegt, ist nicht der Hauptthread, sondern eine asynchrone Operation zum Ausführen von Aufgaben. Bei dieser Strategie wird der abgelehnte Thread tatsächlich zur Ausführung an den Hauptthread übergeben, was einem Wechsel von asynchron zu synchron entspricht. Stellen Sie sich das bei Spitzenverkehr vor Wenn in dieser Phase aufgrund dieser Strategie eine große Anzahl asynchroner Threads den Hauptthread verlässt, was sind die Konsequenzen? Es ist wahrscheinlich, dass das Programm Ihres Hauptthreads abstürzt und dann eine Servicelawine entsteht.

Zeigen Sie die vier vom Thread-Pool bereitgestellten Strategien an:

1), AbortPolicy: die Standardrichtlinie, die eine RejectedExecutionException direkt ablehnt und auslöst;

2), CallerRunsPolicy: Der Aufrufer-Thread führt die Aufgabe weiterhin aus, eine einfache Feedback-Mechanismus-Richtlinie;

3), DiscardPolicy: verwirft die Aufgabe direkt ohne Benachrichtigung und Feedback;

4), DiscardOldestPolicy: Eine alte Aufgabe verwerfen, normalerweise die mit der längsten Überlebenszeit.

Viele Leute denken, dass die CallerRunsPolicy-Strategie die umfassendste ist, aber meiner persönlichen Meinung nach stellt die Standardstrategie tatsächlich das geringste Risiko in der Produktionsumgebung dar, und unsere Online-Projekte neigen dazu, der Sicherheit Priorität einzuräumen.


Apropos, basierend auf dem Fall kann im Grunde jeder die Bedeutung dieser Thread-Pool-Parameter verstehen. Erinnern Sie sich also noch an eine Denkfrage, die ich zuvor gesendet habe? Ich erinnere mich nicht daran, weil jeder ein Fisch ist. Die Denkfrage Ist:

Welche Art von Unternehmen eignet sich für die Konfiguration einer kleineren Anzahl von Kernthreads und einer größeren Warteschlange?

  Antwort: Szenarios mit geringem Zeitverbrauch und hoher Parallelität sind sehr gut geeignet, da ein geringer Zeitverbrauch zum Geschäft auf Millisekundenebene gehört und besser für CPU und Speicher geeignet ist. Bei hoher Parallelität ist eine Warteschlangenpufferung erforderlich. Aufgrund des geringen Zeitverbrauchs ist eine Warteschlangenpufferung erforderlich. Es wird nicht lange in der Warteschlange warten. Eine große Anzahl von Kernthreads erhöht gleichzeitig den CPU-Overhead. Daher ist die Konfiguration einer kleineren Anzahl von Kernthreads und einer größeren Warteschlange für dieses Szenario sehr gut geeignet.

  Abgesehen davon wissen diejenigen, die Cloud-Produkte verwendet haben, dass Sie beim Kauf eines Cloud-Servers immer aufgefordert werden, sich für CPU-intensive oder IO-intensive Modelle zu entscheiden. Wenn Sie mehr über Thread-Pools wissen, wissen Sie, was das bedeutet Tatsächlich werden die Servermodelle berücksichtigt, die mit verschiedenen Projekten abgeglichen werden müssen. Im obigen Szenario ist es offensichtlich, einen CPU-intensiven Server zu wählen. Das Fallszenario im vorherigen Kapitel ist jedoch zeitaufwändig und für IO- geeignet. intensive Server.


3. Zusammenfassung

Neben der Zusammenfassung dieses Kapitels sind noch weitere Punkte hinzugefügt, die aus meiner Berufserfahrung stammen.

1) Wenn es sich bei Ihrem Unternehmen um ein zeitaufwändiges Unternehmen handelt, sollte die Anzahl der Kernthreads in der Thread-Pool-Konfiguration erhöht und die Warteschlange entsprechend reduziert werden. 2) Wenn es sich bei Ihrem Unternehmen um ein zeitaufwändiges Unternehmen handelt (Millisekundenebene)

. ), gleichzeitig Wenn der Datenverkehr groß ist, sollte die Anzahl der Kernthreads in der Thread-Pool-Konfiguration reduziert und die Warteschlange entsprechend erhöht werden; 3) Die

maximale Anzahl von Threads ist die wörtliche Bedeutung, die aktuell aktiv ist Der Thread kann dieses Limit nicht überschreiten. Wenn er dieses Limit überschreitet, wird er von der Richtlinie abgelehnt.

4) Wenn die Warteschlangengröße angemessen eingestellt ist, besteht keine Notwendigkeit, die maximale Anzahl von Threads zu verwenden, um zusätzlichen Overhead zu verursachen Der beste Weg, den Thread-Pool zu konfigurieren, besteht darin, die Anzahl der Kernthreads mit der Warteschlangengröße abzugleichen. 5) Die Strategie zur Ablehnung des Thread-Pools sollte so weit wie möglich auf der Standardeinstellung basieren, um das Risiko der Produktionsumgebung zu

verringern Ändern, sofern nicht erforderlich;

6) Die Gesamtzahl der Thread-Pools für Projekte oder Mikrodienste, die auf demselben Server bereitgestellt werden, sollte 5 nicht überschreiten, da sonst Leben und Tod von Leben und Reichtum abhängen; 7) , Verwenden Sie den Thread-Pool nicht wahllos, unterscheiden

Sie Machen Sie Geschäftsszenarien klar und versuchen Sie, sie in Szenarien zu verwenden, die sich verzögern können und nicht besonders wichtig sind, z. B. zum Senden von Nachrichten hier oder zum Senden von Abonnementbenachrichtigungen oder zum Erstellen von Protokollaufzeichnungen für ein bestimmtes Szenario usw. Die Verwendung des Threads ist einfach Pool im Kerngeschäft;

8), Thread-Pools nicht mischen, denken Sie daran, bestimmte Unternehmen zu isolieren, das heißt, passen Sie ihre eigenen Thread-Pools an, unterschiedliche Namen und unterschiedliche Parameter, Sie können sich vorstellen, dass Sie einen Thread-Pool nach Belieben geschrieben haben, konfigurieren Sie I Ich habe die geeigneten Parameter für mein eigenes Unternehmen gefunden, sie wurden jedoch von einem anderen Kollegen in einem Unternehmen mit großer Parallelität verwendet. Zu diesem Zeitpunkt kann ich nur die gleichen Schwierigkeiten haben; 9) Die Thread-Pool-Konfiguration ist kein Leckerbissen zum

Abendessen Auch wenn Sie damit vertraut sind, machen Sie bitte trotzdem einen Stresstest, bevor Sie online gehen. Das ist eine schmerzhafte Lektion für mich.

10) Bitte klären Sie unbedingt das Anwendungsszenario des Thread-Pools und verwechseln Sie es nicht mit dem Bei der Verarbeitungslösung mit hoher Parallelität sind die beiden Geschäftsrichtungen völlig unterschiedlich.


4. Teilen

  Abschließend möchte ich Ihnen eine Formel mitteilen, die ich in meiner vorherigen Arbeit verwendet habe. Sie gilt nur für Szenarien, in denen die aktuellen Fäden des spezifischen Geschäfts kleiner und mittlerer Unternehmen mehr als Tausende von Ebenen umfassen. Schließlich habe ich sie Ich habe noch nie in einer großen Fabrik gearbeitet und die Erfahrung, die ich weitergeben kann, ist begrenzt. .

  Nehmen wir als Beispiel unser Unternehmen. Wir sind ein kleines und mittleres Internetunternehmen. Wir nutzen die Huawei Cloud und die Online-Server bestehen im Wesentlichen aus 8 Kernen. Normalerweise verwende ich den Thread-Pool für bestimmte Unternehmen, um die aktuelle Anzahl der Threads zu testen 2000, da 2000 Threads gleichzeitig ausgeführt werden, ist es in kleinen und mittleren Unternehmen nicht so einfach, einen gleichzeitigen Thread zu erstellen, wie jeder denkt. Unser Unternehmen beliefert Krankenhäuser und wir treffen sie ein paar Mal im Jahr nicht, abgesehen von dem Anstieg der Nukleinsäurezahlen aufgrund der Epidemie in den letzten zwei Jahren.

  Sie können sich vorstellen, dass 2.000 Threads gleichzeitig ein bestimmtes Geschäft verarbeiten, wie viele Benutzer erforderlich sind und welche Art von Szene angezeigt wird. Der Schlüssel liegt darin, dass Sie den Thread-Pool verwenden. Warum verwenden Sie den Thread-Pool selbst? In dieser Szene? Es ist auch etwas, worüber man nachdenken sollte. Einige ähnliche Szenarien verwenden Caching und MQ, um Spitzen zu reduzieren. Aus diesem Grund habe ich in meiner Zusammenfassung gesagt, dass man sie nicht mit Verarbeitungslösungen mit hoher Parallelität verwechseln sollte. Sie sollten Thread-Pools verwenden, wenn Sie die Verarbeitung verzögern ist erforderlich. Es eignet sich am besten für weniger wichtige Geschäfte.

Die von mir zusammengefasste Formel kann hier abgerufen werden:
Link: https://pan.baidu.com/doc/share/TES95Wnsy3ztUp_Al1L~LQ-567189327526315
Extraktionscode: 2jjy



Mein Originalartikel ist rein handgeschrieben. Wenn Sie ihn für nützlich halten, geben Sie ihm bitte einen Daumen nach oben .

Von Zeit zu Zeit werde ich die Erfahrungen und interessanten Dinge in der eigentlichen Arbeit teilen. Wenn Sie interessiert sind, achten Sie bitte darauf ~


Acho que você gosta

Origin blog.csdn.net/xiangyangsanren/article/details/124532681
Recomendado
Clasificación