андрей паньгин
DESCRIPTION
TRANSCRIPT
Особенности разработки сервера на Java
Архитектура Одноклассников
Сокеты в Java: проблемы и решения
Альтернативный механизм сериализации
Кеширование данных и разделяемая память
2
Серверы Одноклассников
• 4000 серверов
• Web, Business logic, Download, Storage, Remote Services
• Все ПО написано на Java
Высоконагруженный сервер
• 20 тыс. одновременных подключений
• 30 тыс. запросов в секунду
• Трафик до 1 Gb/s
3
Remote Service
• Компоненты портала как отдельные сервисы:
система сообщений, граф дружб, поиск, лента и т. д.
• Внутренняя коммуникация между сервисами
4
Business logic server
Graph cluster
User service cluster
long[] friendIds = getConnections (userId)
List<User> friends = getUsers (friendIds)
RPC сценарий
5
Read Request
Deserialize arguments
Invoke method
Serialize result
Send response
Object result = method.invoke(args);
byte[] request = connection.read(…);
request → Method method, Object[] args
result → byte[] response
connection.write(response);
Особенности разработки сервера на Java
Архитектура Одноклассников
Сокеты в Java: проблемы и решения
Альтернативный механизм сериализации
Кеширование данных и разделяемая память
6
Разработка сервера на Java
• java.net (Socket I/O) – Поток на каждое соединение
– Максимум 10 тыс. потоков
• NIO – Неблокирующие операции read / write
– Selector
• NIO frameworks – Apache MINA: http://mina.apache.org
– Netty: http://netty.io
7
Blocking Socket Selector (BLOS)
• Сочетает преимущества Selector + Blocking I/O
• Поддерживается на уровне ОС, но не в Java
• JNI обертки над системными вызовами – Socket → SocketImpl impl → FileDescriptor fd → int fd
8
Linux BSD Solaris Windows
epoll kqueue /dev/poll Completion ports
Архитектура BLOS сервера
9
Acceptor thread
Selector 1
Selector 2
read deserialize invoke serialize send
read deserialize invoke serialize send
Worker thread pool
Проблемы работы с сетью в Java
• Socket – Finalizers => утечка памяти, влияние на GC
– Не поддерживается прямой доступ к памяти (Direct ByteBuffers)
• SocketChannel (NIO) – Не срабатывают таймауты на I/O операциях
– Возможна утечка нативной памяти
• Решение: JNI библиотека – Такой подход используется в Tomcat (APR + Tomcat native)
– Управление сокетами вручную
10
Особенности разработки сервера на Java
Архитектура Одноклассников
Сокеты в Java: проблемы и решения
Альтернативный механизм сериализации
Кеширование данных и разделяемая память
11
Важность сериализации в RPC
• Затрачиваемое время на кодирование и декодирование
• Объем передаваемых по сети данных
12
Read Request
Deserialize arguments
Invoke method
Serialize result
Send response
Способы сериализации в Java
• Стандартная Java сериализация – Медленная
– Большой объем получаемых данных
• JBoss serialization – Не поддерживает простые изменения внутри класса:
добавление поля, удаление, изменение типа или порядка полей
• Avro, Thrift, Protocol Buffers
• Ручная сериализация – Externalizable – Не вариант (тысячи классов!)
13
Архитектура сериализации
• Типы сериализаторов – Встроенные (примитивные типы, массивы, коллекции)
– Сериализатор класса по полям
• Каждому сериализатору сопоставляется уникальный
64-битный ID – хеш от имен, типов и порядка полей
14
UID 2012 7 m a i l . r u 1
class Event { String site = “mail.ru”; int year = 2012; boolean started = true; }
Процедура сериализации
• Запись объекта: 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);
3. Object obj = serializer.read(inputStream);
15
may throw SerializerNotFoundException
Особенности реализации в Java
• Чтение и запись private полей чужих классов – Reflection (медленно!)
– sun.misc.Unsafe
• Создание экземпляров класса – sun.misc.Unsafe.allocateInstance()
– Динамическая генерация байткода
ASM framework: http://asm.ow2.org
• Обход Java верификатора – Наследование “магического” класса sun.reflect.MagicAccessorImpl
16
Производительность
• Среднее время запроса: -20%
• Сетевой трафик: -50%
17
Особенности разработки сервера на Java
Архитектура Одноклассников
Сокеты в Java: проблемы и решения
Альтернативный механизм сериализации
Кеширование данных и разделяемая память
18
Что кешировть?
• Данные из медленного хранилища (БД)
• Результаты вычислений
Где кешировть?
• В оперативной памяти – Java Heap (не подходит для объемов > 10 GB)
– Off-heap memory
• На диске или флеш-накопителе
19
Доступ к off-heap памяти в Java
• Native код (JNI обертки над malloc / free) – Платформозавимый
• ByteBuffer.allocateDirect – Размер буфера ≤ 2 GB
– Освобождается автоматически при GC
– Освобождение вручную: ((sun.nio.ch.DirectBuffer) buf).cleaner().clean();
• MappedByteBuffer (FileChannel.map)
• Unsafe.allocateMemory
20
Снимки (shapshots)
• Решают проблему холодного старта
• Должны быть целостными
• Способы создания снимков – “Stop-the-world”
– Запись по сегментам
– Memory-mapped files (MappedByteBuffer.force)
– Copy-on-write (fork trick)
– Shared memory objects
21
Shared Memory
• Механизм IPC – POSIX: shm_open + mmap
– Windows: CreateFileMapping + MapViewOfFile
– Linux: /dev/shm
• Создание объекта Shared Memory в Java
– new RandomAccessFile("/dev/shm/cache", "rw");
• Отображение в адресное пространство процесса
– легальный способ: FileChannel.map
– хитрый способ: sun.nio.ch.FileChannelImpl, методы map0 и unmap0
22
Реализация off-heap кеша в Java
на примере download сервера
• Непрерывная область памяти с собственным аллокатором
• FIFO (проще, чем LRU)
• sun.misc.Unsafe (самый быстрый способ доступа)
• Shared Memory (/dev/shm)
• Сегментирование ключей по хеш-коду
• Блокировка сегмента через ReadWriteLock / Semaphore
23
Структура кеша
24
Сравнение производительности
• Условия – Linux JDK7u4 64-bit
– 1 млн. операций
– Значения от 0 до 8 KB
25
Примеры
• https://github.com/odnoklassniki/shared-memory-cache.git
• https://github.com/odnoklassniki/rmi-samples.git
Статьи
• http://habrahabr.ru/company/odnoklassniki/blog/148139/
Контакты
• www.odnoklassniki.ru/ap
26