$30 off During Our Annual Pro Sale. View Details »

Разгоняем RPS вопреки всему

aragozin
October 12, 2019

Разгоняем RPS вопреки всему

aragozin

October 12, 2019
Tweet

More Decks by aragozin

Other Decks in Programming

Transcript

  1. Разгоняем RPS
    вопреки всему
    Алексей Рагозин

    View Slide

  2. Тучи сгущаются

    View Slide

  3. Тучи сгущаются
    JBoss
    JSF
    Seam
    BPM
    Hibernate
    PostgreSQL

    View Slide

  4. Проблема с тестированием
    На стенде:
    99% запросов < 1.5 секунд
    У пользователей:
    до 2 минут на “тяжёлые операции”

    View Slide

  5. Неожиданные симптомы
    100% × 8 CPU 2% x 4 CPU

    View Slide

  6. Производительность – это просто
    1. Находим ресурс ограничивающий производительность
    CPU, ширина шины памяти, IOPS, пропускная способность сети
    Критические секции ядра, скорость шифрования потока данных

    View Slide

  7. Производительность – это просто
    1. Находим ресурс ограничивающий производительность
    CPU, ширина шины памяти, IOPS, пропускная способность сети
    Критические секции ядра, скорость шифрования потока данных
    2. Добавляем ресурс

    View Slide

  8. Производительность – это просто
    1. Находим ресурс ограничивающий производительность
    CPU, ширина шины памяти, IOPS, пропускная способность сети
    Критические секции ядра, скорость шифрования потока данных
    2. Добавляем ресурс 2. Находим причину потребления
    дефицитного ресурса
    3. Оптимизируем – уменьшаем
    использование дефицитного ресурса

    View Slide

  9. Производительность – это просто
    1. Находим ресурс ограничивающий производительность
    CPU, ширина шины памяти, IOPS, пропускная способность сети
    Критические секции ядра, скорость шифрования потока данных
    2. Добавляем ресурс 2. Находим причину потребления
    дефицитного ресурса
    3. Оптимизируем – уменьшаем
    использование дефицитного ресурса
    Просто не значит легко!

    View Slide

  10. Упираемся в CPU
    100% × 8 CPU 2% x 4 CPU

    View Slide

  11. Ком проблем

    View Slide

  12. Ком проблем

    View Slide

  13. Ком проблем
    Весь стек работает в одном потоке
    Web server
    Вёрстка (JSF)
    Бизнес логика
    BPM
    Hibernate
    JDBC
    База данных
    Запрос
    Ответ

    View Slide

  14. Ком проблем
    Весь стек работает в одном потоке
    Web server
    Вёрстка (JSF)
    Бизнес логика
    BPM
    Hibernate
    JDBC
    База данных
    Запрос
    Ответ

    View Slide

  15. Профайлеры
    Java Mission Control

    View Slide

  16. “Горячий” код
    “Hot Spots” –
    методы с набольшей
    вероятностью
    выполняющиеся в
    момент дампа потоков

    View Slide

  17. “Огненный граф”

    View Slide

  18. От стека вызовов к …
    … cтеку фреймворков
    Web server
    Вёрстка (JSF)
    Бизнес логика
    BPM
    Hibernate
    JDBC
    База данных
    Запрос
    Ответ
    java.lang.ClassLoader.loadClass(ClassLoader.java:405)
    sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:371)
    org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:119)
    javax.xml.parsers.FactoryFinder.getProviderClass(FactoryFinder.java:112)
    javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:178)
    javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:147)
    javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:219)
    javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:126)
    com.sun.faces.util.Util.createSAXParserFactory(Util.java:217)
    com.sun.faces.facelets.compiler.SAXCompiler.createSAXParser…
    com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:426)
    com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:403)
    com.sun.faces.facelets.compiler.Compiler.compile(Compiler.java:124)
    com.sun.faces.facelets.impl.DefaultFaceletFactory.createFacelet(DefaultFaceletFactory.java:319)
    com.sun.faces.facelets.impl.DefaultFaceletFactory.access$100(DefaultFaceletFactory.java:92)
    com.sun.faces.facelets.impl.DefaultFaceletFactory$1.newInstance(DefaultFaceletFactory.java:159)
    com.sun.faces.facelets.impl.DefaultFaceletFactory$1.newInstance(DefaultFaceletFactory.java:157)
    com.sun.faces.facelets.impl.DefaultFaceletCache$1.newInstance(DefaultFaceletCache.java:79)
    com.sun.faces.facelets.impl.DefaultFaceletCache$1.newInstance(DefaultFaceletCache.java:74)
    com.sun.faces.facelets.impl.DefaultFaceletCache$NoCache.get(DefaultFaceletCache.java:233)
    com.sun.faces.facelets.impl.DefaultFaceletCache$NoCache.get(DefaultFaceletCache.java:226)
    ……

    View Slide

  19. От стека вызовов к …
    … cтеку фреймворков
    Web server
    Вёрстка (JSF)
    Бизнес логика
    BPM
    Hibernate
    JDBC
    База данных
    Запрос
    Ответ
    javassist.util.proxy.RuntimeSupport.find2Methods(RuntimeSupport.java:53)
    mycompany.cardsystem.Card_$$_javassist_122.getHibernateLazyInitializer(Card_$$_javassist_122.java)
    org.hibernate.Hibernate.isInitialized(Hibernate.java:89)
    org.hibernate.engine.internal.StatefulPersistenceContext.reassociateIfUninitializedProxy(StatefulPersist…
    org.hibernate.event.internal.ProxyVisitor.processEntity(ProxyVisitor.java:49)
    org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:124)
    org.hibernate.event.internal.WrapVisitor.processValue(WrapVisitor.java:125)
    org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:76)
    org.hibernate.event.internal.DefaultFlushEntityEventListener.wrapCollections(DefaultFlushEntityEventL…
    org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventList…
    org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener….
    org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushi…
    org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListene…
    org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1204)
    org.hibernate.internal.SessionImpl.list(SessionImpl.java:1261)
    org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
    org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:264)
    mycompany.bpmimpl.persistanse.CsEJB3FindUtils.findActivityVariableEntity(CsEJB3FindUtils.java:185)
    mycompany.bpmimpl.persistanse.CsEJB3FindUtils.findActivityVariableEntity(CsEJB3FindUtils.java:191)
    mycompany.bpmimpl.persistanse.CsPersistentManager.persist(CsPersistentManager.java:1006)
    mycompany.bpm.WfActivityImpl.persistActivityContext(Unknown Source)
    mycompany.bpm.WfActivityImpl.setProcessContext(Unknown Source)
    mycompany.bpm.WfActivityImpl.set_result(Unknown Source)
    mycompany.bpm.WfActivityImpl.receive_event(Unknown Source)

    View Slide

  20. Виновные найдены
    JDBC
    3500ms
    Hibernate
    Tomcat / HTTP
    Вёрстка

    View Slide

  21. Виновные найдены
    JDBC
    3500ms
    Hibernate
    Tomcat / HTTP
    JSF Компилятор
    JSF Life cycle
    Бижекция бинов
    “Resource not found”

    View Slide

  22. Виновные найдены
    JDBC
    3500ms
    Hibernate
    Tomcat / HTTP
    JSF Компилятор
    JSF Life cycle
    Бижекция бинов
    “Resource not found”
    Ошибка конфигурации
    Проверка изменений в
    справочниках на каждую
    Операцию БД

    View Slide

  23. А теперь вёрстка …
    Сколько раз бин
    инжекцится в контекст на
    один HTTP запрос?
    Какие бины инжектятся чаще?

    View Slide

  24. Трассировка методов
    Task.run()
    wait() process()
    getBody()
    read() parse()
    handle()
    load()
    read()
    Time
    encode()
    wait() process()
    getBody()
    read() parse()
    handle()
    load()
    read()
    encode()
    wait() process()
    getBody()
    read() parse()
    handle()
    encode()
    Task.run()
    wait() process()
    getBody()
    read() parse()
    handle()
    load()
    read()
    Time
    encode()
    process()
    getBody()
    read() parse()
    handle()
    load()
    read()
    encode()
    wait() process()
    getBody()
    read() parse()
    handle()
    encode()
    No tracing
    Tracing parse(), load() and encode()

    View Slide

  25. BTrace
    BTrace
    • Инструментирующий
    профайлер
    • CLI и плагин к Visual VM
    • Скрипты на Java
    https://github.com/btraceio/btrace
    BTrace script
    @Property
    Profiler prof = Profiling.newProfiler();
    @OnMethod(clazz = "org.jboss.seam.Component“, method = "/(inject|disinject|outject)/")
    void entryByMethod2(@ProbeClassName String className,
    @ProbeMethodName String methodName, @Self Object component) {
    if (component != null) {
    Field nameField = field(classOf(component), "name", true);
    if (nameField != null) {
    String name = (String)get(nameField, component);
    Profiling.recordEntry(prof, concat("org.jboss.seam.Component.",
    concat(methodName, concat(":", name))));
    }
    }
    }
    @OnMethod(clazz = "org.jboss.seam.Component“, method = "/(inject|disinject|outject)/",
    location = @Location(value = Kind.RETURN))
    void exitByMthd2(@ProbeClassName String className,
    @ProbeMethodName String methodName, @Self Object component,
    @Duration long duration) {
    if (component != null) {
    Field nameField = field(classOf(component), "name", true);
    if (nameField != null) {
    String name = (String)get(nameField, component);
    Profiling.recordExit(prof, concat("org.jboss.seam.Component.",
    concat(methodName, concat(":", name))), duration);
    }
    }
    }

    View Slide

  26. Инструменты трассировки для JVM
    Arthas
    В том числе умеет собирать статистику по методам
    https://github.com/alibaba/arthas
    MyPerf4j
    Публикует статистику по вызовам методов в InfluxDB
    https://github.com/LinShunKang/MyPerf4J

    View Slide

  27. Нюансы вёрстки





    ...





    View Slide

  28. Нюансы вёрстки





    ...





    View Slide

  29. JDBC
    1943ms
    Hibernate
    Tomcat / HTTP
    Вёрстка
    1061ms
    645ms
    267ms
    Другое
    Зачистка проблем
    Исходная версия
    Read-only режим для
    Hibernate объектов
    Тюнинг размера бачтча
    ID генератора
    Отдельные entity manager
    для справочников
    Минимизация пустых комитов
    Включение кеша компиляции JSF
    Оптимизация вёрстки
    Обход бага с интернанализацией

    View Slide

  30. Виноват ли монолит?

    View Slide

  31. Спасибо!
    Алексей Рагозин
    [email protected]
    https://blog.ragozin.info
    Вебинары и прочие
    мероприятия по теме Java Ops
    https://aragozin.timepad.ru/

    View Slide