SlideShare uma empresa Scribd logo
1 de 49
Разработка высоконагруженного
сервера на Java
Андрей Паньгин
Одноклассники, ведущий инженер
План доклада
• Архитектура ОК
• Работа с сетью
• Удалённые вызовы и сериализация
• Кеширование
• Паузы JVM, оптимизация GC
Факты об ОК
• 8000 серверов
• 48 млн. уникальных пользователей в день
• 8 млн. пользователей онлайн
• 300 000 web запросов в секунду
• 4 ПБ данных (без учёта дублирования)
Экстремальные нагрузки
• На что способен один сервер
– 50,000 вызовов/с в сек (push delivery)
– 40 Гбит/с (video download)
– 100,000 пользователей онлайн (xmpp)
– 384 ГБ в памяти (cache)
• Это всё Java!
Архитектура ОК
Web
Web
Mobile
Mobile
API
API
Business
logic
Business
logic
Business
logic
Business
logic
Business
logic
Business
logic
GraphGraphGraph
GraphGraphMessaging
GraphGraphPhoto
GraphGraphFeed
BLOB
storage
SQL
servers
Cassandra
Services
Business layerFront-end
Storages
HTTP
RPC
RPC
Внутренняя коммуникация
• Удалённый вызов методов (RPC)
Business logic
server
Graph cluster
User service
cluster
long[] friendIds = getConnections (userId)
List<User> friends = getUsers (friendIds)
План доклада
• Архитектура ОК
• Работа с сетью
• Удалённые вызовы и сериализация
• Кеширование
• Паузы JVM, оптимизация GC
java.net.Socket I/O
• Поток на каждое соединение
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
}
}
Проблемы Socket I/O
• 10 тыс. соединений = 10 тыс. потоков
• Finalizers => утечка памяти
• byte[] массивы, копирование
NIO
while (true) {
if (selector.select() > 0) { // blocking call
for (SelectionKey key : selector.selectedKeys()) {
if (key.isReadable()) {
doRead(key);
} else if (key.isWritable()) {
doWrite(key);
}
}
selector.selectedKeys().clear();
}
}
• Selector + неблокирующие read/write
NIO frameworks
• Apache MINA
– http://mina.apache.org
• Netty
– http://netty.io
• Основаны на NIO
• Event-driven модель
Проблемы NIO
• Selector глючный, не потокобезопасный
• Нельзя делать select() на blocking сокетах
• Не работает setSoTimeout()
• Ограниченная поддержка SSL/TLS
• Не поддерживаются все возможности ОС
– TCP опции: TCP_DEFER_ACCEPT, TCP_CORK
– Флаги send/recv: MSG_MORE, MSG_PEEK
Решение
• JNI библиотека
– Tomcat Native (APR connector)
– one-nio
• Управление сокетами вручную
• Поддержка OpenSSL
Архитектура сервера
Acceptor thread
Selector 1
Selector N
Worker thread pool
NCPU
read
read
process write
process write
Пример сервера
public class MyHttpServer extends HttpServer {
public MyHttpServer() throws IOException {
super(new ConnectionString("https://0.0.0.0"));
}
@Path("/hello")
public Response hello() {
return Response.ok("Hello world");
}
public static void main(String[] args) throws Exception {
new MyHttpServer().start();
}
}
Пример клиента
public class MyHttpClient {
public static void main(String[] args) throws Exception {
HttpClient client = new HttpClient("https://localhost");
Response response = client.get("/hello");
System.out.println("Status: " + response.getStatus());
System.out.println(response.toString());
client.close();
}
}
План доклада
• Архитектура ОК
• Работа с сетью
• Удалённые вызовы и сериализация
• Кеширование
• Паузы JVM, оптимизация GC
RPC сценарий
Method m, Object[] args
Object result
long[] friendIds = graph.getFriends(userId);
Method m, Object[] args
byte[] request
Method m, Object[] args
Object result
byte[] response
Object result
Исполнение
Десериализация
Десериализация
Сериализация
Сериализация
Клиент Сервер
 0.4 мс
Сериализация
• Быстрая, компактная
• Минимум ручной работы
• Поддержка эволюции
– Java Serialization
– JBoss
– Thrift, Avro, Protobuf
– Kryo
one.nio.serial
• Массивы и коллекции
– count obj1 … objN
• Мапы
– count key1 value1 … keyN valueN
• Enum
– short ordinal()
• Externalizable
– readExternal / writeExternal
• Остальные Serializable
– non-static non-transient fields
Схема сериализации
• Serializer
– Long UID – хеш от имён, типов и порядка полей
• Repository
– Map<Class, Serializer> для сериализации
– Map<Long, Serializer> для десериализации
class Person {
String name = "Victor";
int yearOfBirth = 1980;
boolean married = true;
}
UID 19806 V i c t o r 1-18
String UID
Обмен схемами
1. Client  Server: request
2. Server throws SerializerNotFoundException ?
– Client  Server: provideSerializer(serializer)
– Goto 1
3. Deserialize response
4. Client throws SerializerNotFoundException ?
– Client  Server: requestSerializer(uid)
– Add to repository
– Goto 3
Особенности реализации на Java
• Чтение и запись private полей
– Reflection (медленно!)
– sun.misc.Unsafe
• Создание экземпляров класса
– sun.misc.Unsafe.allocateInstance()
– Генерация байткода: http://asm.ow2.org
• Обход Java верификатора
– Наследование sun.reflect.MagicAccessorImpl
План доклада
• Архитектура ОК
• Работа с сетью
• Удалённые вызовы и сериализация
• Кеширование
• Паузы JVM, оптимизация GC
Числа, которые нужно знать
L1 cache reference 0.5 ns
Main memory reference 100 ns
Compress 1K bytes w/ cheap algorithm 3,000 ns
Send 2K bytes over 1 Gbps network 20,000 ns
Read 1 MB sequentially from memory 250,000 ns
Round trip within same datacenter 500,000 ns
Read 1 MB sequentially from network 10,000,000 ns
Read 1 MB sequentially from disk 30,000,000 ns
Send packet CA->Netherlands->CA 150,000,000 ns
Кеширование
• Что кешировать?
– Данные из медленного хранилища (БД)
– Результаты вычислений
• Где кешировать?
– Java Heap (не подходит для объемов > 10 GB)
– Off-heap memory
Как выйти за пределы Heap
• Native код (JNI обертки над malloc / free)
– Платформозавимый
• ByteBuffer.allocateDirect
– Размер буфера ≤ 2 GB
– Освобождается автоматически при GC
– Освобождение вручную:
((sun.nio.ch.DirectBuffer) buf).cleaner().clean();
• Unsafe.allocateMemory / freeMemory
Решения для off-heap кешей
• JSR 107: javax.cache
– Ehcache, Coherence
• Apache DirectMemory
• MapDB
• Chronicle Map
• one-nio
Требования к кешам
• Ключи и значения произвольных типов
– Long, String, byte[], сериализованные объекты
• Быстродействие
• Атомарные операции: read-modify-write
• До 384 GB RAM, до 100 млн. объектов
• Экспирация по времени
• Вытеснение LRU
• Персистентность
Персистентность
• Решает проблему холодного старта
• 2 уровня
– Сохранение между перезапусками приложения
– Снимки на диске (snapshots)
• Создание снимков
– Stop-the-world
– По сегментам
– Copy-on-write (fork trick)
Shared Memory
• Механизм IPC
– Linux: /dev/shm
– Поддерживается sendfile()
• Создание объекта Shared Memory в Java
– new RandomAccessFile("/dev/shm/cache", "rw");
• Отображение в адресное пространство:
– FileChannel.map()  MappedByteBuffer
– 2GB, no unmapping
Mapping > 2GB
// Mapping
Method map0 = FileChannelImpl.class.getDeclaredMethod(
"map0", int.class, long.class, long.class);
map0.setAccessible(true);
long addr = (Long) map0.invoke(f.getChannel(), 1, 0L, f.length());
// Unmapping
Method unmap0 = FileChannelImpl.class.getDeclaredMethod(
"unmap0", long.class, long.class);
unmap0.setAccessible(true);
unmap0.invoke(null, addr, length);
Проблема абсолютных адресов
• Только относительная адресация
– Хранение смещений вместо адресов
• Relocation
– Сдвиг всех абсолютных адресов на старте
Распределение памяти
• Doug Lea’s malloc
• one.nio.mem.Malloc, MallocMT
16 24 32 48 … 256 384 … 1G
sz sz sz sz sz sz
Кеши в one-nio
SharedMemoryLongMap
Long  V
SharedMemoryStringMap
String  V
SharedMemoryBlobMap
Long  byte[]
OffheapBlobMap
byte[]  byte[]
OffheapMap
K  V
SharedMemoryMap
K  V
Устройство кеша
0 addr 0addr…
hashCode(key) % capacity
hash time next
key (?)
value
hash time 0
key (?)
value
0
hash time 0
key (?)
value
entry
Возможности кеша
• Потокобезопасность
– get, put, remove, lockRecordForRead/Write
• Прямой доступ к off-heap, сериализация
• Поддержка shared memory
• Стратегии очистки
– BasicCleanup (TTL), SamplingCleanup (LRU)
План доклада
• Архитектура ОК
• Работа с сетью
• Удалённые вызовы и сериализация
• Кеширование
• Паузы JVM, оптимизация GC
Паузы JVM
• Требования к latency
– хорошо: 100 мс
– плохо: 1 с
• GC
– ParNew
– CMS (initial mark, remark)
• G1 GC
– -XX:MaxGCPauseMillis=200
– Много улучшений в 8u40
Тюнинг GC
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintClassHistogramBeforeFullGC
-XX:+PrintClassHistogramAfterFullGC
-XX:+PrintPromotionFailure
Тюнинг GC
-XX:+UseConcMarkSweepGC
-XX:+ExplicitGCInvokesConcurrent
-XX:+CMSClassUnloadingEnabled (default in 8)
-XX:+UnlockDiagnosticVMOptions
-XX:ParGCCardsPerStrideChunk=32768
Тюнинг GC
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=75
-XX:CMSWaitDuration=10000
-XX:+CMSScavengeBeforeRemark
-XX:+ParallelRefProcEnabled
-XX:+CMSParallelInitialMarkEnabled (default in 8)
Паузы JVM
• VM operations
– Thread dump, heap dump, debugging
– Biased lock revocation (-XX:-UseBiasedLocking)
– Deoptimization
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
Safepoint sync
• Непрерываемые операции
– System.arraycopy(), clone(), ByteBuffer.get()
– MappedByteBuffer I/O
-XX:+SafepointTimeout
-XX:SafepointTimeoutDelay=1000
GC-friendly структуры
class Entry {
long key;
Object value;
}
Entry[] entries;
long[] keys;
Object[] values;
class Blob {
long offset;
int length;
byte[] sha1_hash;
}
class Blob {
long offset;
int length;
int hash0, hash1, hash2,
hash3, hash4;
}
GC-friendly структуры
class Props {
Map<String, String> map;
}
class Props extends HashMap<String, String>
• String  char[] или byte[]
• ByteBuffer wrappers
GC-friendly структуры
• LinkedList  ArrayList
• HashMap  open-address hash table
• Коллекции примитивов (Trove)
• BitSet(100 000)  100 x BitSet(1000)
Спасибо!
• Наш Open Source
– https://github.com/odnoklassniki
• Блог
– http://habrahabr.ru/company/odnoklassniki/blog/
• Контакты
– andrey.pangin@corp.mail.ru
• Работа в ОК
– http://v.ok.ru

Mais conteúdo relacionado

Mais procurados

Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
victor-yastrebov
 
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Ontico
 
Web осень 2013 лекция 1
Web осень 2013 лекция 1Web осень 2013 лекция 1
Web осень 2013 лекция 1
Technopark
 

Mais procurados (20)

Bytecode
BytecodeBytecode
Bytecode
 
Thread
ThreadThread
Thread
 
Проект «Одноклассники» Mail.Ru Group, Андрей Паньгин
Проект «Одноклассники» Mail.Ru Group, Андрей ПаньгинПроект «Одноклассники» Mail.Ru Group, Андрей Паньгин
Проект «Одноклассники» Mail.Ru Group, Андрей Паньгин
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
 
Как сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрееКак сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрее
 
Java threads - part 2
Java threads - part 2Java threads - part 2
Java threads - part 2
 
JRebel
JRebelJRebel
JRebel
 
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
 
Java 8. Thread pools
Java 8. Thread poolsJava 8. Thread pools
Java 8. Thread pools
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Java threads - part 3
Java threads - part 3Java threads - part 3
Java threads - part 3
 
Михаил Щербаков "WinDbg сотоварищи"
Михаил Щербаков "WinDbg сотоварищи"Михаил Щербаков "WinDbg сотоварищи"
Михаил Щербаков "WinDbg сотоварищи"
 
Zagursky
ZagurskyZagursky
Zagursky
 
Web осень 2013 лекция 1
Web осень 2013 лекция 1Web осень 2013 лекция 1
Web осень 2013 лекция 1
 
Парсим CSS: performance tips & tricks
Парсим CSS: performance tips & tricksПарсим CSS: performance tips & tricks
Парсим CSS: performance tips & tricks
 
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶ отладки в Tarantool
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶  отладки в TarantoolИнструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶  отладки в Tarantool
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶ отладки в Tarantool
 
JavaDay'14
JavaDay'14JavaDay'14
JavaDay'14
 
Практика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверПрактика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-сервер
 
WinDbg со товарищи
WinDbg со товарищиWinDbg со товарищи
WinDbg со товарищи
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 

Semelhante a Developing highload servers with Java

как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
rit2011
 
Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)
Andrey Smirnov
 
Hosting for forbes.ru_
Hosting for forbes.ru_Hosting for forbes.ru_
Hosting for forbes.ru_
drupalconf
 
андрей паньгин
андрей паньгинандрей паньгин
андрей паньгин
kuchinskaya
 
Анатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей СмирновАнатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей Смирнов
Ontico
 
Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)
Andrey Smirnov
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на Groovy
Regn
 
Как превратить приложение в платформу
Как превратить приложение в платформуКак превратить приложение в платформу
Как превратить приложение в платформу
Vadim Kruchkov
 

Semelhante a Developing highload servers with Java (20)

Tempesta FW: challenges, internals, use cases / Александр Крижановский (Tempe...
Tempesta FW: challenges, internals, use cases / Александр Крижановский (Tempe...Tempesta FW: challenges, internals, use cases / Александр Крижановский (Tempe...
Tempesta FW: challenges, internals, use cases / Александр Крижановский (Tempe...
 
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
как написать масштабируемую баннерокрутилку. денис бирюков, артем гавриченков...
 
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
Анатомия веб-сервиса, Андрей Смирнов (ex-Skype)
 
Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)Анатомия веб сервиса (HighLoad-2014)
Анатомия веб сервиса (HighLoad-2014)
 
Экстремальная оптимизация производительности на примере MongoDB Java Driver
Экстремальная оптимизация производительности на примере MongoDB Java DriverЭкстремальная оптимизация производительности на примере MongoDB Java Driver
Экстремальная оптимизация производительности на примере MongoDB Java Driver
 
Hosting for forbes.ru_
Hosting for forbes.ru_Hosting for forbes.ru_
Hosting for forbes.ru_
 
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
 
Семь тысяч Rps, один go
Семь тысяч Rps, один goСемь тысяч Rps, один go
Семь тысяч Rps, один go
 
андрей паньгин
андрей паньгинандрей паньгин
андрей паньгин
 
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
 
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
 
Анатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей СмирновАнатомия веб-сервиса, Андрей Смирнов
Анатомия веб-сервиса, Андрей Смирнов
 
Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)Анатомия веб-сервиса (РИТ-2014)
Анатомия веб-сервиса (РИТ-2014)
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
 
ECP и API управления процессами. InterSystems Meetup Sankt-Peterburg 2014
ECP и API управления процессами. InterSystems Meetup Sankt-Peterburg 2014ECP и API управления процессами. InterSystems Meetup Sankt-Peterburg 2014
ECP и API управления процессами. InterSystems Meetup Sankt-Peterburg 2014
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на Groovy
 
Как превратить приложение в платформу
Как превратить приложение в платформуКак превратить приложение в платформу
Как превратить приложение в платформу
 
Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Семинар 5. Многопоточное программирование на OpenMP (часть 5)Семинар 5. Многопоточное программирование на OpenMP (часть 5)
Семинар 5. Многопоточное программирование на OpenMP (часть 5)
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
 

Developing highload servers with Java