1. Обзор основ Linux
1. Пространство пользователя и пространство ядра
Теперь операционная система использует виртуальную адресацию, процессор сначала генерирует виртуальный адрес, транслирует адрес в физический адрес (адрес памяти), затем передает его по шине и, наконец, процессор получает байт, возвращаемый определенным физическим адресом.
Для 32-битной операционной системы ее адресное пространство (виртуальное пространство для хранения) равно 4G (2 в 32-й степени). Ядром операционной системы является ядро, которое не зависит от обычных приложений и может обращаться к защищенному пространству памяти, а также имеет все разрешения для доступа к нижележащим аппаратным устройствам.
Чтобы гарантировать, что пользовательский процесс не может напрямую управлять ядром и обеспечить безопасность ядра, система беспокойства делит виртуальное пространство на две части: одна — пространство ядра, а другая — пространство пользователя.
Для операционной системы линукс:
Самый старший байт 1G (от виртуального адреса 0xC0000000 до 0xFFFFFFFF) используется ядром, которое называется пространством ядра.
Нижние байты 3G (от виртуального адреса 0x00000000 до 0xBFFFFFFFF) используются каждым процессом, что называется пользовательским пространством.
2. Прямой ввод-вывод и кэшированный ввод-вывод
Файловая система ввода-вывода делится на DirectIO (прямой ввод-вывод) и BufferIO (буферизованный ввод-вывод), из которых BufferIO также называется обычным вводом-выводом (стандартный ввод-вывод). Операцией ввода-вывода по умолчанию для большинства файловых систем является кэшированный ввод-вывод.
Кэшированный ввод-вывод
операция чтения: Операционная система проверяет, есть ли в буфере ядра необходимые данные.Если они были закэшированы, они будут возвращены непосредственно из кеша, в противном случае они будут прочитаны с диска и затем закэшированы в кеше операционной системы.
операция записи: Копирует данные из пространства пользователя в кэш в пространстве ядра. В это время операция записи для программы пользователя завершена, и время записи на диск определяется операционной системой, если явно не вызывается команда синхронизации.
кwriteНапример, данные будут сначала скопированы в буфер процесса, затем скопированы в буфер ядра операционной системы, а затем записаны на устройство хранения.
Прямой ввод-вывод (меньше копирования в буфер процесса приложения)
3. Блокировка и синхронизация
1) Блокировка (Block)/Не сдача в аренду (NonBlock)
Блокировка и неблокировка — это способ обработки того, готовы ли данные, когда процесс обращается к данным, например, когда данные не готовы.
блокировать: часто необходимо дождаться готовности данных в буфере перед обработкой других вещей, иначе они всегда будут ждать там.
неблокирующий: Когда наш процесс обращается к нашему буферу данных, если данные не готовы, он вернется напрямую, без ожидания. Если данные готовы, также вернитесь напрямую.
Блокировка и неблокировка связаны с состоянием программы во время ожидания результата (сообщения, возвращаемого значения).
2) Синхронизация/Асинхронизация
И синхронные, и асинхронные основаны на том, как частная операционная система приложения обрабатывает события ввода-вывода, такие как
Синхронизировать: это операция, в которой приложение должно непосредственно участвовать в операциях чтения и записи ввода-вывода.
асинхронный: все операции чтения и записи IO передаются операционной системе для обработки, и приложению нужно только дождаться уведомления.
Синхронный метод При обработке событий ввода-вывода вы должны заблокировать метод, чтобы дождаться завершения наших событий ввода-вывода (блокировка событий ввода-вывода или опрос событий ввода-вывода).
В асинхронном режиме все операции чтения и записи операций ввода-вывода передаются операционной системе. В это время мы можем делать другие вещи, не завершая реальную операцию ввода-вывода.Когда операция завершит ввод-вывод, наше приложение получит уведомление.
Синхронный и асинхронный фокус на механизмах передачи сообщений.
2. Общие модели ввода-вывода
Для доступа IO он проходит две фазы:
- Ожидание готовности данных
- Действие: копирование данных из ядра в процесс
Например:
Функция чтения: разделена на ожидание читаемости системы и реальное чтение.
Функция записи: она разделена на ожидание записи сетевой карты и реальную запись.
иллюстрировать:
Блокировка ожидания готовности не использует ЦП, это «ожидание».
Настоящая блокировка операций чтения и записи использует ЦП, который действительно «работает», и этот процесс очень быстрый, относящийся к копированию памяти, а пропускная способность обычно выше уровня 1 ГБ / с, что можно понимать как в основном не время -потребление.
На следующем рисунке показано сравнение нескольких распространенных моделей ввода-вывода.:
В традиционном BIO socket.read(), если в TCP RecvBuffer нет данных, функция будет заблокирована до тех пор, пока данные не будут получены, а прочитанные данные будут возвращены.
Для NIO, если в TCP RecvBuffer есть данные, данные считываются с сетевой карты в память и возвращаются пользователю; в противном случае он возвращает 0 напрямую и никогда не блокируется.
Последний AIO (ASYNC I / O) будет идти дальше: не только ждет готовности не блокировки, но даже процесс данных с сетевой карты к памяти асинхронно.
Другими словами, пользователей в BIO больше всего беспокоит «я хочу читать», пользователей в NIO больше всего беспокоит «я умею читать», а в модели AIO пользователям нужно уделять больше внимания «законченному чтению».
Важной особенностью NIO является то, что основные функции чтения, записи, регистрации и получения сокетов неблокируются на этапе ожидания готовности, а реальные операции ввода-вывода синхронно блокируются (потребляя ЦП, но с очень высокой производительностью).
3. Что такое БИО, НИО, АИО
1. Синхронный блокирующий ввод-вывод (BIO)
Синхронный блокирующий ввод/вывод, режим реализации серверасоединение нить, то есть когда у клиента есть запрос на соединение, серверу нужно запустить поток для обработки.Если соединение ничего не делает, это вызовет ненужные накладные расходы потока, которые можно улучшить с помощью механизма пула потоков.
Метод BIO подходит для архитектуры с относительно небольшим количеством соединений и фиксированным числом соединений.Этот метод предъявляет относительно высокие требования к ресурсам на стороне сервера, а параллелизм ограничен приложениями.До jdk1.4 это был единственный IO вариант, но программа интуитивно понятна и проста в понимании.
БИО схема:
Псевдоасинхронная модель ввода-выводаТакже известна как модель обслуживания клиентов M:N. То есть потоки M используются для обслуживания соединений N клиентов в виде модели пула потоков; размер M может быть установлен на максимальное значение в соответствии с конфигурацией сервера, а количество клиентов, которое может быть обслуживаемых N может быть намного больше, чем M. Таким образом, чтобы повысить эффективность обслуживания сервера и улучшить использование потоков. Аналогичен модели BIO, за исключением того, что после принятия клиентского запроса Акцептор больше не запускает поток самостоятельно для обработки, а передает клиентский запрос в пул потоков для обработки, тем самым уменьшая количество создаваемых потоков, улучшая использование потока, и увеличение вычислительной мощности сервера;
Диаграмма псевдоасинхронного ввода-вывода
2. Синхронный неблокирующий I / O (NIO)
Синхронный неблокирующий ввод/вывод, режим реализации сервераодин запрос на поток, то есть запросы на подключение, отправленные клиентом, будут зарегистрированы на мультиплексоре, и мультиплексор будет запускать поток для обработки только тогда, когда к нему будет подключен запрос ввода-вывода после опроса. Метод NIO подходит для архитектур с большим количеством подключений и относительно короткими подключениями (легкая операция), таких как чат-серверы, где параллелизм ограничен приложениями, а программирование сложнее, и jdk1.4 начал его поддерживать.
Модель мультиплексирования ввода/вывода
Мультиплексирование ввода-вывода: ввод-вывод относится к нашему сетевому вводу-выводу, мультиплексирование относится к нескольким соединениям TCP (или нескольким каналам), а мультиплексирование относится к мультиплексированию одного или небольшого количества потоков. Понимание строки заключается в том, что многие сетевые операции ввода-вывода мультиплексируют один или небольшое количество потоков для обработки этих соединений.
Преимущество мультиплексирования не в том, что одно соединение может быть обработано быстрее, а в том, что можно обработать больше соединений.
В настоящее время широко используются три модели мультиплексирования ввода-вывода: выбор, опрос и epoll.
Мультиплексирование ввода-вывода — это механизм, с помощью которого процесс может отслеживать несколько дескрипторов.Когда дескриптор готов (обычно готов к чтению или записи), он может уведомить программу о выполнении соответствующих операций чтения и записи. Но select, poll и epoll по сути являются синхронным вводом-выводом, потому что все они должны отвечать за чтение и запись после того, как события чтения и записи готовы, то есть процесс чтения и записи блокируется, а асинхронный ввод-вывод /O не требует собственного Отвечает за чтение и запись, реализация асинхронного ввода-вывода будет отвечать за копирование данных из ядра в пространство пользователя.
jdk1.4 — используемая модель выбора/опроса
После jdk1.5 выбор/опрос был изменен на модель epoll.
1) выбрать модель
Файловые дескрипторы (fd) каждого клиентского соединения, то есть сокеты, складываются в набор.После вызова функции select она всегда будет следить, какие из этих файловых дескрипторов доступны для чтения.Если есть читаемые дескрипторы, то Наш рабочий процесс читает ресурс.
В функции SELECT мы говорим ядро файловых дескрипторов в разных состояниях, которые необходимо отслеживать, и приемлемый период ожидания. Функция возвращает количество готовых дескрипторов во всех состояниях и может найти готовные дескрипторы файлов, пересекающие FDSET.,
Существующие проблемы:
- Каждый раз, когда вызывается select, набор отслеживаемых fds необходимо копировать из пользовательского состояния в состояние ядра.Когда fd велико, накладные расходы очень велики.
- Каждый раз, когда вызывается select, необходимо опрашивать все fds, чтобы проверить состояние готовности. Эти накладные расходы также велики, когда имеется много fd.
- Максимальное количество файловых дескрипторов, поддерживаемых select, ограничено, по умолчанию 1024.
2) модель опроса
По сравнению с select, poll не имеет ограничения на максимальное количество файловых дескрипторов.
3) модель эполла
epoll был официально предложен в ядре Linux 2.6, и это метод ввода-вывода, управляемый событиями.По сравнению с select, epoll не имеет ограничений на количество дескрипторов.Он использует один файловый дескриптор для управления несколькими дескрипторами и описывает файлы, которые пользователи заботятся о событиях. События символа хранятся в таблице событий ядра, так что копирование в пространство пользователя и пространство ядра нужно сделать только один раз (это можно понимать как общую память, которая не принадлежит ни пользователю, ни пользователю). режим, ни режим ядра).
Усовершенствованная версия select/poll, которая может значительно улучшить использование системного ЦП программами с несколькими активными подключениями среди большого количества одновременных подключений. Причина в том, что при получении события ему не нужно проходить весь набор дескрипторов прослушивания, а нужно только проходить наборы дескрипторов, которые асинхронно пробуждаются событием ввода-вывода ядра и добавляются в очередь Ready.
Преимущества эполла:
- Избегайте копий на уровне памяти
- Управляемый событиями (не опрашиваемый)
Но не во всех случаях epoll лучше, чем select/poll, например в следующих сценариях:
В случае, если большинство клиентов активны, система разбудит все callback-функции, что приведет к высокой нагрузке. Поскольку необходимо обработать так много подключений, обход select/poll проще и эффективнее.
4) выбор и опрос и сравнение epoll
select | poll | epoll | |
---|---|---|---|
Метод работы | траверс | траверс | Перезвоните |
низкоуровневая реализация | множество | связанный список | хеш-таблица |
Эффективность ввода-вывода | Каждый вызов проходится линейно, а временная сложность составляет O (n) | Каждый вызов проходится линейно, а временная сложность составляет O (n) | В методе уведомления о событии всякий раз, когда fd будет готов, будет вызываться функция обратного вызова, зарегистрированная системой, и готовый fd будет помещен в readyList.Временная сложность O(1) |
Максимальное количество подключений | 1024 | неограниченный | неограниченный |
копия | Каждый раз, когда вы вызываете select, вам нужно скопировать набор fd из пользовательского режима в режим ядра. | Каждый раз, когда вызывается опрос, набор fd необходимо копировать из пользовательского режима в режим ядра. | Когда вызывается epoll_ctl, он копируется в ядро и сохраняется, а потом не копируется каждый раз, когда epoll_wait |
3 основные концепции NIO
1) Буфер Буфер
Буфер - это объект. Он содержит некоторые данные для записи или чтения. В потокоориентированном вводе/выводе данные могут быть записаны или прочитаны непосредственно в объект Stream.
В NIO все данные обрабатываются буферами. IO ориентирован на поток, NIO — на буфер.
Наиболее часто используемый буфер — это ByteBuffer, который предоставляет набор функций для управления байтовыми массивами. В дополнение к ByteBuffer существуют и другие буферы, фактически каждому базовому типу Java (кроме Boolean) соответствует буфер, а именно:
- ByteBuffer: байтовый буфер
- CharBuffer: буфер символов
- ShortBuffer: короткий целочисленный буфер
- IntBuffer: Целочисленный буфер
- LongBuffer: длинный целочисленный буфер
- FloatBuffer: буфер с плавающей запятой
- DoubleBuffer: буфер двойной точности с плавающей запятой
2) Канал Канал
Канал — это канал, по которому данные могут быть прочитаны и записаны, он подобен водопроводу, а сетевые данные читаются и записываются через Канал.
Разница между каналом и потоком заключается в том, что канал является двунаправленным, поток движется только в одном направлении, а канал может использоваться для чтения, записи или того и другого.
Поскольку канал является полнодуплексным, он отображает API базовой операционной системы лучше, чем потоки, особенно в сетевом программировании UNIX, каналы базовой операционной системы являются полнодуплексными, поддерживая как чтение, так и запись.
Канал имеет четыре реализации:
- FileChannel: данные считываются из файла.
- DatagramChannel: Чтение или запись данных из сети UDP.
- SocketChannel: Чтение или запись данных из сети TCP.
- ServerSocketChannel: позволяет прослушивать подключения по TCP, как сервер. Для каждого соединения будет создан SocketChannel.
3) Селектор мультиплексора
Селектор Селектор может прослушивать интересующие вещи для нескольких каналов канала (чтение, запись, принятие (полученное сервером), подключение, реализация потока для управления несколькими каналами, экономия ресурсов, потребляемых контекстами переключения потоков. Селектор может только управлять неблокирующий канал, FileChannel блокируется и не может управляться.
Ключевые объекты
Селектор: объект селектора, регистрация канала, объект монитора канала и связанный селектор.
SelectorKey: ключевое слово мониторинга канала, которое используется для контроля состояния канала.
**Отслеживать регистрацию** Слушатель зарегистрирован в Selector
socketChannel.register(selector, SelectionKey.OP_READ);
отслеживаемые события
- OP_ACCEPT: готов к приему, используется serviceSocketChannel
- OP_READ: чтение готово, используется socketChannel
- OP_WRITE: запись готова, используется socketChannel
- OP_CONNECT: соединение готово, используется socketChannel
Приложения и фреймворки NIO
1) Применение НИО
Успешное применение Java NIO в различных распределенных Java-системах обмена мгновенными сообщениями и промежуточного программного обеспечения полностью доказывает, что коммуникационная основа, построенная на NIO, представляет собой эффективную и масштабируемую коммуникационную архитектуру.
Например, Dubbo (инфраструктура службы) по умолчанию использует Netty в качестве основного компонента связи, который используется для реализации внутренней связи между узлами процесса.
Jetty, Mina, Netty, Dubbo, ZooKeeper и т. д. реализованы на основе NIO.
Мина родилась в организации Apache, большой корове в мире открытого исходного кода. Нетти родилась в коммерческом магнате с открытым исходным кодом Jboss. Фреймворк распределенных сервисов Dubbo Ali
2) структура NIO
В частности, Netty в настоящее время является самой популярной платформой Java с открытым исходным кодом NIO framework.Netty предоставляет асинхронные, управляемые событиями платформы сетевых приложений и инструменты для быстрой разработки высокопроизводительных и надежных сетевых серверов и клиентских программ.
По сравнению с собственным NIO JDK, Netty предоставляет относительно простой и удобный API, который очень подходит для сетевого программирования.
Создателем двух фреймворков NIO, Мины и Нетти, является один и тот же человек, Трастин Ли. Netty является расширением и расширением Mina в некоторой степени, она решает некоторые дефекты дизайна на Mina, а также оптимизирует концепцию дизайна на Mina.
С другой стороны, преимущества Нетти по сравнению с Миной:
- легче учиться
- Более простой API
- Подробный образец исходного кода и документация по API
- Более активные форумы и сообщества
- Более высокая скорость обслуживания обновления кода
Netty, несомненно, является лучшим выбором для платформы NIO.Ее надежность, функциональность, производительность, настраиваемость и масштабируемость не имеют себе равных среди аналогичных платформ.В последующем мы подробно сосредоточимся на принципах реализации и практических сценариях Netty.
3. Асинхронный неблокирующий ввод-вывод (AIO)
Режим реализации сервераДействительный запрос для потока, клиентский запрос ввода-вывода сначала выполняется операционной системой, а затем уведомляет серверное приложение о запуске потока для обработки. Метод AIO подходит для архитектур с большим количеством подключений и относительно длинными подключениями (тяжелыми операциями), такими как серверы фотоальбомов, которые полностью вызывают ОС для участия в параллельных операциях, а программирование более сложное.
AIO, также известный как NIO2, поддерживался только в JDK7.
Справочный источник
Режим ввода-вывода и мультиплексирование ввода-вывода (блокирующий ввод-вывод, неблокирующий ввод-вывод, синхронный ввод-вывод, асинхронный ввод-вывод и другие концепции)
Иллюстрируя Java BI0, NIO, самое простое и понятное понимание синхронных и асинхронных моделей ввода-вывода.
Подробно объясните разницу между NIO и BIO, принцип работы NIO и сценарии параллельного использования.
Три механизма мультиплексирования ввода-вывода Select, Poll, Epoll
Разница между BIO, NIO, AIO и мультиплексным вводом-выводом (иллюстрация)
Анализ внутренних принципов IO, NIO, AIO
В чем разница между BIO, NIO и AIO
【NIO】 Модель мультиплексирования ввода/вывода
Подробное объяснение принципа NIO