SlideShare ist ein Scribd-Unternehmen logo
1 von 26
Downloaden Sie, um offline zu lesen
Особенности разработки
высоконагруженного сервера на Java



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

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


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



                                              1
Remote Service

• Компоненты портала как отдельные сервисы
  – Система сообщений, граф дружб, поиск, лента и др.
• Внутренняя коммуникация между сервисами

                   long[] friendIds = getConnections (userId)
                                                                Graph cluster
  Business logic
     server
                   List<User> friends = getUsers (friendIds)
                                                                User service
                                                                  cluster


                                                                                2
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
java.net I/O (Sockets)

• Поток на каждое соединение
• Максимум 10 тыс. потоков

  InputStream in = socket.getInputStream();
  OutputStream out = socket.getOutputStream();

  while (true) {
      int bytesRead = in.read(...); // blocking call
      if (bytesRead > 0) {
          byte[] response = processRequest(...);
          out.write(response);       // blocking call
      }
  }



                                                        4
NIO (SocketChannels)
• Selector, неблокирующие read / write
• Direct ByteBuffers
    while (true) {
        if (selector.select() > 0) { // blocking call
            Iterator<SelectionKey> iterator =
                selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                if (key.isReadable()) {
                    doRead(key);
                } else if (key.isWritable()) {
                    doWrite(key);
                }
                iterator.remove();
            }
        }
    }
                                                        5
NIO frameworks

• Apache MINA
  – http://mina.apache.org
• Netty
  – https://netty.io


• Основаны на NIO
• Событийно-управляемая (event-driven) модель




                                            6
Socket I/O → Netty

• Плюсы
  + Сокращение числа потоков (4000 → 200)

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




                                            7
Blocking socket selector (BLOS)

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


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

                                                   8
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);
   }




                                                          9
Архитектура 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

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

• java.net.Socket
  – Finalizers => GC impact
    (объекты SocketImpl не собираются до Full GC)
  – Нет поддержки Direct Buffers


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



                                                    11
Решение

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


• В Tomcat используется похожий подход
  – APR (Apache Portable Runtime)
    http://tomcat.apache.org/tomcat-7.0-doc/apr.html



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

             Deserialize arguments

                Invoke method

                Serialize result

                Send response


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

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



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

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



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

• Типы сериализаторов
  – Встроенные (базовые типы, массивы, коллекции)
  – Генерируемые по полям класса
• Сериализатор класса имеет уникальный ID –
  64-битный хеш от имен, типов и порядка полей

  class Event {
    String name = “jug.msk.ru”;
    int year = 2013;              UID   10 j u g . m s k . r u 2013 1
    boolean started = true;
  }


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

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


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



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

• Чтение и запись private полей чужих объектов




• Создание экземпляров класса




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

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


• Создание экземпляров класса
  – sun.misc.Unsafe.allocateInstance()
  – Динамическая генерация байткода




                                             19
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
  // As simple as malloc()
  Object x = unsafe.allocateInstance(X.class);

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


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

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


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

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

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

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

• Reflection внутри использует MagicAccessorImpl

                                              22
Производительность (1/2)

• Количество потоков: 4000 → 200
• Среднее время запроса: -20%




                                   23
Производительность (2/2)

• GC overhead: -30%
• Сетевой трафик: -50%




                           24
Спасибо!

• Примеры
  – https://github.com/odnoklassniki/one-nio


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


• Работа в Одноклассниках
  – http://v.ok.ru


                                               25

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Java servlet life cycle - methods ppt
Java servlet life cycle - methods pptJava servlet life cycle - methods ppt
Java servlet life cycle - methods ppt
 
Collections - Lists, Sets
Collections - Lists, Sets Collections - Lists, Sets
Collections - Lists, Sets
 
Heap and stack space in java
Heap and stack space in javaHeap and stack space in java
Heap and stack space in java
 
Spring mvc
Spring mvcSpring mvc
Spring mvc
 
String in java
String in javaString in java
String in java
 
Collections In Java
Collections In JavaCollections In Java
Collections In Java
 
Java I/o streams
Java I/o streamsJava I/o streams
Java I/o streams
 
Constructor in Java - ITVoyagers
Constructor in Java - ITVoyagersConstructor in Java - ITVoyagers
Constructor in Java - ITVoyagers
 
Batching and Java EE (jdk.io)
Batching and Java EE (jdk.io)Batching and Java EE (jdk.io)
Batching and Java EE (jdk.io)
 
Java spring batch
Java spring batchJava spring batch
Java spring batch
 
Java Exception handling
Java Exception handlingJava Exception handling
Java Exception handling
 
Collections framework in java
Collections framework in javaCollections framework in java
Collections framework in java
 
Collections in Java Notes
Collections in Java NotesCollections in Java Notes
Collections in Java Notes
 
Java Stack Data Structure.pptx
Java Stack Data Structure.pptxJava Stack Data Structure.pptx
Java Stack Data Structure.pptx
 
Iterator - a powerful but underappreciated design pattern
Iterator - a powerful but underappreciated design patternIterator - a powerful but underappreciated design pattern
Iterator - a powerful but underappreciated design pattern
 
Golang 高性能实战
Golang 高性能实战Golang 高性能实战
Golang 高性能实战
 
Access modifiers in java
Access modifiers in javaAccess modifiers in java
Access modifiers in java
 
The Singleton Pattern Presentation
The Singleton Pattern PresentationThe Singleton Pattern Presentation
The Singleton Pattern Presentation
 
Scaling Apache Storm - Strata + Hadoop World 2014
Scaling Apache Storm - Strata + Hadoop World 2014Scaling Apache Storm - Strata + Hadoop World 2014
Scaling Apache Storm - Strata + Hadoop World 2014
 
Struts framework
Struts frameworkStruts framework
Struts framework
 

Ähnlich wie Java tricks for high-load server programming

Незаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервераНезаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервераodnoklassniki.ru
 
Проект «Одноклассники» Mail.Ru Group, Андрей Паньгин
Проект «Одноклассники» Mail.Ru Group, Андрей ПаньгинПроект «Одноклассники» Mail.Ru Group, Андрей Паньгин
Проект «Одноклассники» Mail.Ru Group, Андрей ПаньгинEYevseyeva
 
Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)Ontico
 
андрей паньгин
андрей паньгинандрей паньгин
андрей паньгинkuchinskaya
 
Developing highload servers with Java
Developing highload servers with JavaDeveloping highload servers with Java
Developing highload servers with JavaAndrei Pangin
 
Анатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей СмирновАнатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей СмирновOntico
 
Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)Andrey Smirnov
 
ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS Pavel Tsukanov
 
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...rit2011
 
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest
 
Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»e-Legion
 
YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011CodeCamp
 
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)Ontico
 
Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)Andrey Smirnov
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Yandex
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Yandex
 
Клиент-серверные приложения на iPhone
Клиент-серверные приложения на iPhoneКлиент-серверные приложения на iPhone
Клиент-серверные приложения на iPhonePavel Bashmakov
 
Cocoa Networking
Cocoa NetworkingCocoa Networking
Cocoa Networkingguest57eb8a
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyRegn
 
Caching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in JavaCaching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in JavaAndrei Pangin
 

Ähnlich wie Java tricks for high-load server programming (20)

Незаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервераНезаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервера
 
Проект «Одноклассники» Mail.Ru Group, Андрей Паньгин
Проект «Одноклассники» Mail.Ru Group, Андрей ПаньгинПроект «Одноклассники» Mail.Ru Group, Андрей Паньгин
Проект «Одноклассники» Mail.Ru Group, Андрей Паньгин
 
Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)
 
андрей паньгин
андрей паньгинандрей паньгин
андрей паньгин
 
Developing highload servers with Java
Developing highload servers with JavaDeveloping highload servers with Java
Developing highload servers with Java
 
Анатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей СмирновАнатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей Смирнов
 
Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)
 
ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS
 
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
 
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
 
Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»Юрий Буянов «Архитектура Goozy»
Юрий Буянов «Архитектура Goozy»
 
YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011YuryByyanov (e-legion) @ CodeCamp2011
YuryByyanov (e-legion) @ CodeCamp2011
 
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
 
Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"
 
Клиент-серверные приложения на iPhone
Клиент-серверные приложения на iPhoneКлиент-серверные приложения на iPhone
Клиент-серверные приложения на iPhone
 
Cocoa Networking
Cocoa NetworkingCocoa Networking
Cocoa Networking
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на Groovy
 
Caching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in JavaCaching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in Java
 

Java tricks for high-load server programming

  • 1. Особенности разработки высоконагруженного сервера на Java Андрей Паньгин ведущий разработчик проекта Одноклассники
  • 2. Серверы Одноклассников • Всего 5000 серверов – Web, Business logic, Download, Storage… – Все ПО написано на Java • Высоконагруженный сервер – 20 тыс. одновременных подключений – 30 тыс. запросов в секунду – Трафик до 1 Gb/s 1
  • 3. Remote Service • Компоненты портала как отдельные сервисы – Система сообщений, граф дружб, поиск, лента и др. • Внутренняя коммуникация между сервисами long[] friendIds = getConnections (userId) Graph cluster Business logic server List<User> friends = getUsers (friendIds) User service cluster 2
  • 4. 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. java.net I/O (Sockets) • Поток на каждое соединение • Максимум 10 тыс. потоков InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); while (true) { int bytesRead = in.read(...); // blocking call if (bytesRead > 0) { byte[] response = processRequest(...); out.write(response); // blocking call } } 4
  • 6. NIO (SocketChannels) • Selector, неблокирующие read / write • Direct ByteBuffers while (true) { if (selector.select() > 0) { // blocking call Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if (key.isReadable()) { doRead(key); } else if (key.isWritable()) { doWrite(key); } iterator.remove(); } } } 5
  • 7. NIO frameworks • Apache MINA – http://mina.apache.org • Netty – https://netty.io • Основаны на NIO • Событийно-управляемая (event-driven) модель 6
  • 8. Socket I/O → Netty • Плюсы + Сокращение числа потоков (4000 → 200) • Минусы – Конструирование запроса по частям – Влияние на GC – Снижение производительности на 20% 7
  • 9. Blocking socket selector (BLOS) • Сочетает преимущества Selector + Blocking I/O • Возможно в OS, но не поддерживается в Java Linux epoll Solaris /dev/poll BSD kqueue Windows I/O completion ports • Реализуется посредством JNI – Простые Java-обертки над системными вызовами 8
  • 10. 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); } 9
  • 11. Архитектура 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 10
  • 12. Проблемы работы с сетью в Java • java.net.Socket – Finalizers => GC impact (объекты SocketImpl не собираются до Full GC) – Нет поддержки Direct Buffers • NIO не спасает – Не срабатывают I/O timeouts – Возможна утечка нативной памяти 11
  • 13. Решение • И снова JNI – Нет finalize(), нет утечки памяти – Время GC до 10 раз меньше – Необходимость закрывать сокеты вручную • В Tomcat используется похожий подход – APR (Apache Portable Runtime) http://tomcat.apache.org/tomcat-7.0-doc/apr.html 12
  • 14. Remote Service • RPC сценарий Read Request Deserialize arguments Invoke method Serialize result Send response • Эффективность сериализации – ключ к производительности RPC – Затрачиваемое на сериализацию время – Размер передаваемых по сети данных 13
  • 15. Сериализация • Built-in Java Serialization – Слишком медленная – Большой объем получаемых данных • JBoss Serialization – Не поддерживает разные версии классов • Avro, Thrift, Protocol Buffers • Ручная сериализация – Externalizable – Не вариант (тысячи классов!) 14
  • 16. Требования к сериализации • Быстрая • Компактная • Обрабатывает простые изменения внутри класса – Добавление поля – Удаление поля – Изменение порядка полей – Изменение типа поля (int → long) 15
  • 17. Архитектура сериализации (1/2) • Типы сериализаторов – Встроенные (базовые типы, массивы, коллекции) – Генерируемые по полям класса • Сериализатор класса имеет уникальный ID – 64-битный хеш от имен, типов и порядка полей class Event { String name = “jug.msk.ru”; int year = 2013; UID 10 j u g . m s k . r u 2013 1 boolean started = true; } 16
  • 18. Архитектура сериализации (2/2) • Запись объекта: 1. Serializer serializer = Repository.getByClass(obj.getClass()); 2. outputStream.writeLong(serializer.uid); 3. serializer.write(obj, outputStream); • Чтение объекта: 1. long uid = inputStream.readLong(); 2. Serializer serializer = Repository.getById(uid);  may throw SerializerNotFoundException 3. Object obj = serializer.read(inputStream); 17
  • 19. Трудности реализации • Чтение и запись private полей чужих объектов • Создание экземпляров класса 18
  • 20. Трудности реализации • Чтение и запись private полей чужих объектов – Reflection (медленно!) – sun.misc.Unsafe • Создание экземпляров класса – sun.misc.Unsafe.allocateInstance() – Динамическая генерация байткода 19
  • 21. 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 // As simple as malloc() Object x = unsafe.allocateInstance(X.class); // Read private field f of object x long offset = unsafe.objectFieldOffset(f); Object result = unsafe.getObject(x, offset); 20
  • 22. Генерация байткода 1. Построить массив byte[] с бинарным представлением класса 2. Вызвать ClassLoader.defineClass()  ClassLoader должен быть унаследован • ASM framework (http://asm.ow2.org) – Построить представление класса с помощью org.objectweb.asm.ClassWriter – Преобразовать его в массив byte[]: ClassWriter.toByteArray() 21
  • 23. А как же private поля? • JVM при загрузке нового класса верифицирует байткод • Если класс унаследован от sun.reflect.MagicAccessorImpl, верификатор не будет проверять права доступа для байткодов getfield и putfield • Reflection внутри использует MagicAccessorImpl 22
  • 24. Производительность (1/2) • Количество потоков: 4000 → 200 • Среднее время запроса: -20% 23
  • 25. Производительность (2/2) • GC overhead: -30% • Сетевой трафик: -50% 24
  • 26. Спасибо! • Примеры – https://github.com/odnoklassniki/one-nio • Контакты – andrey.pangin@odnoklassniki.ru – www.odnoklassniki.ru/ap • Работа в Одноклассниках – http://v.ok.ru 25