monitoring and optimization of java applications (ukrainian)
TRANSCRIPT
МОНІТОРИНГ ТАОПТИМІЗАЦІЯ
JAVA-ЗАСТОСУНКІВ, @by_mamagaga @anxolerd
21 грудня 2016
ЧАСТИНА 1.ОГЛЯД ТИПОВИХ ПРОБЛЕМ ТАСПОСОБІВ ЇХ ОПТИМІЗАЦІЇ
Deadlock — взаємне блокуваня, яке приводить дозависання програми.
ТИПОВИЙ ПРИКЛАДclass T1 extends Thread { @Override public void run() { // ... lockA.lock(); lockB.lock(); // Critical section lockB.unlock(); lockA.unlock(); // ... } }
class T2 extends Thread { @Override public void run() { // ... lockB.lock(); lockA.lock(); // Critical section lockA.unlock(); lockB.unlock(); // ... } }
ЯК БОРОТИСЯ З DEADLOCKSРетельно проектувати застосунокЗвертати особливу увагу на взаємодію потоків
ВИТОКИ ПАМ'ЯТІ
Memory leak — процес неконтрольованого зменшенняоб'єму пам'яті комп'ютера, пов'язаний з помилками впрограмах, які вчасно не звілняють вже не потрібні
ділянки пам'яті.
СТВОРЕННЯ ОБ'ЄКТІВ У ЦИКЛІclass InLoopCreator { public static void main(String[] args){ // ... for (Object o : collection) { // Note that a new checker instance // will be created on each iteration Checker c = new Checker(); if (c.check(o)) { process(o); } } // ... }}
НЕВИКОРИСТАННЯ ПАТТЕРНІВclass DwarfNPC { byte[] texture; // ...
DwarfNPC() { // ...
// Note that we load the same texture // for every single instance this.texture = FileLoader.load("assets/textures/dwarf");
// ... }}
ЗАВАНТАЖЕННЯ УСЬОГО І ОДРАЗУclass GreedyLoader { List<World> worlds = new ArrayList<World>();
GreedyLoader() { // ... for (String resourceUrl : resourceList) { World world = World.fromResource(resourceUrl); worlds.add(world); } // ... }
// Worlds are used sequentially public World getNextWorld() { /* ... */ }
}
НЕВИВАНТАЖЕННЯ РЕСУРСІВclass HeavyTaskProcessor { Resources resources;
void processWithResources() { resources = load(resources); // Do processing }
void processWithoutResources1() {} void processWithoutResources2() {} void processWithoutResources3() {} void processWithoutResources4() {}
// ... }
ВАЖКІ SQL-ЗАПИТИ
ОЧІКУВАННЯ-- Easy SELECT * FROM "user" WHERE id = 42;
-- Normal SELECT boss.* FROM "user" JOIN "user" AS boss ON boss.id = "user".boss_id WHERE "user".role = 'employee';
РЕАЛЬНІСТЬSELECT cl.* FROM client cl JOIN company ON cl.company_id = cl.id JOIN service_record sr ON sr.company_id = company.id JOIN binding_record br ON br.client_id = cl.ud WHERE br.valid_since < now() - INTERVAL '42 days' AND (sr.invoice_id IS NULL OR sr.upgrade_invoice_id IS NULL) AND sr.id IN (SELECT id FROM services WHERE price > 0) AND NOT EXISTS ( SELECT 1 FROM binding_record br2 WHERE br2.valid_since > br.valid_since AND br2.client_id = br.client_id AND br2.status IN (1,2,5,6) )
СТРАТЕГІЇ ВИРІШЕННЯПроходити по базі частинамиРозбити запит на декілька меншихВиконувати фільтрацію на стороні застосункуОптимізовувати сам запит
ПРОХОДИТИ ПО БАЗІ ЧАСТИНАМИString q = "select * from big_table"; // ... ResultSet rs = stmt.executeQuery(q); process(rs);
String q = "select * from big_table limit=? offset=?"; PreparedStatement st = con.prepareStatement(q);
while (true) { st.setLong(0, limitValue); st.setLong(1, offsetValue);
ResultSet rs = stmt.executeQuery(q); if (rs.isBeforeFirst()) { // result is not empty process(rs); offsetValue = offsetValue + limitValue; } else { break; }}
РОЗБИТИ ЗАПИТ НА ДЕКІЛЬКА МЕНШИХSELECT * FROM table_name WHERE (table_name.column1 = 'group1' and table_name.some_value > 10) or ( table_name.column1 = 'group2' and table_name.some_value < 2 and table_name.some_other_value > 13 ) ;
-- QUERY 1 SELECT * FROM table_name WHERE table_name.column1 = 'group1' AND table_name.some_value > 10;
-- QUERY 2 SELECT * FROM table_name WHERE table_name.column1 = 'group2' AND table_name.some_value < 2 AND table_name.some_other_value > 13;
ВИКОНАТИ ФІЛЬТРАЦІЮ НА СТОРОНІЗАСТОСУНКУ
String q = "SELECT * FROM table_name WHERE column1 > 42"; ResultSet rs = conn.executeQuery(q); List<Entity> alist = parseRs(rs); for (Entity item : alist) { if (!someCondition(item)) { continue; } process(item); }
ОПТИМІЗУВАТИ ЗАПИТ
Використоувати індексиUNION ALL замість складних ORЗменшувати вибірку за допомогою CTE
ЧАСТИНА 2.МОНІТОРИНГ ЗАСТОСУНКІВ
JMX
Java Management Extensions (JMX) — технологія Java,що призначена для контролю та керування
застосунками, системними об'єктами, пристроями(напр. принтерами) та комп'ютерними мережами. Даніресурси представляються у вигляді MBean-об'єктів
(Managed Bean)
ДЕМО
JMC
Java Mission Control (JMC) — набір утиліт длякерування, моніторингу та профілювання Java-
застосунків. Входить до складу Oracle JDK з версії 7u40.Складається із JMX консолі та Java Flight Recorder
ДЕМО
КОРИСНІ ПОСИЛАННЯОфіційна сторінкаДемонстрація можливостей JMCВступ до Java Mission Control
LOGS (ELK)
ElasticsearchLogstashKibana
ДЕМОPublic Kibana instance
КОРИСНІ ПОСИЛАННЯOSDN2016 - TARAS FILIPOV - СОВРЕМЕННЫЕСРЕДСТВА АНАЛИЗА ЛОГОВВстановлення ELK стеку
JAVA MELODY
https://github.com/javamelody/javamelody/wiki
ДЕМО
ДЯКУЄМО, ЩОДОСЛУХАЛИ ДО
КІНЦЯ)