Прерывания или что такое MSI и MSI-X

Недавно довелось разбираться с проблемой производительности сетевой подсистемы Linux. Как и предполагалось проблема была связана с обработкой сетевых прерываний. Однако выяснилось что термин MSI-X знаком не всем и далеко не все понимают преимущества этой технологии и покупают карты где она не поддерживается.
Более того, при беглом осмотре выяснилось что далеко не все вендоры продают адаптеры с поддержкой MSI-X.
Но начну я как всегда издалека.

Обработка hardware прерываний всегда была “дорогой” операцией. “Дороговизна” связана как с большим количеством прерываний, так и со сложностями по распределению их обработки.
Проблема с количеством прерываний в Linux была частично решена с появлением NAPI: вместо прерывания по каждому событию, теперь драйвер сетевой карты самостоятельно забирает пришедшие пакеты из очереди карточки.Полноценная же возможность по распределению прерываний по cpu появилась лишь с приходом PCI 3.0 и MSI-X.Но сначала немного теории.

Обработка PCI прерываний
Изначально PCI шина была ограничена 4 линиями, выделенными под прерывания. Теоретически один PCI адаптер может использовать все 4 прерывания, но так-как эти прерывания являются общими для всех карт, то большинство PCI адаптеров использую лишь 1 прерывание.
Из-за того что PCI прерывания были общими для всех устройств на шине, для корректной обработки прерывания ОС была вынужденна запускать все обработчики данного прерывания.
Если же PCI устройство писало в память, то возникала проблема синхронизации и обработчик прерывания был вынужден проверять что данные действительно записаны в память. Это было необходимо т.к. прерывание посылалось по выделенным линиям и могло быть отправлено одновременно с операцией записи а значит и “прийти” на процессор до того как данные реально будут записаны в память. Проблема синхронизации решалась на уровне драйверов: необходимо считать регистр, тем самым убедиться что операция записи завершена. Это добавляло накладных расходов для обработчика прерываний и не делало его более производительным.
Все эти проблемы был призван решить MSI.

MSI
Если ранее за каждым устройством закреплялся свой номер запроса на прерывание (IRQ), то прерывание в случае MSI это запись по заранее определенному адресу. Благодаря этому отпадает необходимость в выделенных линиях для обработки прерываний и упрощается схема самого адаптера. Кроме того решается проблема с синхронизацией т.к. операция записи в память и прерывание теперь используют общий канал и более не могут прийти на процессор одновременно.
MSI позволяет использовать десятки прерываний. Точнее до 32. Однако более 16 прерываний использовались крайне редко.

MSI-X
В PCI 3.0 появилось расширение MSI : MSI-X позволило увеличить кол-во прерываний от одного устройства до 2048. Правда использование более 64 я не встречал. Но что более важно, MSI-X использует различные адреса записи для каждого прерывания, что позволило назначить обработку отдельный прерываний на определенный процессор.

APIC и распределение прерываний между CPU
APIC (Advanced Programmable Interrupt Controller) отвечает за распределение прерываний по процессорам. APIC предусматривает несколько различных политик распределения прерываний. Так первоначально все прерывания обрабатывались одним ( нулевым ) ядром.
За распределение прерываний по CPU отвечает чип IO-APIC. Этот чип может работать в 2 режимах :
fixed/physical mode: прерывания от каждого конкретного устройства обрабатываются конкретным CPU
logical mode: прерывания одного устройства могут обрабатываться несколькими CPU.
Применение logical mode в большинстве случаев не оправдано т.к. возникают проблемы cache miss’ов в случае работы с одной сущностью несколькими CPU ( например обработке прерываний несколькими CPU для одной tcp сессии ).
Попробую описать эту проблему детальнее. Итак у вас прерывания разбрасываются round-robin по нескольким CPU. Когда приходит первый пакет tcp сессии и генерируется прерывание, то оно обрабатывается процессором X. Второе прерывание о пакете, в рамках того же tcp соединения попало на процессор Y. Так как данных о данной сессии до этого на процессоре Y не было то никаких данных о ней CPU кеше нет Имеем cache miss на процессоре Y. При этом данные были в кеше процессора X и если бы прерывание попало на процессор X то обо было бы обработано быстрее. Теперь же данные о этой tcp сессии удаляются из кеша процессора X для обеспечения когерентности кешей. Однако следующее прерывание о новом пакете в рамках этой же tcp сессии снова попадает на процессор X и мы снова получаем cache miss…
Получается что с одной стороны выгодно распределять прерывания по всем CPU, чтобы CPU не было узким место и была равномерная загрузка CPU.
С другой стороны распределение прерываний по разным CPU безо всякой логики повышает кол-во cache miss. А это “дорогая” операция также оказывает влияние на производительность.

IO-APIC и MSI
На самом деле через IO-APIC будут распределяться либо прерывания “старого” типа (INT), либо MSI/MSI-X прерывания, для устройств, драйвера которых не реализовали поддержку MSI/MSI-X.
Как я описал выше MSI/MSI-X генерирует прерывания, посылая операцию записи с определенным адресом. Соответственно если драйвер не поддерживает MSI/MSI-X то будет использоваться некий стандартный адрес и прерывания будут попадать на IO-APIC и далее уже распределяться по LAPIC ( Local APIC ) разных CPU.
В случае же если в драйвере реализована поддержка MSI/MSI-X то при инициализации адрес может быть изменен, а значит прерывания будут попадать на определенный CPU в обход IO-APIC.

Так в чем же плюс MSI-X?
Помните предыдущий пример про tcp сессию,А что если бы сетевая карта “знала” о tcp сессиях и генерировала бы прерывания для того CPU, который и занимается обработкой данной tcp сессии? Это позволило бы решить и проблему с распределением прерываний по нескольким CPU при этом обеспечивая локальность обработки пакетов определенного типа.
Именно этого и позволяет добиться MSI-X.

Теперь о командах. lspci -t показывает список PCI устройств и мостов.
После чего в файле /sys/bus/pci/devices/*/msi_bus можно увидеть включена ли поддержка MSI: 1 – включена 0 – выключена.
Распределение прерываний по ядрам CPU вы можете посмотреть в файле /proc/interrupts . Там же можно увидеть используется ли IO-APIC для распределения прерываний, или же прерывания идут напрямую через MSI.
Для каждого прерывания есть директория в /proc/irq/ . В файле smp_affinity находится bitmap, который определяет каким ядром будет обрабатываться это прерывание. Меняя этот bitmap мы можем менять привязку прерываний к ядрам процессора.

О том как обработка MSI и MSI-X прерываний реализована в Solaris отлично написано здесь : в блоге Saurabh Mishra
и частично в блоге Charlie Chen здесь и здесь

Solaris 11 zones

Несмотря на то что Solaris zones появились в solaris 10 в 11 версии эта технология претерпела значительные изменения.
Однако большинство изменений произошли не в самой технологии, а были вызваны в ее тесной интеграции с другими фичами Solaris 11: системой управления пакетами (IPS) и файловой системой zfs.
Так в Solaris 11 зона может быть установлена только на файловую систему zfs. При этом исключительно в отдельный датасет.

Многие помнят что в Solaris 10 кроме обыкновенных (native) зон можно сделать так-называемые branded zones. Технология branded zone позволяет создавать зону с окружением эмулирующим другую ОС. В частности в Solaris 10 можно создать branded zone для Solaris 8 и 9 а также Linux.
Branded zones можно было создавать только whole-root. В solaris 11 все зоны используют технологию branded zones. Native зон теперь не существует. Поддерживается только 2 типа “брендов”: solaris для зон solaris 11, и solaris10 собственно для Solaris 10. Поддержки Linux, как и Solaris 9 не стало.

Кроме того если в Solaris 10 было 2 типа зон : sparce и whole-root то в 11 версии остался только один тип. Это ограничение новой системы управления пакетами (IPS) которая не поддерживает замонтированные через lofi директории (опция inherited-pkg-dir ) с файлами, входящими в тот или иной пакет.
Sparce зоны имели определенные преимущества перед whole root зонами. В большинстве случаев в зоне нет необходимости модифицировать /usr или /lib . По этому использование sparce зон было оправдано и позволяло не только сэкономить место на внутренних дисках, но и сделать все решение проще в администрировании и на мой взгляд более масштабируемым.
Кроме того root права для sparce зоны можно было безбоязненно передавать сторонним людям и не беспокоится за работоспособность и безопасность как зоны так и всего сервера. Тогда как в случае с whole-root зоной root пользователь мог легко довести зону до нерабочего состояния.
И хотя в Solaris 11 нет sparce зон, но создать зоны, со схожими характеристиками все же возможно. Так чтобы сэкономить дисковое пространство можно использовать дудупликацию на уровне zfs. А вот чтобы запретить в зоне модифицировать системные директории появилась новая фича : Immutable Zone, или read only zones.
Более подробно что это такое и как это настраивается в следующей статье.

BigData и с чем её едят

Сегодня на работе разгорелась небывалая дискуссия. Конечно же о модном нынче термине BigData. Большинство интересовал вопрос “А BigData это вообще сколько”, после чего люди называли самые большие числа, которые могли представить, и, вероятно представив такой объем данных, их глаза округлялись, появлялась улыбка и они уходили в забытье.
При этом мне показалось что понимание что же такое BigData и зачем оно нужно есть далеко не у всех.
Давайте разбираться.

Сейчас все кто только возможно говорят про BigData. Пожалуй уже даже больше чем про “облака”. Выступление любого вендора обязательно включает эти 2 слова 😉
При этом говоря о BigData часто говорят совершенно о разных технологиях : кто-то говорит про Hadoop и MapReduce, кто-то про NoSql, кто-то вообще о кластерных системах хранения.

Термин BigData пришел из интернет индустрии. Бизнес большинства интернет-компаний крутится вокруг аналитики. Google анализирует ваши поисковые запросы и предлагает вам рекламу тех товаров и услуг которые вероятно вам интересны. Похожим способом зарабатывает Yahoo, Yandex и Facebook. Все эти компании собирают как можно больше информации о вас чтобы предложить наиболее релевантную рекламу. Это не просто. Для этого требуется анализ большого массива данных о вас и данных о людях, с подобным вам поведением. Создание аналитических решений на данный момент фактически единственный способ заработка для подобных компаний. Это и есть “Bigdata technology”.

Теперь давайте посмотрим на рынок Enterprise решений. Есть ли там BigData? Безусловно!
Такие вещи как Business Intelligence, Decision Support и Data Mining and Analytics ( не уверен как правильно переводить на русский ) существуют в Enterprise’е достаточно давно.
Вот только спрос на действительно качественные решения из этой области очень не высок.
Примерно 6 лет назад стало понятно что стандартные базы данных не могут полноценно справиться с подобными задачами. Тогда на рынке начали появляться специфические решения для решения этой задачи: Teradata, Netezza, Greenplum, и прочие.

И все же большого распространения среди Enterprise компаний они не получили. Почему?

На мой взгляд в интернет-компаниях и в “традиционных” компаниях под аналитикой понимают несколько разные вещи. И если для интернет-компаний аналитика необходима для существования, то “традиционная” компания может продавать утюги и безо всякой аналитики. Да, аналитика может чем-то помочь. Но зарабатывать деньги без нее можно.

В основном аналитика в “традиционных” компаниях помогает принимать бизнесу те или иные решения. Т.Е. результаты аналитики предоставляются узкому кругу сотрудников самой компании.
Результаты же аналитики в интернет-компаниях предоставляются непосредственно потребителю. И если вдуматься разница в этих подходах колоссальная. Как на уровне источников данных, так и на уровне самих данных.

Так если для Enterprise аналитики источником данных служат в основном внутренние системы, то для “интернет-компаний” источник данных это действия пользователя. Причем чем больше данных сохраняется тем лучше: ведь тем детальнее может быть анализ!

Опять же так-как источник данных для Еnterprise компаний являются существующие базы данных, то и типы данных достаточно структурированы.
В случае же “интернет-компаний” тип данных сильно разниться и может меняться с такой же скоростью как и сами данные. В ответ на это появляется большое кол-во NoSQL баз.

И можно называть сколь угодно большие цифры, говоря о BigData, но важно понимать не то сколько у вас данных, а то что у вас за данные и что вы с этими данными планируете делать.

Настройка сети в Solaris 11

В отпуске наконец-то появилось время детальнее покопаться в новых фичах Solaris 11. В частности в том как устроена сетевая подсистема.
Сетевая подсистема претерпела большие изменения еще в 10 версии, но в 11 они приобрели законченный вид. Об изменениях на уроне ядра я постараюсь написать попозже. Сейчас же, коротко об изменениях в утилитах.
Если кто-либо считает, что настроить сеть в Solaris 10 было сложно, то он явно не делал этого в 11 версии.
В Solaris 10 для настройки сети использовалось несколько файлов и пара утилит. В крайнем случае, все можно было изменить динамически с помощью ifconfig. Оказывается, это было очень сложно. Чтобы упростить этот непростой процесс в Solaris 11, появились команды netadm, netcfg и ipadm и некоторые другие, а также пару демонов: netcfgd, nwamd.
Теперь по умолчанию для настройки сети используется новая фича NWAM ( Network Auto-Magic ), которая, в идеале, настроит сеть на сервере за Ва. А также автоматически перенастроит в случае каких-либо изменений. Здорово звучит не правда ли? Давайте разбираться

настройка NWAM Профиля

Посмотреть список профилей и локаций можно с помощью команды :

 netcfg list

Профиль описывает необходимые настройки сетевых адаптеров, сетевых интерфейсов и туннелей. Будьте внимательны: в 10 версии различие между адаптером и интерфейсом были столь незначительными, что многие объединяли эти понятия.
Профиль по умолчанию (Automatic) пытается получить адрес по dhcp по всем поднятым интерфейсам. Не очень типичная конфигурация для сервера. Давайте создадим профиль со статически настроенным адресом.
Сначала надо создать сам профиль и добавить в него физический интерфейс.

antony@sol11:~$ netcfg
netcfg> create ncp user
netcfg:ncp:user> create ncu phys net1
Created ncu 'net1'. Walking properties ...
activation-mode (manual) [manual|prioritized]> manual
link-mac-addr> 
link-autopush> 
link-mtu>
netcfg:ncp:user:ncu:net1> end
Committed changes

И только после того как в профиле есть интерфейс добавить в профиль ip адрес :

netcfg:ncp:user> create ncu ip net1
Created ncu 'net1'. Walking properties ...
ip-version (ipv4,ipv6) [ipv4|ipv6]> ipv4
ipv4-addrsrc (dhcp) [dhcp|static]> static
ipv4-addr> 192.168.56.2
ipv4-default-route>
netcfg:ncp:user:ncu:net1> list
 ncu:net1
 type interface
 class ip
 parent "user"
 enabled true
 ip-version ipv4
 ipv4-addrsrc static
 ipv4-addr "192.168.56.2"
 ipv6-addrsrc dhcp,autoconf
netcfg:ncp:user:ncu:net1> commit
Committed changes
netcfg:ncp:user:ncu:net1> end
netcfg:ncp:user> exit

Каждый профиль (NCP, Network configuration Profile ) должен содержать минимум 2 связанных NCU ( Network Configuration Unit ) :
– phys Описывающий настройки сетевого адаптера
– ip. Описывающий настройки интерфейса
Какую политику использовать задается в параметрах сервиса network/physical:default
Посмотреть, какая политика настроена сейчас :

svccfg -s network/physical:default listprop netcfg/active_ncp

Изменить :

svccfg -s network/physical:default setprop netcfg/active_ncp = user
svccfg -s network/physical:default refresh

При этом те интерфейсы, что были настроены профилем Automatic, не опустятся. Чтобы полностью перенастроить конфигурацию необходимо:

svcadm restart network/physical:default

И если все сделано правильно – то сеть поднимется. Очень просто, не правда ли? 😉
Все это описываю для того, чтобы было понимание, как именно настраивается сеть через NWAM. На самом деле, чтобы применить созданный Profile, достаточно одной команды:

netadm enable -p ncp user

Активный профиль можно также посмотреть в выводе этой команды:

antony@sol11:~$ netadm list
TYPE PROFILE STATE
ncp Automatic disabled
ncp user online
 ncu:phys net1 online
ncu:ip net1 online
loc Automatic offline
loc NoNet offline

С ключом -x можно посмотреть детальную информацию:

antony@sol11:~$ netadm list -x
 TYPE PROFILE STATE AUXILIARY STATE
ncp Automatic disabled disabled by administrator
ncp user online active
ncu:phys net1 online interface/link is up
 ncu:ip net1 online interface/link is up
loc Automatic online active
loc NoNet offline conditions for activation are unmet
NWAM Location

Надеюсь, с профилями более-менее разобрались. Теперь о Location’ах.
Если через профиль (NCP) настраивается ip адрес – то Location определяет остальные сетевые параметры, такие как: домен сервера, адреса DNS серверов, настройки IP filter и IPsec.
Вносить эти изменения через /etc/nsswitch.conf и прочие файлы теперь нельзя, так как содержимое этого файла автоматически генерируется из свойств сервиса. Сам же файл оставлен только для обратно совместимости.
Просмотреть настройки Locftion’а можно уже знакомой утилитой netcfg

antony@sol11:~$ netcfg list loc Automatic
loc:Automatic
 activation-mode system
 enabled false
 nameservices dns
 nameservices-config-file "/etc/nsswitch.dns"
 dns-nameservice-configsrc dhcp

Так как в данном location’е список dns сервров получается по dhcp, то в свойствах сервиса ничего нет.

antony@sol11:~$ svccfg -s svc:/network/dns/client listprop config
config application 
config/value_authorization astring solaris.smf.value.name-service.dns.client
antony@sol11:~$

Я не часто встречаю сервера, где все сетевые настройки получаются через dhcp.
Давайте создадим location, где dns сервера задаются статически :

antony@sol11:~$ netcfg 
netcfg> create loc user1
Created loc 'user1'. Walking properties ...
 activation-mode (manual) [manual|conditional-any|conditional-all]> manual
nameservices (dns) [dns|files|nis|ldap]> 
nameservices-config-file ("/etc/nsswitch.dns")> 
dns-nameservice-configsrc (dhcp) [manual|dhcp]> manual
 dns-nameservice-domain> pavlenko.net
dns-nameservice-servers> 8.8.8.8
dns-nameservice-search> 
dns-nameservice-sortlist> 
dns-nameservice-options> 
nfsv4-domain> 
 ipfilter-config-file> 
ipfilter-v6-config-file> 
ipnat-config-file> 
ippool-config-file> 
ike-config-file> 
ipsecpolicy-config-file> 
netcfg:loc:user1> list
loc:user1
 activation-mode manual
 enabled false
 nameservices dns
 nameservices-config-file "/etc/nsswitch.dns"
 dns-nameservice-configsrc manual
 dns-nameservice-domain "pavlenko.net"
 dns-nameservice-servers "8.8.8.8"
netcfg:loc:user1> commit
Committed changes
netcfg:loc:user1> quit
antony@sol11:~$

Теперь применяем данный location :

antony@sol11:~$ netadm enable -p loc user1
 Enabling loc 'user1'
antony@sol11:~$

В свойствах сервиса network/dns/client мы видим указанные в location’е настройки dns.

antony@sol11:~$ svccfg -s svc:/network/dns/client listprop config
 config application 
config/value_authorization astring solaris.smf.value.name-service.dns.client
config/domain astring pavlenko.net
 config/nameserver net_address 8.8.8.8
antony@sol11:~$

Location может быть активирован не только администратором, но и автоматически, при совпадении нужных условий. Например, можно настроить, чтобы при поднятии “внешнего” ip адреса автоматически включался ip filter с правильными параметрами.
Как настраивать сеть в Solaris 11 с помощью нового механизма NWAM – я вкратце описал.

Отключаем NWAM и делаем все по человечески

А теперь приз для тех, кто дочитал до этого места. Весь этот очень удобный механизм NWAM можно отключить.
Естественно, после этого вписать настройки в файлы, как и раньше в Solaris 10 все равно не получится.
Но настроить статическую конфигурацию можно достаточно быстро.
Существует специальный профиль: DefaultFixed. Применение данного профиля отключает NWAM. Конечно, документация советует отключать NWAM только в случае “если вы используете расширенные сетевые фичи, которые пока не поддерживаются NWAM”, но, на мой взгляд, все ровно наоборот. NWAM имеет смысл включать только в том случае, если вам действительно нужны эти фичи.
Итак отключаем NWAM :

netadm enable -p ncp DefaultFixed

Как проверить какой профиль используется – я писал выше. Еще не забыли?
Смотрим

svccfg -s network/physical:default listprop netcfg/active_ncp

После этого уже полюбившаяся нам команда netadm перестает наконец работать:

# netadm list
netadm: DefaultFixed NCP is enabled;
automatic network management is not available.
'netadm list' is only supported when automatic network management is active.

Ура!
Теперь смотрим, какие в системе есть сетевые интерфейсы и выбираем тот, что вам нужен.

antony@sol11:~$ dladm show-phys
LINK MEDIA STATE SPEED DUPLEX DEVICE
net0 Ethernet up 1000 full e1000g0
 net1 Ethernet up 1000 full e1000g1

Состояние интерфейсов можно посмотреть :

antony@sol11:~$ ipadm  show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       down     no     --
net1       ip       ok       yes    --
antony@sol11:~$

Если нужный вам интерфейс в dladm есть, а в ipadm нет, то добавляем его командой

 ipadm create-ip net1

В моем случае интерфейс есть.
Чтобы посмотреть, что уже настроен:

antony@sol11:~$ ipadm show-addr
ADDROBJ TYPE STATE ADDR
lo0/v4 static ok 127.0.0.1/8
lo0/v6 static ok ::1/128
antony@sol11:~$

И наконец, добавляем нужный нам адрес на выбранном интерфейсе :

ipadm create-addr -T static -a 192.168.56.102 met1/v4

Если все сделано правильно, то адрес станет доступен и появится в выводе ipadm :

 antony@sol11:~$ ipadm show-addr
ADDROBJ TYPE STATE ADDR
lo0/v4 static ok 127.0.0.1/8
net1/v4 static ok 192.168.56.102/24
 lo0/v6 static ok ::1/128
antony@sol11:~$

Как настраивать default route’ер, я надеюсь, все знают. Команда routeadm в Solaris 11 не изменилась.
Вместо правки /etc/nsswitch.conf, теперь настраиваем name service switch через сервис

antony@sol11:~$ svccfg -s name-service/switch
svc:/system/name-service/switch> setprop config/host = "files dns"

Если используется ldap то

svc:/system/name-service/switch> setprop config/password = "files ldap"

И так далее – настраиваем все необходимые опции. После того как все необходимые опции настроены :

svc:/system/name-service/switch> end
antony@sol11:~$ svcadm refresh name-service/switch
antony@sol11:~$ svcadm restart name-service/switch

Для обратной совместимости внесенные изменения также попадают в файл /etc/nsswitch.conf
Привыкнуть к свойствам сервиса получается не сразу. По этому, советую после внесения проверять, что все правильно настроено уже через файл. И при необходимости дальше менять свойства сервиса.
Вместо правки /etc/resolv.conf настраиваем dns тоже через сервис:

antony@sol11:~$ svccfg -s dns/client
svc:/network/dns/client> listprop config
config                      application
config/value_authorization astring     solaris.smf.value.name-service.dns.client
config/domain              astring     ie.oracle.com
 svc:/network/dns/client> setprop config/nameserver = (8.8.8.8 217.118.66.243)
svc:/network/dns/client> setprop config/domain = pavlenko.net
svc:/network/dns/client> listprop config
 config application 
config/value_authorization astring solaris.smf.value.name-service.dns.client
config/nameserver net_address 8.8.8.8 217.118.66.243
config/domain astring pavlenko.net
 svc:/network/dns/client> exit
antony@sol11:~$ svcadm refresh dns/client
antony@sol11:~$ svcadm restart dns/client

После этого /etc/resolv.conf также изменится.
Ну, вот и все. Просто – не правда ли?

Производительность java на серверах с процессором Niagara ( UltraSPARC T1/T2/T3 )

Эта bug’а известна с момента появления первого процессора Niagara но до сих пор большое количество java приложений испытывают проблемы с производительностью.
В чем суть проблемы?
Некоторые параметры зависят от типа оборудования. К примеру JVM выбирает тип сборщика мусора в зависимости от “железа”.
При старте JVM определяет что в сервере на базе Niagara много “процессоров”, а значит это сервер и в случае если тип gc не установлен в опциях то будет использоваться параллельный сборщик мусора. Этот GC создает несколько потоков. Количество потоков зависит от количества процессоров. ( Как я понимаю на текущий момент правильная формула такова : (ncpus <= 8) ? ncpus : 3 + ((ncpus * 5) / 8) )
Таким образом на сервере с процессорами Niagara у вас будет множество потоков GC. На самом деле это не проблема если запущено не много JVM’ов.
Но в случае если ваше приложение использует большое количество JVM’ов или же, к примеру, вы используете этот сервер для консолидации java приложений, то накладные расходы на столь значительное количество потоков может оказаться катастрофическим.
Недавно я видел сервер T5440 на котором было запущено 74 JVM. И этот сервер периодически странным образом “зависал”.
Да, это bug . Но и сейчас большое количество приложений использует старую версию JVM. И некоторые из этих приложений испытывают странные проблемы с производительностью…
Решение проблемы очень простое. Вы можете самостоятельно выставить количество потоков GC :

-XX:ParallelGCThreads= N

Для большинства приложений 4 будет хорошим значением для N .
Эта опция может не только решить проблему с производительностью но и высвободить часть ресурсов сервера.

Балансировка сетевого трафика в Solaris

Про этот блог забыли все, даже Я сам 😉
Попробую опубликовать хотя-бы то что что было написано достаточно давно но не опубликовано.
Уже очень давно состоялась встреча Московской группы пользователей OpenSolaris где в частности рассказывалось о способах балансировки сетевого трафика в Linux и FreeBSD. Однако выяснилось что ни кто не знает что в OpenSolaris также есть балансировки трафика.
В Solaris 10 действительно подобного функционала не было, однако в OpenSolaris был добавлен ILB ( Integrated Load Balancer ). Сейчас ILB уже включен в репозиторий Solaris 11 Express и думаю он будет входить в Solaris 11.
Давайте попробуем разобраться что такое ILB и как его настраивать.
Для начала необходимо проверить установлен ли ILB и если нет, то установить :

root@solaris:~# pkg search ilbadm
INDEX      ACTION VALUE           PACKAGE
basename   file   usr/sbin/ilbadm pkg:/service/network/load-balancer/ilb@0.5.11-0.151.0.1
root@solaris:~# man pkg
root@solaris:~# pkg install pkg:/service/network/load-balancer/ilb@0.5.11-0.151.0.1
               Packages to install:     1
           Create boot environment:    No
               Services to restart:     1
DOWNLOAD                                  PKGS       FILES    XFER (MB)
Completed                                  1/1       11/11      0.2/0.2

PHASE                                        ACTIONS
Install Phase                                  38/38 

PHASE                                          ITEMS
Package State Update Phase                       1/1 
Image State Update Phase                         2/2 

PHASE                                          ITEMS
Reading Existing Index                           8/8 
Indexing Packages                                1/1
root@solaris:~# 

Теперь ILB установлен и мы можем приступить к настройке балансировки.
Для этого надо стартовать демон ilb. Но перед этим надо поднять ip forwarding. Если забыть это сделать то вывод ilbadm вам сразу же подскажет что не так :

root@solaris:~# ilbadm show-rule
ilbadm: socket() failed
root@solaris:~#

В чём ошибка очевидно, не правда ли? 😉
Итак стартуем ip forwarding :

root@solaris:~# svcadm enable svc:/network/ipv4-forwarding
root@solaris:~# svcadm enable svc:/network/loadbalancer/ilb:default

ILB поддерживает 3 режима балансировки :
– DST
– Полный NAT
– Частичный NAT
В режиме DSR ( Direct Server Return ) ILB балансирует входящий трафик между back-end серверами. При этом ответы от back-end серверов идут напрямую клиенту в обход балансировщика.
Режимы основанные на NAT балансировщик обрабатывает как входящий так и исходящий трафик меняя IP адреса в заголовках IP пакетов.
В случае Full-NAT происходит замена и source и destination адреса. Т.Е. заголовок IP пакета выглядит так, как будто back-end сервера получают трафик непосредственно от балансировщика.
Клиенты также будут получать ответы из заранее настроенного диапазона IP адресов. Например от самого балансировщика.
В случае с Half-NAT ILB меняет лишь destination IP.
Чтобы попробовать ILB я взял 3 сервера. Два из них я использовал как back-end сервера. Их адреса : 192.168.57.102 и 192.168.57.103. На них я поднял nginx. Третий сервер выступал балансировщиком. Его адрес : 192.168.57.101.
Чтобы ILB работать, ему надо указать на какие back-end сервера его балансировать. Для этого необходимо создать серверную группу :

root@solaris:~# ilbadm create-servergroup -s servers=192.168.57.102:80,192.168.57.103:80 websg
root@solaris:~# ilbadm show-servergroup
root@solaris:/tmp# ilbadm show-sg
SGNAME         SERVERID            MINPORT MAXPORT IP_ADDRESS
websg          _websg.0            80      80      192.168.57.102
websg          _websg.1            80      80      192.168.57.103

После создается само правило, по которому будет балансироваться трафик. Для начала я настроил Full-NAT:

root@solaris:/tmp# ilbadm create-rule -e -i vip=192.168.56.101,port=80 -m lbalg=rr,type=NAT,proxy-src=192.168.56.101 -o servergroup=websg webrule
root@solaris:/tmp# ilbadm show-rule
RULENAME            STATUS LBALG       TYPE    PROTOCOL VIP         PORT
webrule             E      roundrobin  NAT     TCP  192.168.56.101  80

и это всё!
Я настроил чтобы http трафик на to 192.168.56.101 ( виртуальный IP ) балансировался между двумя другими серверами. Запросы будут обрабатываться back-end серверами по очереди (round-robin). Ответы же будут приходить от адреса 192.168.56.101.
Теперь давайте поменяем правило с Full-NAT на Half-NAT :

ilbadm  delete-rule -a
ilbadm create-rule -e -i vip=192.168.56.101,port=80 -m lbalg=rr,type=h -o servergroup=websg webrule
root@solaris:/tmp# ilbadm show-rule
RULENAME            STATUS LBALG       TYPE    PROTOCOL VIP         PORT
webrule             E      roundrobin  HALF-NAT TCP 192.168.56.101  80

Всё это очень просто настраивается. При этом есть большое количество разнообразных опций. Так например можно изменить алгоритм балансировки запросов между back-end серверами. Кроме того средствами ILB можно настроить мониторинг back-end серверов Кроме того поддерживается Session persistence и Connection draining.

внутренности ufs

Так как про fsdb для файловой системы vxfs я уже писал, то решил описать и fsdb для ufs, ведь вопросы иногда возникают, несмотря на возраст файловой системы и относительно полный man.
При работе с fsdb надо быть очень аккуратным. Одно неверное движение и данных как не бывало.
Запускаем fsdb c возможностью записи :

fsdb -o w /dev/rdsk/_your_file_system_

У fsdb своеобразный синтаксис, похожий на adb. Все команды начинаются с :
Так например есть команда :ls
Также будет работать :ls /
Не стоит забывать, что / это именно корень файловой системы и если вы открыли с помощью fsdb var то это будет именно корень файловой системы
var а ни в коем случае не корневой файловой системы.
Тут у :ls есть всего 2 опции -l выводит список вместе с номером inod’а и -R делает рекурсивный листинг.
Так как есть :ls то есть и :cd
Также есть очень полезная команда :base . С помощью ее можно поменять шестнадцатеричную систему (по умолчанию) на десятеричную. Делается это так :

:base=0t10

В fsdb есть понятие “точка”. То есть вы сначала выбираете объект, с которым хотите работать, тем самым присваиваете точке его адрес. Все же последующие команды будут выполняться относительно значения “точки”
Так если вы хотите что-то сделать с 5 inode’ом, то сначала вы его выбираете.
Делается так

 5:inode

Далее вы можете вывести информацию об этом inode :

?i

Эти две команды можно объединить в одну :

5:inode?i

/dev/rdsk/c1t3d0s0 > 5:inode?i
i#: 5 md: d---rwxr-xr-x uid: 0 gid: 3
ln: 4 bs: 2 sz : c_flags : 0 200

db#0: 2fc
accessed: Wed Apr 29 16:24:50 2009
modified: Wed Feb 25 13:40:05 2009
created : Wed Feb 25 13:40:05 2009

Думаю вывод всем понятен. Возможно лишь стоит уточнить значение поля db. DB расшифровывается как direct block. Именно в db и записываются сами данные. Как я надеюсь все помнят inode ufs имеет 12 direct block’ов и 3 indirect block’ов. IB это блок, в котором содержаться не данные, а до 2048 адресов других блоков. Причем только первый ib будет содержать ссылки на db. Если же этого не хватает, то будет использован второй, так называемый double indirect block, который содержит 2048 ссылок на ib, которые уже содержат ссылки непосредственно на db. Вот Соответственно третий ib это triple indirect block и что там содержится думаю понятно.
Если вернуться к нашему случаю, то мы видим что inode состоят из одного db ( нулевого ) в блоке 2fc.
Но мы отвлеклись.
Файл это или директория можно понять по полю md (mode). Если флаг d есть, значит директория, если нет, то файл 😉
Если оказывается что это директория :ls покажет вам в ней есть.

Я надеюсь все помнят что такое директория в ufs. Это ни что иное как массив, где перечислены соответствие inode определенному имени файла.
Так после того, как вы выбрали inode , который является директорией, вы можете посмотреть и изменить эти поля.
:ls собственно эти записи вам и показывает, но вот только немного не в том порядке. В “том” порядке это можно сделать вот так :

0:dir?d
1:dir?d
2:dir?d

Чтобы все время это не вводить достаточно лишь просто нажимать Enter и
будет выполняться :dir?d к следующему элементу.

Ну или чтобы вывести 20 записей, хранящиеся в 0 блоке 2 inode’а :

2:ino; 0:db:block,20?d

Или же

 308:fragment,20?d

Если вы вдруг захотите, чтобы какая-то из записей (допустим пятая) указывала не на 22 inode а к примеру на 66 то все в ваших руках 😉
Делается это так :

5:dir?d=42

так как 42 – 66 в hex

Заметьте, что при этом название у директории/файла сохраниться прежнее, но вот указывать она уже будет в другое место.
Если же вы хотите и название поменять, то это тоже крайне просто :

 5:dir:nm="test"

вуаля и имя и записи меняется.

С директориями разобрались. Теперь к файлам.
В общем-то все тоже самое.

/dev/rdsk/c1t3d0s0 > :ls -l /etc/passwd
/etc:
i#: a317 passwd
/dev/rdsk/c1t3d0s0 > 0xa317:inode?i
i#: a317 md: ----rw-r--r-- uid: 0 gid: 3
ln: 1 bs: 2 sz : c_flags : 0 395

db#0: 6a8db
accessed: Wed Apr 29 16:20:06 2009
modified: Mon Apr 27 11:59:48 2009
created : Mon Apr 27 11:59:48 2009

/dev/rdsk/c1t3d0s0 > 0:db:block,100/c

И мы видим содержание /etc/passwd, Можем ли мы что-то поменять? Безусловно!
Это можно сделать несколькими способами.
Заполнить часть файла нулями :

6a889:fragment,4=fill=0x0

Или же просто записать в определенный адрес :

1aa22400=0xffff

А если нужно записать текст, то можно сделать вот так :

1aa36c00="root"

Итак, какой же самый простой способ удалить inode на незамонтированной файловой системе? Конечно же используя команду clri 🙂

Какие процессы в свопе? (поле w в vmstat )

В выводе vmstat есть несколько полей, которые трудно интерпретировать.
Поле w – одни из них. Да, из мануала мы знаем, что это “the number of swapped out lightweight processes (LWPs) that are waiting for processing resources to finish.” Так и что же стоит делать если это значение не нулевое?
Чаще всего это значит что серверу не хватает оперативной памяти. Но что же делать если эта проблема решена, а значение так и не изменилось?

bash-3.2# vmstat 5                                                                              
kthr      memory            page            disk          faults     cpu
r b w   swap  free  re  mf pi po fr de sr s6 sd sd sd   in   sy   cs us sy id
0 0 84 5041144 290400 1  6  0  0  0 1176 0 0  0  0  7 4231  164  838  0 2 98                       
0 0 84 5041136 290456 0  0  0  0  0 376 0  0  0  0  0 4228  148  575  0 2 98
0 0 84 5041136 290456 0  0  0  0  0  0  0  0  0  0  0 4232  162  579  0 2 98
0 0 84 5041128 290448 0  0  0  0  0  0  0  0  0  0  0 4227  149  637  0 2 98

Для начала давайте посмотрим lwp каких процессов засвопились:

echo "::walk thread thr |::print kthread_t t_schedflag|::grep .==0 |::eval p_pidp->pid_id" | mdb -k

Или же сразу выведем команду :

echo "::walk thread thr |::print kthread_t t_schedflag|::grep .==0 |::eval p_user.u_comm" | mdb -k

Итак мы знаем lwp каких процессов до сих пор в свопе. И если это число в выводе vmstat не растёт, то и проблем на сервере, скорее всего, тоже нет, но почему-то для многих людей это поле как красная тряпка для быка. Для того, чтобы lwp процесса перешли в нормальное состояние надо чтобы они что-то выполнили. Для этого, например, некоторым приложениям можно послать SIGHUP. Но проще всего конечно-же просто запустить truss на это приложение. truss’у будут нужны некоторые данные о процессе, и тем самым он перейдет обратно, в нормальное состояние.

Automount и новые nfs’ные шары

Automount вещь очень удобная, но у нее есть ряд неприятных багов.
Так если вы уже используете automount для доступа к nfs’ным шарам с сервера host1 и позже расшариваете еще одну директорию, то вы не сможете ее увидеть используя аutomount.
Это хорошо известная бага и похоже она уже никогда не будет закрыта. Но решить эту проблему очень просто. Вы можете использовать большие буквы и automount выдаст вам эту новую шару.

host1# ls /net/host2/opt/
dir1

Итак в каталоге opt расшарена только одна директория.

host2# share /opt/dir2
host1# ls /net/host2/opt/
dir1

Но мы все еще не можем получить доступ к dir2. Однако если попробовать Host2 ( большая буква H ):

host1# ls /net/Host2/opt/
dir1 dir2

И все заработало