Что такое система elasticsearch и чем она хороша
Если вы читаете эту статью, то наверняка уже знаете, что такое Elasticsearch. Для полноты описания приведем ее определение.
Elasticsearch — высокомасштабируемая распределенная поисковая система полнотекстового поиска и анализа данных, работающая в режиме реального времени. Утилита позволяет хранить, искать и анализировать большие объемы данных. Обычно используется в качестве базового механизма/технологии, помогая приложениям со сложными функциями поиска. Elasticsearch представляет собой основной компонент Elastic Stack.
Elasticsearch как сердце Elastic Stack играет основную роль в поиске и анализе данных. Она построена на уникальной технологии — Apache Lucene. Благодаря этому Elasticsearch в корне отличается от традиционных решений для реляционных баз данных или NoSQL. Ниже перечислены основные преимущества использования Elasticsearch в качестве хранилища данных:
- неструктурированность, документоориентированность;
- возможность поиска;
- возможность анализа данных;
- поддержка пользовательских библиотек и REST API;
- легкое управление и масштабирование;
- работа в псевдореальном времени;
- высокая скорость работы;
- устойчивость к ошибкам и сбоям.
Рассмотрим все преимущества по отдельности.
Почему osal уг
Причины:
- Кооперативка. Если в конечном устройстве кооперативка еще смотрится. То в роутере, где проект получается сам по себе большим, это уже превращается в геморой.
- Во всех хороших ОСях есть папка target. В ней находится аппаратно зависимая часть. В OSAL она тоже есть, но только чтоб не отставать от моды. По факту почти каждый файл ОС привязан к конкретному камню. Я не пойму, как можно было сделать простейшую кооперативку настолько зависимой от конкретного железа! Оценил по достоинству когда портировал на CC2510.
- Разработана аматорами.
- Разработчики не особо понимали смысла либы HAL. Поэтому OSAL вмонтирована в HAL. Всегда думал, что должно быть наоборот, либо раздельно. Благодаря этому приходиться одновременно учить HAL,OSAL,MAC,Z-Stack. Кстати OSAL тоже привязана к MAC.
Система УГ. Не рекомендую использовать вообще. Но у вас нет выбора ;). Я попробовал это дело исправить, портировал scmRTOS, познал всю глубину проблемы и забил. Появилась мысля привязать FreeRTOS, но там нужно это все дело портировать c SDCC на IAR и непонятно как привязать Z-Stack. На это я тоже забил…
Ах да, тру эмбеддеры запиливают свою ОС… которая как правило не отличается от OSAL. Но я не тру.Поэтому решил модифицировать OSAL.
ЗЫ: Недавно вышел стек ZBOSS. Разработан славянами на деньги немцев. Он намного понятней, чем Z-Stack и не привязан к какой либо ОС или библиотеке. Но он слишком свежий.
Что делать?
У нас нет доступа ко многим задачам Z-Stack(можно получить через анус). Поэтому будем расслаивать на уровни все задачи. У каждого уровня будет свой стек.
Делается это с пол пинка.
Т.к. У уровня есть свой стек, то уровни тогда могут друг друга вытеснять. Также можно передавать управление, внутри уровня, другим задачам. Как же такое возможно, ведь у задач нет своих личных стеков ?! Будем пользоваться рекурсией. В кооператвке задачи, это конечные автоматы и ничего страшного если один конечный автомат вызовет другой минуя диспетчер.
Beats
Beats — это легковесная платформа доставки данных с открытым исходным кодом, дополняющая Logstash. В отличие от Logstash, работающей на серверной стороне, Beats располагается на стороне клиента. В ее основе лежит библиотека libbeat, которая предоставляет API для передачи данных от источника, настройки ввода и реализации сбора данных.
Команда Elastic и сообщество разработчиков открытого ПО создали много компонентов Beats, например Packetbeat, Filebeat, Metricbeat, Winlogbeat, Audiobeat и Heartbeat. Filebeat используется для доставки лог-файлов с ваших серверов на централизованный сервер Logstash или Elasticsearch.
Metricbeat предназначен для мониторинга серверов и периодического сбора показателей операционных систем и сервисов, запущенных на ваших серверах. На данный момент существует более 40 сообществ Beat, созданных для мониторинга Elasticsearch, Cassandra, веб-сервера Apache, производительности JVM и др. Вы также можете создать свой компонент на основе библиотеки libbeat, если не нашли подходящий.
Elasticsearch
Изначально, Elasticsearch – это решение для полнотекстового поиска, но с дополнительными удобствами, типа легкого масштабирования, репликации и прочего, что сделало продукт очень удобным и хорошим решением для высоконагруженных проектов с большими объемами данных.
Elasticsearch является нереляционным хранилищем(NoSQL) документов в формате JSON, и поисковой системой на базе полнотекстового поиска Lucene. Аппаратная платформа — Java Virtual Machine, поэтому системе требуется большое количество ресурсов процессора и оперативки для работы.
Каждое приходящее сообщение, как с Logstash или с помощью API запроса, индексируется как “документ” – аналог таблицы в реляционных SQL. Все документы хранятся в индексе – аналог базы данных в SQL.
Пример документа в базе:
{
"_index": "checkpoint-2022.10.10",
"_type": "_doc",
"_id": "yvNZcWwBygXz5W1aycBy",
"_version": 1,
"_score": null,
"_source": {
"layer_uuid": [
"dae7f01c-4c98-4c3a-a643-bfbb8fcf40f0",
"dbee3718-cf2f-4de0-8681-529cb75be9a6"
],
"outzone": "External",
"layer_name": [
"TSS-Standard Security",
"TSS-Standard Application"
],
"time": "1565269565",
"dst": "103.5.198.210",
"parent_rule": "0",
"host": "10.10.10.250",
"ifname": "eth6",
]
}
Вся работа с базой данных строится на JSON запросах с помощью REST API, которые либо выдают документы по индексу, либо некую статистику в формате: вопрос — ответ. Для того чтобы все ответы на запросы визуализировать была написана Kibana, которая представляет из себя веб сервис.
Kibana
Kibana позволяет искатьбрать данные и запрашивать статистику из базы данных elasticsearch, но основе ответов строятся множество красивых графиков и дашбоардов. Также система имеет функционал администрирования базы данных elasticsearch, в последующих статьях мы рассмотрим более подробно данный сервис.
Пример дашбоарда для Check Point, картинка кликабельна:
Пример дашбоарда по OpenVas, картинка кликабельна:
Logstash
Logstash – это утилита для обработки лог событий из различных источников, с помощью которой можно выделить поля и их значения в сообщении, также можно настроить фильтрацию и редактирование данных. После всех манипуляций Logstash перенаправляет события в конечное хранилище данных. Утилита настраивается только через конфигурационные файлы.
Типичная конфигурация logstash представляет из себя файл(ы) состоящий из нескольких входящих потоков информации (input), несколько фильтров для этой информации (filter) и несколько исходящих потоков (output). Выглядит это как один или несколько конфигурационных файлов, которые в простейшем варианте (который не делает вообще ничего) выглядит вот так:
input {
}
filter {
}
output {
}
В INPUT мы настраиваем на какой порт будут приходить логи и по какому протоколу, либо из какой папки читать новые или постоянно дозаписывающиеся файлы. В FILTER мы настраиваем парсер логов: разбор полей, редактирование значений, добавление новых параметров или удаление.
FILTER это поле для управления сообщением которое приходит на Logstash с массой вариантов редактирования. В output мы настраиваем куда отправляем уже разобранный лог, в случае если это elasticsearch отправляется JSON запрос, в котором отправляются поля со значениями, либо же в рамках дебага можно выводить в stdout или записывать в файл.
Анализ данных
У Elasticsearch есть еще одно важное функциональное преимущество — возможность аналитической обработки данных. Да, то, что изначально известно как полнотекстовый движок поиска, теперь используется и как механизм для аналитики. Многие организации задействуют в работе решения для анализа данных на базе Elasticsearch.
Сегодня, с ростом количества данных, выполнить поиск означает найти иголку в стоге сена. При этом поиск дает возможность выявить нужное среди огромных массивов информации. Аналитика же, наоборот, позволяет увидеть цельную картину. Например, вы хотите узнать, сколько на вашем сайте посетителей конкретно из США в сравнении с количеством пользователей из других стран, или, возможно, вам необходимо знать, какая часть посетителей пользуется macOS, Windows или Linux.
Elasticsearch предлагает широкий спектр агрегаторов для аналитики. Системы агрегации Elasticsearch могут применяться для различных типов данных.
Анализ показателей
У Elastic Stack есть богатые возможности аналитики благодаря многофункциональным API сбора информации в Elasticsearch. Таким образом, эта система является отличным инструментом для анализа данных и показателей. Показатели обычно представляют собой числовые значения, что отличает их от неструктурированного текста, характерного для документов и веб-страниц.
Метрические данные, как правило, имеют временную природу, то есть значения или измерения записываются за определенный промежуток времени. Фиксируемые показатели чаще всего поступают с конкретного объекта. Например, сведения о температуре (метрические) записываются определенным устройством со своим идентификатором.
Elasticsearch и Kibana позволяют разбивать метрические данные на фрагменты и распределять их в зависимости от разных параметров для более удобной работы. Elasticsearch имеет широкий функционал по управлению временными и пространственными данными — вы можете отобразить показатели, собранные из миллионов источников, в виде линейных графиков или гистограмм. Можно также выполнить пространственный анализ карты.
Веб-поиск и поиск по сайту
Elasticsearch может служить поисковой системой вашего сайта и выполнять поиск как в Google по всему его контенту. Поиск на таких платформах, как GitHub, Wikipedia, и многих других работает именно благодаря Elasticsearch.
Кроме того, Elasticsearch способна работать как платформа сбора контента. Что такое контент-агрегатор, или платформа сбора контента? Это инструмент для «прочесывания» сайтов, индексирования веб-страниц, предоставляющий поисковый функционал для найденного контента. Это мощное решение для построения агрегированных платформ.
Крупный веб-агрегатор Apache Nutch был создан Дагом Каттингом, одним из первых разработчиков Apache Lucene. Apache Nutch «прочесывает» сайты, обрабатывает HTML-страницы, сохраняет и индексирует их для поиска. Он дополняет возможности индексирования в Elasticsearch и Apache Solr для их поисковых систем.
Как вы можете видеть, Elasticsearch и Elastic Stack можно использовать для широкого спектра задач. Elastic Stack — это платформа с расширенным набором инструментов для создания комплексных решений поиска и аналитики. Она подходит для разработчиков, архитекторов, бизнес-аналитиков и системных администраторов.
Вполне возможно создать решение на базе Elastic Stack, почти не прибегая к написанию кода, исключительно за счет изменения конфигурации. В то же время система Elasticsearch очень гибкая, следовательно, разработчики и программисты могут строить мощные приложения благодаря обширной поддержке языков программирования и REST API.
История зарождения проблемы
OSAL
— это простейшая кооперативная система c от Ti. Диспетчер ОС системы поддерживает приоритеты и события.
У меня есть подозрения, что она разработана индусами. OSAL полное УГ.
Зачем тогда такое УГ использовать ?? Дело в том, что Ti сделало хитрый финт ушами. Они вмонтировали в OSAL такие «шедевры» как Z-Stack и BLE Stack.
Шло время. И тут бац, ударила молния. Рынок помешался на Cortex-M3. Ti решило запилить SoC CC2580 (ZigBee c кортексом). Вот тут-то и началось веселье.
Изначально разработчики приняли глупое решение и привязали Z-Stack к Clib. Тем самым отсекли C . Они попытались это исправить, но осознав, что стек придется переписать, отказались от этой идеи. В коде до сих пор остались их попытки отвязаться от Clib.
Разработчики, непонятно зачем вмонтировали Z-Stack в кооперативную систему. OSAL под это дело и была разработана. Вот нахрена они это сделали!!! В миру есть дохренище ОС, но они решили слепить свою с блэкджеком и шлюхами. Дело это поручили аматорам (я не верю, что профессионалы могли такое родить)… они и слепили УГ.
Пришла пора осваивать кортексы… А вот и облом. OSAL смотрится не кошерно на кортексе. Они попытались прикрутить FreeRTOS, но потерпели фейл. Следы ихнего фейла в коде еще остались.Служба поддержки зарядила, что RTOS не будет т.к. нужно переписать весь стек а они это делать не собираются.
Я буду дико ржать если они на рынок выплюнут CC2580 с OSAL на борту.
Как устроен стек
Стек хранит последовательность данных. Связаны данные так: каждый элемент указывает на тот, который нужно использовать следующим. Это линейная связь — данные идут друг за другом и нужно брать их по очереди. Из середины стека брать нельзя.
👉 Главный принцип работы стека — данные, которые попали в стек недавно, используются первыми. Чем раньше попал — тем позже используется. После использования элемент стека исчезает, и верхним становится следующий элемент.
Классический способ объяснения принципов стека звучит так: представьте, что вы моете посуду и складываете одинаковые чистые тарелки стопкой друг на друга. Каждая новая тарелка — это элемент стека, а вы просто добавляете их по одной в стек.
Когда кому-то понадобится тарелка, он не будет брать её снизу или из середины — он возьмёт первую сверху, потом следующую и так далее.
🤔 Есть структура данных, похожая на стек, — называется очередь, или queue. Если в стеке кто последний пришёл, того первым заберут, то в очереди наоборот: кто раньше пришёл, тот раньше ушёл. Можно представить очередь в магазине: кто раньше её занял, тот первый дошёл до кассы. Очередь — это тоже линейный набор данных, но обрабатывается по-другому.
Легкое управление и масштабирование
Elasticsearch можно запустить на одном узле и легко масштабировать до сотен узлов. Начать работу с экземпляром узла Elasticsearch очень просто — его установочная версия не требует каких-либо изменений в конфигурации. При этом вы можете масштабировать его.
Горизонтальное масштабирование — это возможность горизонтально масштабировать систему путем запуска нескольких однотипных процессов, вместо того чтобы наращивать мощность одного процесса. Вертикальное масштабирование — это наращивание мощности одного процесса путем добавления мощности (увеличения количества ядер ЦП), памяти или дискового пространства.
В отличие от большинства традиционных баз данных, которые поддерживают только вертикальное масштабирование, Elasticsearch может быть масштабирована горизонтально. Она может быть запущена на десятках или сотнях узлов вместо одного очень дорогого сервера.
Добавить к имеющемуся кластеру Elasticsearch еще один узел так же легко, как и добавить узел в той же сети, практически без дополнительных настроек. Нет необходимости изменять клиентское приложение в зависимости от того, работает оно на одном узле или на кластере из сотен узлов.
Минусы
- Тяжелая обработка неэффективна. Если ваш проект включает в себя тяжелые математические вычисления или сложные алгоритмы, Node.js — не лучший вариант. Вам лучше использовать серверную службу, которая больше ориентирована на работу с этим типом набора данных.
- Молодой. Node.js — относительно молодая технология по сравнению с PostgreSQL или MySQL. Быть молодым иногда означает отсутствие опыта в решении проблем.
Итак, теперь, когда мы знаем, что такое full stack JavaScript и что он может предложить, давайте узнаем, что нужно знать программисту, чтобы считаться веб-разработчиком full stack JavaScript.
Неструктурированность и документоориентированность
Elasticsearch не навязывает четкую структуру для ваших данных; вы можете хранить любые документы JSON, которые прекрасно подходят для Elasticsearch в отличие от строк и столбцов в реляционных базах данных. Такой документ можно сравнить с записью в таблице БД.
В традиционных реляционных базах данных таблицы структурированы: имеют фиксированное количество столбцов, у каждого свой тип и размер. Но данные могут динамично меняться, что потребует поддержки новых или динамических столбцов. Документы JSON изначально поддерживают такой тип данных. Например, взгляните на следующий документ:
{
"name": "John Smith",
"address": "121 John Street, NY, 10010",
"age": 40
}
Так может выглядеть запись о клиенте. В ней указаны имя, адрес и возраст клиента. А другая запись может выглядеть так:
Обзор компонентов elastic stack
Компоненты Elastic Stack представлены на рис. 1. Нет необходимости использовать сразу все из них в вашем решении. Некоторые компоненты универсальны, их можно применять без Elastic Stack или других инструментов.
Взглянем на предназначение каждого компонента и на то, какое место они занимают в общем наборе (рис. 1).
Рис. 1 Elasticsearch
Elasticsearch хранит все ваши данные, предоставляет возможности поиска и анализа в масштабируемом виде. Мы уже рассматривали преимущества и причины использования Elasticsearch. Вы можете работать с Elasticsearch без каких-либо других компонентов, чтобы оснастить свое приложение инструментами для поиска и анализа данных.
Пару слов о z-stack
Это действительно наиболее развитый стек… При этом он еще обильно обмазан фекалиями… Реально, у меня неоднократно появлялась мысля перейти на другое железо.
Особенности:
- Он умнее разработчика. Поэтому он может перезагрузить SoC, проверить уровень напряжения и если оно ему не понравится, то зависнуть. Любит игнорить прямые приказы. Кстати вопрос «Как выключить Z-Stack» у службы поддержки вызывает разрыв шаблона. Никто не догадался сделать функцию выключения(выключить можно, но через попу).
- Неквалифицированная служба поддержки. Игнорте ответы если ответил индус.
- Чрезмерно запутан и нелогичен. Вы прочитали в доке описание API функции, вызываете ее и получаете самый неожиданный результат. Оказывается перед этим нужно вызвать еще 2-3 функции а уже потом эту. Естественно это нигде не написано. В Ti это просекли быстро и запилили SimpleAPI, но они поручили это все тем-же людям. В итоге получилось над запутанным API еще более запутанное SimpleAPI и все вместе это куй его знает как работает. В Ti не рекомендуют использовать SimpleAPI.
- Документации много, но она не информативна.
- Пробелы в документации. Почти все важное тактично не описано вообще.
- Догматичен. Работает по принципу «либо так, либо никак и вообще я перезагружаюсь». Разработчик не чувствует себя царьком и богом над чипом в присутствии Z-Stack. Ti убивает всю магию системного программирования.
Переполнение стека
Почти всегда стек вызовов хранится в оперативной памяти и имеет определённый размер. Если у вас будет много вложенных вызовов или рекурсия с очень большой глубиной вложенности, то может случиться такая ситуация:
- рекурсия всё работает и работает;
- при каждом новом витке рекурсии в стек добавляются новый элемент;
- когда элементов будет слишком много, память закончится, новые элементы некуда будет складывать и произойдёт переполнение стека.
Переполнение — это плохо: данные могут залезать в чужую область памяти и записывать себя вместо прежних данных. Это может привести к сбою в работе других программ или самого компьютера. Ещё таким образом можно внедрить в оперативную память вредоносный код: если программа плохо работает со стеком, можно специально вызвать переполнение и записать в память что-нибудь вредоносное.
Плюсы
- Эффективность команды. Нет необходимости переосмысливать логику на другом языке, что может увеличить количество времени, необходимое для выполнения задачи. Подобные концепции немного упрощают написание кода. Команды также лучше работают вместе, если все они понимают кодовую базу.
- Один и тот же язык означает меньше ошибок и меньше кода. Поскольку и клиент, и сервер находятся на JavaScript, вероятность ошибок в коде из-за неправильного синтаксиса меньше. Использование npm node_modulesкак во внешнем, так и во внутреннем абстракциях кода от вашего проекта, чтобы уменьшить кодовую базу.
- Эффективный. Асинхронный JavaScript с использованием цикла событий делает его очень желанной технологией из-за его эффективности. Он легкий и быстрый, что делает его сегодня действительно популярным среди крупных технологических компаний.
- Не нишевая. JavaScript — один из самых популярных языков программирования в мире, наряду с Java и Python. Не нужно много времени, чтобы изучить кодовую базу или найти кого-то, кто присоединился бы к команде, если нужен новый разработчик.
- Активное сообщество. Сообщество веб-разработчиков JavaScript — это обширное сообщество с множеством ресурсов.
- Открытый источник. Если вы заглянули на домашнюю страницу NPM, вы увидите, что у нас есть широкий спектр проектов и модулей с открытым исходным кодом, доступных для использования в проектах. Это снижает рыночную стоимость вашего приложения.
Поиск по продуктам
Поиск по продуктам (товарам) заключается в выборе наиболее релевантных продуктов из тысяч или десятков тысяч вариантов и их выводе в списке в числе первых. Эта задача особенно актуальна для сайтов электронной коммерции, где продается огромное количество продуктов от множества различных производителей.
Полнотекстовый поиск в Elasticsearch и другие виды релевантного поиска помогают находить лучшие варианты. Отображение наиболее соответствующих условию продуктов на первой странице имеет особую ценность, поскольку повышает шансы на успешную продажу товара.
Представим, что покупатель ищет аксессуары для iPhone 7, а в результатах поиска на первой странице видит различные чехлы, зарядные устройства и аксессуары для предыдущих поколений iPhone. Возможности анализа текста, предоставляемые Lucene, и нововведения Elasticsearch гарантируют получение требуемого результата поиска, в данном случае — аксессуаров для седьмой версии iPhone.
Однако задача релевантного поиска стоит не только перед сайтами электронной коммерции. Elasticsearch можно использовать для любого приложения, которому необходимо найти самый релевантный продукт из миллионов или миллиардов товаров.
Понеслась
Лезем в файл инициализации процессов и добавляем.
uint8 processList[sizeof( tasksArr ) / sizeof( tasksArr[0] )];
s_layer layerContext[2];
//allocate stack
__idata uint8 r_stack1[0x99];
uint8 v_stack1[0x300];
//__idata uint8 r_stack2[0x20]; //for one layer, you can use the system stack
uint8 v_stack2[0x100];
processList — определяет принадлежность процесса к уровню.layerContext — структура с описанием стека уровня (кому надо глянет описание структуры в коде).
Дальше выделяется стек для процессов. Закоментированный r_stack2 это не глюк, для этого уровня мы будем использовать стек main-a.
Кстати обратите внимание как выделяется место под стек. При такой форме записи, размер стека не будет зависеть от языка программирования или даже от микроконтроллера! Некоторые это делают неправильно, поэтому размер у них зависит от языка программирования. А здесь мы четко указываем сколько надо.
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
macTaskInit( taskID );
nwk_init( taskID );
Hal_Init( taskID );
#if defined( MT_TASK )
MT_TaskInit( taskID );
#endif
APS_Init( taskID );
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_Init( taskID );
#endif
ZDApp_Init( taskID );
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_Init( taskID );
#endif
GenericApp_Init( taskID );
//init layer list
for(uint8 i=0; i<(tasksCnt-1); i )
{
processList[i]=0;
}
processList[tasksCnt-1]=1;
//init layer context
layerContext[0].layer=0;
layerContext[0].rstack=(uint8*)&r_stack1;
layerContext[0].pstack=&v_stack1[256];
init_stack_frame(layerContext[0].layer, layerContext[0].rstack, layerContext[0].pstack, osal_start_system);
layerContext[1].layer=1;
//layerContext[1].rstack=(uint8*)&r_stack2;
#pragma segment="ISTACK"
layerContext[1].rstack=__segment_begin("ISTACK");
layerContext[1].pstack=&v_stack2[256];
init_stack_frame(layerContext[1].layer, layerContext[1].rstack, layerContext[1].pstack, osal_start_system);
Инициализируем задачи и контексты.
void init_stack_frame(uint8 gr,uint8 *RStack,uint8 *Stack ,void (*exec)())
{
*(HARDWARE_STACK_ADDRESS ( RStack))=(uint16)exec;
*(HARDWARE_STACK_ADDRESS ( RStack))=(uint16)exec>>8;
*(--Stack) = 0x80; //IEN0 register
Stack -= 1 2; //A DPTR
*(--Stack) = (uint8)(RStack); //SP
Stack-=1 8 VREG_COUNT 1 1; //PSW REG VREG_COUNT VB B
uint8 _spxl=(uint16)(Stack-2);
uint8 _spxh=((uint16)(Stack-2)>>8);
*(--Stack) = _spxl; //SPX
*(--Stack) = _spxh;
layerContext[gr].context=Stack;
}
Написано кривовато, но побую.
Также видим, что передается управление не процессу а диспетчеру. Так автоматически будет занесен в стек возврата адрес кооперативного диспетчера. Помним, что в кооперативках задачи могут завершаться.
В main-е меняем функцию запуска системы
//os_start
osal_start();
Теперь эта функция находится в ассемблерном файле. Без асма тут не обойтись, ведь будем свапать контексты.
Теперь делаем свою версию деспетчера
uint8 idx = 0;
osalTimeUpdate();
Hal_ProcessPoll();
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while ( idx < tasksCnt);
if (idx < tasksCnt)
{
uint16 events;
halIntState_t intState;
if(processList[idx]!=activeLayer)
{
uint8 oldLayer;
HAL_ENTER_CRITICAL_SECTION(intState);
oldLayer=activeLayer;
activeLayer=processList[idx];
//switch context
os_context_switcher(layerContext[oldLayer].context, layerContext[activeLayer].context);
HAL_EXIT_CRITICAL_SECTION(intState);
}
else
{
HAL_ENTER_CRITICAL_SECTION(intState);
events = tasksEvents[idx];
tasksEvents[idx] = 0; // Clear the Events for this task.
HAL_EXIT_CRITICAL_SECTION(intState);
activeTaskID = idx;
events = (tasksArr[idx])( idx, events );
activeTaskID = TASK_NO_TASK;
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
}
}
Я добавил, только момент с переключением контекстов уровней. Как видим, ничего сложного нет.
А теперь запиливаем самое вкусное. Ради нее родимой все и затевалось.
/*********************************************************************
* @fn task_yield
*
* @brief
*
* @param task_id - current task ID
*
* return
* YIELD_CONTEXT_RETURN
* YIELD_CONTROL_RETURN
* YIELD_RECURSION
* YIELD_RETURN
* YIELD_NO_TASK
*
* @
*/
uint8 task_yield(uint8 task_id)
{
static uint8 recursion=0;
uint8 idx = 0;
osalTimeUpdate();
Hal_ProcessPoll();
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while ( idx < tasksCnt);
if (idx < tasksCnt)
{
uint16 events;
halIntState_t intState;
if(processList[idx]!=activeLayer)
{
uint8 oldLayer;
HAL_ENTER_CRITICAL_SECTION(intState);
oldLayer=activeLayer;
activeLayer=processList[idx];
//switch context
os_context_switcher(layerContext[oldLayer].context, layerContext[activeLayer].context);
HAL_EXIT_CRITICAL_SECTION(intState);
return YIELD_CONTEXT_RETURN;
}
else
{
if(idx!=task_id)
{
if(recursion==0)
{
HAL_ENTER_CRITICAL_SECTION(intState);
events = tasksEvents[idx];
tasksEvents[idx] = 0; // Clear the Events for this task.
recursion=1;
HAL_EXIT_CRITICAL_SECTION(intState);
activeTaskID = idx;
events = (tasksArr[idx])( idx, events );
activeTaskID = TASK_NO_TASK;
HAL_ENTER_CRITICAL_SECTION(intState);
recursion=0;
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
return YIELD_CONTROL_RETURN;
}
else
{
return YIELD_RECURSION;
}
}
else
{
return YIELD_RETURN;
}
}
}
return YIELD_NO_TASK;
}
Опять же, все очень просто. Если нужно свапаем контексты, иначе передаем управление другому процессу рекурсивно с защитой от зацикливания. Переменная recursion должна быть статичной а не глобальной, чтоб у каждого уровня была своя локальная защита от зацикливания.
Отработав функция возвращает причину возврата.
И теперь мы можем реализовать sleep вот так. Раньше это было невозможно.
// Send a message out - This event is generated by a timer
// (setup in GenericApp_Init()).
if ( events & GENERICAPP_SEND_MSG_EVT )
{
events = events ^ GENERICAPP_SEND_MSG_EVT;
// Send "the" message
GenericApp_SendTheMessage();
// Setup to send message again
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
//delay
do{
task_yield(task_id);
events=update_task_events( task_id, events );
}while(!(events&GENERICAPP_SEND_MSG_EVT));
// return unprocessed events
return (events ^ GENERICAPP_SEND_MSG_EVT);
}
Резюме
В этой статье мы поговорили о необходимости альтернативных технологий для поиска и анализа данных, отличных от реляционных баз данных и хранилищ NoSQL. Мы рассмотрели сильные стороны Elasticsearch, являющейся ядром Elastic Stack. Кратко ознакомились с остальными компонентами Elastic Stack и разобрались, какое место они занимают во всей экосистеме.
В следующей статье мы начнем с изучения основных концепций Elasticsearch: разберемся в индексах, шардах, типах данных, разметке и других фундаментальных понятиях. Мы также поработаем с CRUD-операциями (создание, чтение, обновление и удаление) в Elasticsearch и попытаемся разобраться, что же такое поиск.
Серверные технологии
- Node.js: что это такое, как работает, зачем он нам нужен
- Фреймворки Node.js: Express.js, Koa, Hapi и т. Д.
- Backbone.js: библиотека JavaScript с интерфейсом RESTful JSON.
- Совместное использование ресурсов между источниками (CORS)
- Интерфейсы прикладного программирования (API) и как писать конечные точки, которые взаимодействуют с базой данных
- Разница между базами данных NoSQL и SQL и как создать базу данных с помощью JavaScript
- Файлы cookie против токенов и как реализовать и то, и другое
Это не исчерпывающий список, и вам, конечно, не нужно знать все в этом списке, чтобы начать становиться разработчиком полного стека. Начни с малого!
Скачивание и установка
Теперь, когда приведено достаточно причин для изучения Elasticsearch и Elastic Stack, начнем со скачивания и установки основных компонентов. Для начала скачаем и установим Elasticsearch и Kibana. Остальные компоненты мы установим тогда, когда они нам понадобятся в процессе изучения.
Начиная с версии Elastic Stack 5.х, все компоненты обновляются вместе и имеют один номер версии. К этому моменту они уже протестированы на совместимость друг с другом. Это касается и компонентов Elastic Stack версии 6.х.
Способы реализации стека
Существует несколько способов реализации стека:
- с помощью одномерного массива;
- с помощью связанного списка;
- с помощью класса объектно-ориентированного программирования.
Пример реализации стека с помощью одномерного массива
Стек можно реализовать в виде следующей структуры:
NMAX
— максимальное количество элементов в стеке;
elem
— массив из
NMAX
чисел типа
float
, предназначенный для хранения элементов стека;
top
— индекс элемента, находящегося в вершине стека.
Стандартный диспетчер
У нас дан единый стек и все задачи вертятся в нем. Поэтому их прервать почти невозможно.
osalTimeUpdate();
Hal_ProcessPoll();
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while ( idx < tasksCnt);
if (idx < tasksCnt)
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState);
events = tasksEvents[idx];
tasksEvents[idx] = 0; // Clear the Events for this task.
HAL_EXIT_CRITICAL_SECTION(intState);
activeTaskID = idx;
events = (tasksArr[idx])( idx, events );
activeTaskID = TASK_NO_TASK;
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
}
Принцип действия простейший. Обновляем таймеры, обрабатываем кривой HAL. После в списке событий ищем наиболее приоритетный процесс готовый к работе. Если не нашли, то перезапускаем диспетчер. Ну а если нашли, то вызываем этот процесс. Все.
/* Yield in case cooperative scheduling is being used. */
#if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
{
osal_task_yield();
}
#endif
Кстати это ихние потуги исправить проблему… Умерли в зародыше.
Стек вызовов
В программировании есть два вида стека — стек вызовов и стек данных.
Когда в программе есть подпрограммы — процедуры и функции, — то компьютеру нужно помнить, где он прервался в основном коде, чтобы выполнить подпрограмму. После выполнения он должен вернуться обратно и продолжить выполнять основной код. При этом если подпрограмма возвращает какие-то данные, то их тоже нужно запомнить и передать в основной код.
Чтобы это реализовать, компьютер использует стек вызовов — специальную область памяти, где хранит данные о точках перехода между фрагментами кода.
Допустим, у нас есть программа, внутри которой есть три функции, причём одна из них внутри вызывает другую. Нарисуем, чтобы было понятнее:
Программа запускается, потом идёт вызов синей функции. Она выполняется, и программа продолжает с того места, где остановилась. Потом выполняется зелёная функция, которая вызывает красную. Пока красная не закончит работу, все остальные ждут. Как только красная закончилась — продолжается зелёная, а после её окончания программа продолжает свою работу с того же места.
А вот как стек помогает это реализовать на практике:
Программа дошла до синей функции, сохранила точку, куда ей вернуться после того, как закончится функция, и если функция вернёт какие-то данные, то программа тоже их получит. Когда синяя функция закончится и программа получит верхний элемент стека, он автоматически исчезнет. Стек снова пустой.
С зелёной функцией всё то же самое — в стек заносится точка возврата, и программа начинает выполнять зелёную функцию. Но внутри неё мы вызываем красную, и вот что происходит:
При вызове красной функции в стек помещается новый элемент с информацией о данных, точке возврата и указанием на следующий элемент. Это значит, что когда красная функция закончит работу, то компьютер возьмёт из стека адрес возврата и вернёт управление снова зелёной функции, а красный элемент исчезнет. Когда и зелёная закончит работу, то компьютер из стека возьмёт новый адрес возврата и продолжит работу со старого места.
Стекирование коммутаторов cisco. часть 1
В данной статье (будет состоять из двух частей) хотел бы кратко пройтись по основным технологиям стекирования коммутаторов Cisco. Попробуем разобраться с общей архитектурой передачи пакетов в рамках каждого типа стека, реакцией на отказы, а также с цифрами пропускной способности. В первой части мы рассмотрим технологии StackWise и StackWise Plus. Во второй части — StackWise-160, StackWise-480, FlexStack и FlexStack Plus.
Сейчас функционалом стекирования никого не удивишь. Он есть во многих моделях коммутаторов различных производителей, в том числе и у Cisco. Но так было не всегда. На заре моей карьеры (где-то середина двухтысячных) в области сетевых технологий в портфеле компании Cisco был всего один коммутатор с поддержкой полноценного стека. Это была модель коммутатора Cisco 3750. Псевдо стеки на базе 2950 и 3550 в ту пору уже практически умерли. На тот момент меня, как молодого специалиста, очень удивлял факт того, что вопросу стекирования коммутаторов компанией Cisco уделялось так мало внимания. При этом, например, у коммутаторов 3com (прим. куплен компанией HP), которые в то время были достаточно популярны, стекирование поддерживалось достаточно на большом перечне моделей. Также обстояли дела и у Allied Telesis. Я даже помню, как приверженцы продукции Cisco мне объясняли, что стекирование – это плохо, и в продакшене данную технологию не стоит использовать. Жаль, уже не помню точных формулировок, но речь шла вроде о стабильности работы. Стоит заметить, что в то время основными доводами в пользу стекирование было упрощение управления (во всяком случае, на тот момент мне казалось именно так). Т.е. вместо того, чтобы настраивать отдельно два или более устройства, стек даёт нам возможность получить один большой коммутатор.
Шло время. Многие осознали плюсы стекирования. И сейчас большая часть коммутаторов Cisco поддерживет данную технологию. В настоящее время, говоря о стекировании, стоит разделять стек на уровне доступа (там, где подключаем обычных пользователей) и стек во всех остальных случаях.
В первом случае основной причиной объединения коммутаторов в стек является упрощение администрирования. В какой-то момент времени мне даже стало казаться, что это уже совсем не актуально и является больше маркетинговым моментом. Но не так давно в общении с заказчиком, у которого большой парк автомобилей сетевых устройств, выяснил, что главной причиной объединения коммутаторов в стек на уровне доступа стало именно это.
Во всех остальных случаях, на мой взгляд, основным «за» в пользу стека стала возможность организации относительно недорогой схемы отказоустойчивости в сети (как на уровне ядра сети, так и при подключении серверного оборудования). Стек позволяет нам агрегировать физические каналы, заведённые на разные коммутаторы, в один логический. Это обеспечивает нас не только большей пропускной способностью (за счёт утилизации одновременно нескольких каналов) и отказоустойчивостью (выход из строя одного из коммутаторов стека не приведёт к остановке сети), но и в ряде случаев даёт возможность полностью отказаться от петель. А значит от использования протоколов семейства STP. Т.е. упрощает жизнь, делая топологию сети достаточно простой.
На оборудовании Cisco в зависимости от платформы используются несколько технологий стекирования. Небольшое замечание. Рассматривать будем классические схемы стекирования. Технология VSS останется за кадром.
Предлагаю чуточку подробнее разобраться с цифрами общей пропускной способности стековой шины, а также общей архитектурой передачи пакетов в рамках каждого типа стека. Хотел бы пояснить, что под стековой шиной будем подразумевать внутренние интерфейсы и порты, которые обеспечивают стекирование. Её производительность — это суммарная полезная пропускная способность всех стековых портов. Почему я не говорю про общую производительность стека? Это обусловлено тем, что в большинстве технологий при выполнении коммутации пакетов между внутренними портами одного коммутатора, используется лишь внутренняя логика (коммутационная фабрика, ASICи и пр.). В этом случае пакет не попадает на стековую шину. Стековая шина утилизируется только тогда, когда пакет попадает на порт одного коммутатора, а выходит через порт уже другого коммутатора стека.
StackWise
Рассмотрим технологию StackWise. Она является самой пожилой среди остальных. Для соединения коммутаторов в стек по технологии StackWise используется специализированный стековый кабель. При этом отдельного стекового модуля нет, стековые порты сразу встроены в коммутатор (по два порта).
Пропускная способность стекового кабеля 16 Гбит/с (в каждую сторону). Так как на каждом коммутаторе два стековых порта, пропускная способность стековой шины должна равняться:
16 Гбит/с * 2 (в каждую сторону) * 2 (количество портов) = 64 Гбит/с
Смотрим в спецификацию, а там 32 Гбит/с. Куда делась половина пропускной способности?
В коммутаторах 3750 (3750v2) и 3750G отсутствует как таковая выделенная внутренняя коммутационная фабрика (используется старая архитектура shared-ring switch fabric). Стековые порты подключаются напрямую к внутренней шине коммутатора, становясь её продолжением. Таким образом, коммутаторы одного стека имеют одну большую шину в виде кольца. Данная шина на логическом уровне представляет собой два пути в виде кольца каждый.
Пропускная способность каждого из них — 16 Гбит/с. Эти пути разнонаправленные: пакеты по ним передаются в противоположные стороны. Так как мы имеем общую шину на весь стек, пакет, попав на порт любого коммутатора стека, обязательно пройдёт не только через все внутренние ASIC’и, но и через всё кольцо стека, даже если исходящий порт находится на том же коммутаторе, что и входящий. Причём пакет будет убран с шины, только когда он пройдёт весь круг и вернётся обратно. Это позволяет ASIC’у, который «захватил» один из путей, узнать о том, что пакет дошёл и путь можно освобождать. Такой алгоритм работы можно называть «удаление отправителем» (в терминах Cisco — Source stripped). Выбор пути, по которому отправить пакет, определяется исходя из доступности каждого из них (используется механизм токенов: тот ASIC, который обладает токеном, передаёт данные).
Давайте рассмотрим это на примере (Рис. 2). В нашем случае пакет, попав на порт коммутатора (1), попадает на ASIC, который в свою очередь выбирает синий путь (2) (допустим, он был свободен в этот момент). Далее пакет по синему пути проходит через все коммутаторы (3), попадая в итоге на тот коммутатор, где находится порт назначения (4). Коммутатор отправляет копию пакета (5) через свой локальный порт. Но сам пакет продолжает своё путешествие по стековому кольцу (6), пока не достигнет ASIC’а, который его изначально отправил (7). Только там он будет удалён со стековой шины.
Таким образом, один и тот же пакет проходит 2 раза через стековые порты коммутатора (сначала через один (3), потом через второй (6) порты). А значит наша общая полезная пропускная способность стековой шины равна 32 Гбит/с (ровно в два раза меньше физической).
А, что будет если один из коммутаторов стека откажет? В этом случае пути замкнутся друг на друга, тем самым образуя одно большое кольцо (Рис. 3). Ровным счётом также поведут себя коммутаторы в случае, если будет отключён один из стековых кабелей.
Стоит отметить ещё два момента. Два пути «крутятся» в разные стороны. Предполагаю, что это сделано для усреднения задержки передачи пакетов внутри стека. Второй момент заключается в том, что для Stackwise пропускная способность стековой шины равна общей производительности стека, в силу того, что все коммутаторы в стеке используют одну общую шину.
StackWise Plus
Перейдём к технологии StackWise Plus. В коммутаторах 3750E и 3750X была добавлена выделенная коммутационная фабрика (switch fabric). Это позволяет делать локальную коммутацию пакетов без их появления в стековом кольце. Стековые порты заводятся непосредственно на коммутационную фабрику. Теперь за логику работы со стековой шиной отвечает непосредственно коммутационная фабрика. В случае технологии StackWise со стековой шиной работал каждый ASIC отдельно.
В технологии StackWise Plus был использован новый алгоритм обработки пакетов в стеке – «удаление получателем» (в терминах Cisco — Destination stripped, ещё одно наименование Spatial reuse). В данном алгоритме пакет удаляется со стековой шины сразу же, как только он достиг коммутатора, на котором находится исходящий порт (Рис. 4). Теперь для сигнализации о том, что путь можно освобождать используется маленький Ack пакет (8 бит).
Как и в технологии Stackwise, логически у нас остаётся два пути. Но так как теперь за работу со стековым кольцом отвечает коммутационная фабрика, механизм работы с этими путями усложнился. Как и раньше доступ к тому или иному пути осуществляет с помощью механизма токенов. Получив токен, коммутационная фабрика может передавать пакеты по стековому кольцу. А так как непосредственно пакеты забираются с каждого ASIC’а, за порядок обслуживания каждого ASIC’a отвечает механизм кредитов. Их раздаёт коммутационная фабрика.
Эти новшества позволили увеличить пропускную способность стековой шины до маркетинговых 64 Гбит/с, прировняв полезную пропускную способность к физической. Теперь пакет проходит только один раз через стековый порт коммутатора. Хотел бы обратить внимание, что в обоих технологиях (Stackwise и StackWise Plus) используются одни и те же типы стековых кабелей.
Тут стоит подчеркнуть, что пропускная способность стековой шины не стала равна 64 Гбит/с, она стала стремиться к этой цифре. Почему? Причина в том, что весь трафик broadcast, multicast и unknown unicast продолжает обрабатываться по алгоритму Source stripped. Т.е. эти типы трафика проходят всё кольцо, прежде чем будут удалены со стековой шины. А значит на данные типы трафика расходуется двойная пропускная способность.
В одном стеке допускается использование любых коммутаторов серии 3750. Если в один стек добавить, например, коммутаторы 3750v2 (поддерживают StackWise) и 3750X (StackWise Plus), стек будет работать по технологии StackWise (алгоритм Source stripped). При этом для 3750X коммутация пакетов между локальными портами будет осуществляться только внутри коммутатора без появления на стековой шине. Для коммутаторов 3750v2 пакеты между локальными портами по старинке будут проходить через всю стековую шину.
Давайте кратко коснёмся схемы работы стека на программном уровне. В рамках стека StackWise или StackWise Plus один из коммутаторов выбирается в качестве мастера (stack master). Он выполняет логические операции (control-plane) для всего стека. При его отказе передача unicast трафика продолжается. Это достигается благодаря синхронизации аппаратных таблиц. Между коммутаторами стека синхронизируются MAC-таблица, а также таблицы Cisco Express Forwarding (CEF), а именно FIB и Adjacency table. А вот остальные таблицы, в том числе таблица маршрутизации, таблица передачи multicast трафика, на новом мастере заполняются заново. При этом возможно использование функционала NSF — Nonstop Forwarding. Т.е. control-plane на новом мастере запускается с нуля.
На этом предлагаю прерваться. Продолжение появится в ближайшие дни.
Вывод элементов стека
Если стек не пуст, движемся от последнего элемента к началу массива с выводом элементов.
ПримерСоздать стек из n элементов и извлечь их из стека.Примечание: для успешной компиляции примера необходимо добавить в код программы все функции работы со стеком, описанные выше на этой странице в порядке их рассмотрения. И не забыть подключить библиотеки stdio.h, stdlib.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main() {
struct stack *stk;
int i,n;
float elem;
stk = (struct stack*)malloc(sizeof(struct stack));
init(stk);
printf(“Введите количество элементов в стеке: “);
scanf(“%d”, &n);
for(i=0; i<n; i ) {
printf(“Введите элемент %d:”, i);
scanf(“%f”, &elem);
push(stk,elem);
}
printf(“В стеке %d элементовnn”, getcount(stk));
stkPrint(stk);
printf(“Верхний элемент %fn”,stkTop(stk));
do {
printf(“Извлекаем элемент %f, “, pop(stk));
printf(“в стеке осталось %d элементовn”, getcount(stk));
} while(isempty(stk) == 0);
getchar(); getchar();
return 0;
}
Результат выполнения
Пример
Перевести введенное число в систему счисления с заданным основанием.
Деление числа на основание системы счисления производится до тех пор, пока в частном не получится 0.
Результат выполнения
Назад:
Структуры данных