SlideShare a Scribd company logo
1 of 21
Download to read offline
Незаурядная Java как инструмент
разработки высоконагруженного сервера




Андрей Паньгин
ведущий разработчик
проекта Одноклассники
Серверы Одноклассников

• Всего >3000 серверов
  – Web, Business logic, Download, Storage,
    Remote Service…
  – Все ПО написано на Java


• Высоконагруженный сервер
  – 20 тыс. одновременных подключений
  – 30 тыс. запросов в секунду
  – Трафик до 1 Gb/s

                                              1
Типичный Java Server

• java.net I/O (Sockets)
  – Поток на каждое соединение
  – Максимум 10 тыс. потоков
• NIO (SocketChannels)
  – Direct buffers
  – Selector
  – Неблокирующий ввод-вывод
• Event-driven NIO frameworks
  – Apache MINA
  – Netty

                                 2
Remote Service

• Компоненты портала как отдельные сервисы
  – Система сообщений, граф дружб, поиск, лента и др.
• Внутренняя коммуникация между сервисами
• RPC сценарий
            Read Request        byte[] request = connection.read(…);

        Deserialize arguments   request    Method method, Object[] args

           Invoke method        Object result = method.invoke(args);

           Serialize result     result    byte[] response

           Send response        connection.write(response);



                                                                          3
Socket I/O      Netty

• Конструирование запроса по частям
• Влияние на GC
• Снижение производительности
  – Среднее время запроса +20%




                                      4
Blocking socket selector (BLOS)

• Сочетает преимущества Selector + Blocking I/O
• Возможно в OS, но не поддерживается в Java
       Linux     epoll
       Solaris   /dev/poll
       BSD       kqueue
       Windows   I/O completion ports


• Реализуется посредством JNI
  – Простые Java-обертки над системными вызовами

                                                   5
Java Socket              Native

• java.net.Socket
      java.net.SocketImpl impl
          java.io.FileDescriptor fd
              int fd


   Object getField(Object holder, Class cls, String name) {
       Field f = cls.getDeclaredField(name);
       f.setAccessible(true);
       return f.get(holder);
   }




                                                              6
Архитектура BLOS сервера
•   1 acceptor thread
•   N selector threads (обычно N = кол-во CPU)
•   Динамический пул потоков-исполнителей
•   Запрос исполняется непрерывно до конца
                                  Acceptor thread
                                    Selector 1
                                    Selector 2

          read      deserialize       invoke        serialize       send

             read       deserialize       invoke        serialize      send

                             Worker thread pool

                                                                              7
Проблемы работы с сетью в Java

• java.net.Socket
  – Нет поддержки Direct Buffers
  – Finalizers => GC impact


• NIO не спасает
  – Не срабатывают I/O timeouts
  – Возможна утечка нативной памяти




                                      8
Решение

• И снова JNI
  – Нет finalize(), нет утечки памяти
  – Время GC до 10 раз меньше
  – Необходимость закрывать сокеты вручную


• В Tomcat используется похожий подход
  – APR (Apache Portable Runtime)




                                             9
Remote Service
• RPC сценарий
                 Read Request

             Deserialize arguments

                Invoke method

                Serialize result

                Send response


• Эффективность сериализации –
  ключ к производительности RPC
  – Затрачиваемое на сериализацию время
  – Размер передаваемых по сети данных
                                          10
Сериализация

• Built-in Java Serialization
   – Слишком медленная
   – Большой объем получаемых данных
• JBoss Serialization
   – Не поддерживает модификацию классов
• Ручная сериализация
   – Не вариант (тысячи классов!)




                                           11
Требования к сериализации

• Быстрая
• Компактная
• Обрабатывает простые изменения
  внутри класса
  –   Добавление поля
  –   Удаление поля
  –   Изменение порядка полей
  –   Изменение типа поля (int long)



                                       12
Архитектура сериализации (1/2)

• Типы сериализаторов
  –   Встроенные (примитивные типы, обертки, массивы)
  –   Collection и Map
  –   Сериализация произвольных классов по полям
  –   Самосериализуемые классы (readObject / writeObject)


• Каждому сериализуемому классу
  сопоставляется уникальный 64-битный ID –
  хеш от имен, типов и порядка полей


                                                       13
Архитектура сериализации (2/2)

• Запись объекта:
  1. Serializer serializer = Repository.getByClass(obj.getClass());
  2. writeLong(serializer.uid);
  3. Serializer.write(obj, this);


• Чтение объекта:
  1. long uid = readLong();
  2. Serializer serializer = Repository.getById(uid);
         may throw SerializerNotFoundException
  3. Object obj = serializer.read(this);



                                                                      14
Трудности реализации

• Чтение/запись private полей чужих объектов
  – Reflection (медленно!)
  – sun.misc.Unsafe


• Создание объектов без вызова конструктора
  – sun.misc.Unsafe.allocateInstance()
  – ReflectionFactory.newConstructorForSerialization()
  – Динамическая генерация байткода




                                                         15
Unsafe
  import sun.misc.Unsafe;

  private static Unsafe getUnsafe() throws Exception {
      Field f = Unsafe.class.getDeclaredField("theUnsafe");
      f.setAccessible(true);
      return (Unsafe) f.get(null);
  }

  // Instantiate class X without calling X's constructor
  Object x = unsafe.allocateInstance(X.class);

  // Read private field f of object x
  long offset = unsafe.objectFieldOffset(f);
  Object result = unsafe.getObject(x, offset);




                                                              16
Генерация байткода

1. Создать свой ClassLoader
2. Построить массив byte[] с бинарным
   представлением класса
3. Вызвать ClassLoader.defineClass()

• ASM framework (http://asm.ow2.org)
  – Построить представление класса с помощью
    org.objectweb.asm.ClassWriter
  – Преобразовать его в массив byte[]:
    ClassWriter.toByteArray()

                                               17
А как же private поля?

• JVM при загрузке нового класса верифицирует
  байткод

• Если класс унаследован от
  sun.reflect.MagicAccessorImpl,
  верификатор не будет проверять права
  доступа для байткодов getfield и putfield




                                              18
Производительность

•   Среднее время запроса: -20%
•   Сетевой трафик: -50%
•   Продолжительность GC: -30%
•   Количество потоков: 4000  200




                                    19
Спасибо!

• Примеры
  – https://github.com/odnoklassniki/rmi-samples.git


• Контакты
  – andrey.pangin@odnoklassniki.ru
  – www.odnoklassniki.ru/ap




                                                       20

More Related Content

What's hot

За гранью NoSQL: NewSQL на Cassandra
За гранью NoSQL: NewSQL на CassandraЗа гранью NoSQL: NewSQL на Cassandra
За гранью NoSQL: NewSQL на Cassandra
odnoklassniki.ru
 
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов НиколайnoBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
Ontico
 
Евгений Потапов (Сумма Айти)
Евгений Потапов (Сумма Айти)Евгений Потапов (Сумма Айти)
Евгений Потапов (Сумма Айти)
Ontico
 
Чему мы научились разрабатывая микросервисы?
Чему мы научились разрабатывая микросервисы?Чему мы научились разрабатывая микросервисы?
Чему мы научились разрабатывая микросервисы?
Vadim Madison
 
Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)
Andrey Smirnov
 
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ontico
 
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
Ontico
 
Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)
Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)
Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)
Ontico
 

What's hot (20)

За гранью NoSQL: NewSQL на Cassandra
За гранью NoSQL: NewSQL на CassandraЗа гранью NoSQL: NewSQL на Cassandra
За гранью NoSQL: NewSQL на Cassandra
 
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов НиколайnoBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
 
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
 
Евгений Потапов (Сумма Айти)
Евгений Потапов (Сумма Айти)Евгений Потапов (Сумма Айти)
Евгений Потапов (Сумма Айти)
 
Метапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptМетапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScript
 
Чему мы научились разрабатывая микросервисы?
Чему мы научились разрабатывая микросервисы?Чему мы научились разрабатывая микросервисы?
Чему мы научились разрабатывая микросервисы?
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actual
 
Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)
 
Денис Иванов
Денис ИвановДенис Иванов
Денис Иванов
 
Жизнь проекта на production советы по эксплуатации / Николай Сивко (okmeter.io)
Жизнь проекта на production советы по эксплуатации / Николай Сивко (okmeter.io)Жизнь проекта на production советы по эксплуатации / Николай Сивко (okmeter.io)
Жизнь проекта на production советы по эксплуатации / Николай Сивко (okmeter.io)
 
Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...
Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...
Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...
 
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
 
Как сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрееКак сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрее
 
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
 
Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)
Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)
Кластеры баз данных делаем сложные вещи просто / Андрей Тихонов (Avito)
 
Java threads - part 2
Java threads - part 2Java threads - part 2
Java threads - part 2
 
Java 8. Thread pools
Java 8. Thread poolsJava 8. Thread pools
Java 8. Thread pools
 
Java threads - part 3
Java threads - part 3Java threads - part 3
Java threads - part 3
 
Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"
Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"
Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"
 
Java threads - part 1
Java threads - part 1Java threads - part 1
Java threads - part 1
 

Similar to Незаурядная Java как инструмент разработки высоконагруженного сервера

CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest
 
Анатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей СмирновАнатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей Смирнов
Ontico
 
YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011
CodeCamp
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoF
Dmitry Buzdin
 
Cocoa Networking
Cocoa NetworkingCocoa Networking
Cocoa Networking
guest57eb8a
 
Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)
Andrey Smirnov
 
Git in Sky presentation @ HighLoad++ 2013
Git in Sky presentation @ HighLoad++ 2013Git in Sky presentation @ HighLoad++ 2013
Git in Sky presentation @ HighLoad++ 2013
Serguei Gitinsky
 
Сергей Житинский, Александр Чистяков (Git in Sky)
Сергей Житинский, Александр Чистяков (Git in Sky)Сергей Житинский, Александр Чистяков (Git in Sky)
Сергей Житинский, Александр Чистяков (Git in Sky)
Ontico
 

Similar to Незаурядная Java как инструмент разработки высоконагруженного сервера (20)

CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
 
Анатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей СмирновАнатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей Смирнов
 
JVM: краткий курс общей анатомии
JVM: краткий курс общей анатомииJVM: краткий курс общей анатомии
JVM: краткий курс общей анатомии
 
Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»
 
YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoF
 
Клиент-серверные приложения на iPhone
Клиент-серверные приложения на iPhoneКлиент-серверные приложения на iPhone
Клиент-серверные приложения на iPhone
 
Cocoa Networking
Cocoa NetworkingCocoa Networking
Cocoa Networking
 
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
 
Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)
 
SmartOS/Solaris app tuning tools/technologies on HL++ 2013
SmartOS/Solaris app tuning tools/technologies on HL++ 2013SmartOS/Solaris app tuning tools/technologies on HL++ 2013
SmartOS/Solaris app tuning tools/technologies on HL++ 2013
 
Git in Sky presentation @ HighLoad++ 2013
Git in Sky presentation @ HighLoad++ 2013Git in Sky presentation @ HighLoad++ 2013
Git in Sky presentation @ HighLoad++ 2013
 
JVM: краткий курс общей анатомии, JPoint 2016 Conference Edition
JVM: краткий курс общей анатомии, JPoint 2016 Conference EditionJVM: краткий курс общей анатомии, JPoint 2016 Conference Edition
JVM: краткий курс общей анатомии, JPoint 2016 Conference Edition
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"
 
Сергей Житинский, Александр Чистяков (Git in Sky)
Сергей Житинский, Александр Чистяков (Git in Sky)Сергей Житинский, Александр Чистяков (Git in Sky)
Сергей Житинский, Александр Чистяков (Git in Sky)
 
ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS
 
Unsafe: to be or to be removed?
Unsafe: to be or to be removed?Unsafe: to be or to be removed?
Unsafe: to be or to be removed?
 
Java Ahead-Of-Time compilation
Java Ahead-Of-Time compilationJava Ahead-Of-Time compilation
Java Ahead-Of-Time compilation
 
TMPA-2013 Sartakov: Genode
TMPA-2013 Sartakov: GenodeTMPA-2013 Sartakov: Genode
TMPA-2013 Sartakov: Genode
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
 

More from odnoklassniki.ru

Тестирование аварий. Андрей Губа. Highload++ 2015
Тестирование аварий. Андрей Губа. Highload++ 2015Тестирование аварий. Андрей Губа. Highload++ 2015
Тестирование аварий. Андрей Губа. Highload++ 2015
odnoklassniki.ru
 
Кадры решают все, или стриминг видео в «Одноклассниках». Александр Тоболь
Кадры решают все, или стриминг видео в «Одноклассниках». Александр ТобольКадры решают все, или стриминг видео в «Одноклассниках». Александр Тоболь
Кадры решают все, или стриминг видео в «Одноклассниках». Александр Тоболь
odnoklassniki.ru
 
Платформа для видео сроком в квартал. Александр Тоболь.
Платформа для видео сроком в квартал. Александр Тоболь.Платформа для видео сроком в квартал. Александр Тоболь.
Платформа для видео сроком в квартал. Александр Тоболь.
odnoklassniki.ru
 
Cистема внутренней статистики Odnoklassniki.ru
Cистема внутренней статистики Odnoklassniki.ruCистема внутренней статистики Odnoklassniki.ru
Cистема внутренней статистики Odnoklassniki.ru
odnoklassniki.ru
 
Как, используя Lucene, построить высоконагруженную систему поиска разнородных...
Как, используя Lucene, построить высоконагруженную систему поиска разнородных...Как, используя Lucene, построить высоконагруженную систему поиска разнородных...
Как, используя Lucene, построить высоконагруженную систему поиска разнородных...
odnoklassniki.ru
 

More from odnoklassniki.ru (14)

Distributed systems at ok.ru #rigadevday
Distributed systems at ok.ru #rigadevdayDistributed systems at ok.ru #rigadevday
Distributed systems at ok.ru #rigadevday
 
Тестирование аварий. Андрей Губа. Highload++ 2015
Тестирование аварий. Андрей Губа. Highload++ 2015Тестирование аварий. Андрей Губа. Highload++ 2015
Тестирование аварий. Андрей Губа. Highload++ 2015
 
Тюним память и сетевой стек в Linux: история перевода высоконагруженных серве...
Тюним память и сетевой стек в Linux: история перевода высоконагруженных серве...Тюним память и сетевой стек в Linux: история перевода высоконагруженных серве...
Тюним память и сетевой стек в Linux: история перевода высоконагруженных серве...
 
Add a bit of ACID to Cassandra. Cassandra Summit EU 2014
Add a bit of ACID to Cassandra. Cassandra Summit EU 2014Add a bit of ACID to Cassandra. Cassandra Summit EU 2014
Add a bit of ACID to Cassandra. Cassandra Summit EU 2014
 
Кадры решают все, или стриминг видео в «Одноклассниках». Александр Тоболь
Кадры решают все, или стриминг видео в «Одноклассниках». Александр ТобольКадры решают все, или стриминг видео в «Одноклассниках». Александр Тоболь
Кадры решают все, или стриминг видео в «Одноклассниках». Александр Тоболь
 
Платформа для видео сроком в квартал. Александр Тоболь.
Платформа для видео сроком в квартал. Александр Тоболь.Платформа для видео сроком в квартал. Александр Тоболь.
Платформа для видео сроком в квартал. Александр Тоболь.
 
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
 
Аварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
Аварийный дамп – чёрный ящик упавшей JVM. Андрей ПаньгинАварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
Аварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
 
Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013
Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013
Being closer to Cassandra by Oleg Anastasyev. Talk at Cassandra Summit EU 2013
 
Управление тысячами серверов в Одноклассниках. Алексей Чудов.
Управление тысячами серверов в Одноклассниках. Алексей Чудов.Управление тысячами серверов в Одноклассниках. Алексей Чудов.
Управление тысячами серверов в Одноклассниках. Алексей Чудов.
 
Класс!ная Cassandra
Класс!ная CassandraКласс!ная Cassandra
Класс!ная Cassandra
 
Java Runtime: повседневные обязанности JVM
Java Runtime: повседневные обязанности JVMJava Runtime: повседневные обязанности JVM
Java Runtime: повседневные обязанности JVM
 
Cистема внутренней статистики Odnoklassniki.ru
Cистема внутренней статистики Odnoklassniki.ruCистема внутренней статистики Odnoklassniki.ru
Cистема внутренней статистики Odnoklassniki.ru
 
Как, используя Lucene, построить высоконагруженную систему поиска разнородных...
Как, используя Lucene, построить высоконагруженную систему поиска разнородных...Как, используя Lucene, построить высоконагруженную систему поиска разнородных...
Как, используя Lucene, построить высоконагруженную систему поиска разнородных...
 

Незаурядная Java как инструмент разработки высоконагруженного сервера

  • 1. Незаурядная Java как инструмент разработки высоконагруженного сервера Андрей Паньгин ведущий разработчик проекта Одноклассники
  • 2. Серверы Одноклассников • Всего >3000 серверов – Web, Business logic, Download, Storage, Remote Service… – Все ПО написано на Java • Высоконагруженный сервер – 20 тыс. одновременных подключений – 30 тыс. запросов в секунду – Трафик до 1 Gb/s 1
  • 3. Типичный Java Server • java.net I/O (Sockets) – Поток на каждое соединение – Максимум 10 тыс. потоков • NIO (SocketChannels) – Direct buffers – Selector – Неблокирующий ввод-вывод • Event-driven NIO frameworks – Apache MINA – Netty 2
  • 4. Remote Service • Компоненты портала как отдельные сервисы – Система сообщений, граф дружб, поиск, лента и др. • Внутренняя коммуникация между сервисами • RPC сценарий Read Request byte[] request = connection.read(…); Deserialize arguments request Method method, Object[] args Invoke method Object result = method.invoke(args); Serialize result result byte[] response Send response connection.write(response); 3
  • 5. Socket I/O Netty • Конструирование запроса по частям • Влияние на GC • Снижение производительности – Среднее время запроса +20% 4
  • 6. Blocking socket selector (BLOS) • Сочетает преимущества Selector + Blocking I/O • Возможно в OS, но не поддерживается в Java Linux epoll Solaris /dev/poll BSD kqueue Windows I/O completion ports • Реализуется посредством JNI – Простые Java-обертки над системными вызовами 5
  • 7. Java Socket Native • java.net.Socket java.net.SocketImpl impl java.io.FileDescriptor fd int fd Object getField(Object holder, Class cls, String name) { Field f = cls.getDeclaredField(name); f.setAccessible(true); return f.get(holder); } 6
  • 8. Архитектура BLOS сервера • 1 acceptor thread • N selector threads (обычно N = кол-во CPU) • Динамический пул потоков-исполнителей • Запрос исполняется непрерывно до конца Acceptor thread Selector 1 Selector 2 read deserialize invoke serialize send read deserialize invoke serialize send Worker thread pool 7
  • 9. Проблемы работы с сетью в Java • java.net.Socket – Нет поддержки Direct Buffers – Finalizers => GC impact • NIO не спасает – Не срабатывают I/O timeouts – Возможна утечка нативной памяти 8
  • 10. Решение • И снова JNI – Нет finalize(), нет утечки памяти – Время GC до 10 раз меньше – Необходимость закрывать сокеты вручную • В Tomcat используется похожий подход – APR (Apache Portable Runtime) 9
  • 11. Remote Service • RPC сценарий Read Request Deserialize arguments Invoke method Serialize result Send response • Эффективность сериализации – ключ к производительности RPC – Затрачиваемое на сериализацию время – Размер передаваемых по сети данных 10
  • 12. Сериализация • Built-in Java Serialization – Слишком медленная – Большой объем получаемых данных • JBoss Serialization – Не поддерживает модификацию классов • Ручная сериализация – Не вариант (тысячи классов!) 11
  • 13. Требования к сериализации • Быстрая • Компактная • Обрабатывает простые изменения внутри класса – Добавление поля – Удаление поля – Изменение порядка полей – Изменение типа поля (int long) 12
  • 14. Архитектура сериализации (1/2) • Типы сериализаторов – Встроенные (примитивные типы, обертки, массивы) – Collection и Map – Сериализация произвольных классов по полям – Самосериализуемые классы (readObject / writeObject) • Каждому сериализуемому классу сопоставляется уникальный 64-битный ID – хеш от имен, типов и порядка полей 13
  • 15. Архитектура сериализации (2/2) • Запись объекта: 1. Serializer serializer = Repository.getByClass(obj.getClass()); 2. writeLong(serializer.uid); 3. Serializer.write(obj, this); • Чтение объекта: 1. long uid = readLong(); 2. Serializer serializer = Repository.getById(uid); may throw SerializerNotFoundException 3. Object obj = serializer.read(this); 14
  • 16. Трудности реализации • Чтение/запись private полей чужих объектов – Reflection (медленно!) – sun.misc.Unsafe • Создание объектов без вызова конструктора – sun.misc.Unsafe.allocateInstance() – ReflectionFactory.newConstructorForSerialization() – Динамическая генерация байткода 15
  • 17. Unsafe import sun.misc.Unsafe; private static Unsafe getUnsafe() throws Exception { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); return (Unsafe) f.get(null); } // Instantiate class X without calling X's constructor Object x = unsafe.allocateInstance(X.class); // Read private field f of object x long offset = unsafe.objectFieldOffset(f); Object result = unsafe.getObject(x, offset); 16
  • 18. Генерация байткода 1. Создать свой ClassLoader 2. Построить массив byte[] с бинарным представлением класса 3. Вызвать ClassLoader.defineClass() • ASM framework (http://asm.ow2.org) – Построить представление класса с помощью org.objectweb.asm.ClassWriter – Преобразовать его в массив byte[]: ClassWriter.toByteArray() 17
  • 19. А как же private поля? • JVM при загрузке нового класса верифицирует байткод • Если класс унаследован от sun.reflect.MagicAccessorImpl, верификатор не будет проверять права доступа для байткодов getfield и putfield 18
  • 20. Производительность • Среднее время запроса: -20% • Сетевой трафик: -50% • Продолжительность GC: -30% • Количество потоков: 4000 200 19
  • 21. Спасибо! • Примеры – https://github.com/odnoklassniki/rmi-samples.git • Контакты – andrey.pangin@odnoklassniki.ru – www.odnoklassniki.ru/ap 20