ThreadPool w Hystrixie

0

Definiuję sobie własne ustawienia ThreadPoola, dając parametry jak poniżej

 @GetMapping
    public String api() throws Exception {

        HystrixCommand.Setter conf = HystrixCommand.Setter
            .withGroupKey(HystrixCommandGroupKey.Factory.asKey("group-1"));

        conf.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
            .withCoreSize(10)
            .withMaximumSize(20)
            .withMaxQueueSize(10));

        return new HCommand(conf).execute();
    }

    static class HCommand extends HystrixCommand<String>{

        protected HCommand(Setter setter) {
            super(setter);
        }

        @Override
        protected String run() throws Exception {
            Thread.sleep(10);
            return "hello";
        }
    }

I testuje za pomocą apache benchmarka dając 10000 zapytań i 20 wątków jednocześnie. I wynik jest taki, że po rozgrzaniu jvm około 10% zapytań nie przechodzi. Dlaczego nie wszystkie ? O ile dobrze rozumiem, to core size zapycha się w pierwszej kolejności nowymi zadaniami, jak się zapełni to idą one do kolejki, a po zapełnieniu kolejki są tworzone nowe, aż do wyczerpania max size.

0

czy te 10% tasków zakończyło się ThreadPoolRejectem ? Wgl, jak to odpalasz, poka środowisko ? masz tam jakiegoś tomcata ? tomcat też ma pulle która Cie ogranicza

EDIT

zrobiłem sobie mały eksperyment i wszystko wygląda ok - wydaje mi się że to Twoje środowisko jest przyczyną.

Generalnie to co chciałem osiągnąć to wykonanie wszystkich zadań w jak najmniejszym przedziale czasu, zrobić brzydkie rzeczy może tutaj tylko kernel :) nie ma niczego przed (tak jak w endpoincie który stoi na tomcat). Wyniki to 80 wyrzuconych wyjątków (zakładam że to zawsze Reject z pooli).

P.S spróbuj sobie to troubleshootować samodzielnie na środowisku które masz, dodaj do aplikacji ilość równoległych połączeń które wchodzą na endpoint, wystaw sobie np: metryki przez dropwizzard i zobacz co się dzieje.

Kod testu który sklepałem (wydaje mi się poprawny) :

public class Main {

    public static void main(String args[]) throws InterruptedException {
        HystrixCommand.Setter conf = HystrixCommand.Setter
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey("group-1"));

        conf.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                                                                        .withCoreSize(10)
                                                                        .withMaximumSize(20)
                                                                          .withMaxQueueSize(10));
        AtomicInteger rejects = new AtomicInteger(0);

        CountDownLatch countDownLatch = new CountDownLatch(100);

        CountDownLatch awaitAll = new CountDownLatch(100);


        for(int i = 0; i < 100; i++)
        {
            new Thread(() ->{
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    System.err.println("XD XD XD XD XD XD XD XD XD XD XD XD XD XD");
                }

                try{
                    new HCommand(conf).execute();

                }catch(Exception e)
                {
                    rejects.incrementAndGet();
                }

                awaitAll.countDown();
            }).start();

            countDownLatch.countDown();

        }
        awaitAll.await();

        System.err.println("Rejects " + rejects.get());
    }

    static class HCommand extends HystrixCommand<String>{

        protected HCommand(Setter setter) {
            super(setter);
        }

        @Override
        protected String run() throws Exception {
            Thread.sleep(10);
            return "hello";
        }
    }
}
0

Log błędu to

Rejected command because thread-pool queueSize is at rejection threshold.

Dodałem dashboard i tam, pokazuje, że kolejka jest ustawiona na 5, a nie na 10. Chodzi o to, że mam ustawione maxQueueSize na 10, ale domyślnie queueSizeRejectionTreshold = 5, więc kolejny wchodzący do kolejki z automatu jest wyrzucany. Dodatkowo, żeby aktywować MaximumSize należy dodać parametr

allowMaximumSizeToDivergeFromCoreSize

całość wygląda następująco.

conf.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
            .withCoreSize(10)
            .withMaximumSize(20)
            .withMaxQueueSize(10)
            .withAllowMaximumSizeToDivergeFromCoreSize(true)
            .withQueueSizeRejectionThreshold(10));

i teraz tylko za pierwszym odpaleniem kilka zapytań się sypie z tym samym błędem. Przy kolejnych odpaleniach już jest ok.

0
ntw222 napisał(a):

Log błędu to

Rejected command because thread-pool queueSize is at rejection threshold.

Dodałem dashboard i tam, pokazuje, że kolejka jest ustawiona na 5, a nie na 10. Chodzi o to, że mam ustawione maxQueueSize na 10, ale domyślnie queueSizeRejectionTreshold = 5, więc kolejny wchodzący do kolejki z automatu jest wyrzucany. Dodatkowo, żeby aktywować MaximumSize należy dodać parametr

allowMaximumSizeToDivergeFromCoreSize

całość wygląda następująco.

conf.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
            .withCoreSize(10)
            .withMaximumSize(20)
            .withMaxQueueSize(10)
            .withAllowMaximumSizeToDivergeFromCoreSize(true)
            .withQueueSizeRejectionThreshold(10));

i teraz tylko za pierwszym odpaleniem kilka zapytań się sypie z tym samym błędem. Przy kolejnych odpaleniach już jest ok.

Dlaczego nie odpowiedziałeś na resztę komentarza ?

0

Odpalam to na Tomcacie, aplikacja spring bootowa. Jak chcesz jeszcze jakieś inne dane to pisz.

JVM version is 25.131-b11
Java System Properties:

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.131-b11
sun.boot.library.path = /usr/lib/jvm/java-8-oracle/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
guice.disable.misplaced.annotation.check = true
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = PL
user.dir = /home/bk/hystrix-exercises
java.vm.specification.name = Java Virtual Machine Specification
PID = 5504
java.runtime.version = 1.8.0_131-b11
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /usr/lib/jvm/java-8-oracle/jre/lib/endorsed
line.separator = 

java.io.tmpdir = /tmp
java.vm.specification.vendor = Oracle Corporation
os.name = Linux
classworlds.conf = /usr/share/maven/bin/m2.conf
sun.jnu.encoding = UTF-8
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
spring.beaninfo.ignore = true
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 3.13.0-135-generic
user.home = /home/bk
user.timezone = Europe/Warsaw
catalina.useNaming = false
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
@appId = application
java.specification.version = 1.8
catalina.home = /tmp/tomcat.7922998641281780846.8080
user.name = bk
java.class.path = /usr/share/maven/boot/plexus-classworlds-2.x.jar
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = org.codehaus.plexus.classworlds.launcher.Launcher spring-boot:run
java.home = /usr/lib/jvm/java-8-oracle/jre
user.language = pl
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.X11.XToolkit
java.vm.info = mixed mode
java.version = 1.8.0_131
securerandom.source = file:/dev/./urandom
java.ext.dirs = /usr/lib/jvm/java-8-oracle/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/classes
java.awt.headless = true
java.vendor = Oracle Corporation
catalina.base = /tmp/tomcat.7922998641281780846.8080
maven.home = /usr/share/maven
file.separator = /
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.cpu.isalist = 

VM Flags:
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=130023424 -XX:MaxHeapSize=2063597568 -XX:MaxNewSize=687865856 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=42991616 -XX:OldSize=87031808 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC 
Command line:  -Dclassworlds.conf=/usr/share/maven/bin/m2.conf -Dmaven.home=/usr/share/maven

Architecture:          x86_64
Tryb(y) pracy CPU:     32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Wątków na rdzeń:    2
Rdzeni na gniazdo:     2
Socket(s):             1
Węzłów NUMA:        1
ID producenta:         GenuineIntel
Rodzina CPU:           6
Model:                 69
Wersja:                1
CPU MHz:               759.000
BogoMIPS:              4589.81
Wirtualizacja:         VT-x
Cache L1d:             32K
Cache L1i:             32K
Cache L2:              256K
Cache L3:              3072K
NUMA node0 CPU(s):     0-3
0

Generalnie to nie wiem nic XD

ale konkluzja jest taka że wszystko działa tak jako powinno.

1 użytkowników online, w tym zalogowanych: 0, gości: 1