- Все статьи
Все статьи
Фильтр
- Все статьи
- API
- Bluetooth
- CSS
- HTML
- IP
- JSON
- Linux
- MVCC
- MySQL
- PostgreSQL
- PowerShell
- SD
- Smart мониторинг
- TCP/IP
- Tencent
- Tencent·T Creation, 2023 г.
- WordPress
- https
- iOS
- ipvsh
- javascript
- libxml2
- nginx
- openssh
- php
- uni-приложение
- wpf
- Автоматизация
- Авторизоваться
- Анализ исходного кода
- Апплеты
- База
- Безопасность
- Биткойн
- Большие данные
- Буровая платформа Хаоса
- Веб-сайт
- Визуализация
- Виртуализация
- Вичат
- Гис
- Джава
- Джанго
- Дженкинс
- Жизнь программы
- ИИ
- Играйте с Tencent Cloud
- Инструмент обнаружения
- Интеллектуальной сети
- Интернет вещей
- Искусственный интеллект
- Конференция Тенсент
- Кубернетес
- Медицинское здоровье
- Модель
- Начать бизнес
- Нвидиа
- Нет публики
- Облачный сервер
- Открытый источник
- Пакет
- Проверочный код
- Разработка оборудования
- Распределенные транзакции
- Рекомендуемая система
- Робот Видение
- Сеть доставки контента CDN
- Скбаат
- Скрипт
- Служить
- Тестирование производительности
- Фишинговая атака
- Электронная коммерция
- автоматизация
- активность
- алгоритм программирования
- андроид
- база данных
- бумага
- веб-пакет
- векторная база данных
- весна
- визуализация данных
- внешний интерфейс
- возврат в систему
- вюпресс
- голос
- девопс
- действующий
- дерзкий
- диск
- добавлять
- доступ
- дп
- завиток
- закладки
- запрос
- игра
- идти
- инструмент
- интервал
- информационная безопасность
- йомен
- картографирование
- клиент
- кодирование
- компьютер
- контейнер
- котлин
- криптовалюта
- кусочек
- кэш
- литкод
- макет
- машина
- медицинский
- мигрировать
- микросервисы
- модели
- монитор
- наука и технология
- нетти
- нить
- обработка данных
- обучать
- объект
- обязательность
- один
- окна
- опечатка
- определенность
- отображать
- переводить
- периферийные вычисления
- печенье
- питон
- поисковый движок
- превосходить
- предприятие
- примечания
- программа
- программирование
- прокси
- промышленность
- просмотр 3
- просмотр.js
- пряжа
- рамка
- реагировать
- резервное копирование
- рендеринг
- рептилия
- решение
- робот
- сеть
- смс
- соединять
- сотни
- тест
- управлять
- финансы
- функция
- хакер
- хранилище
- хром
- цель
- цифровой маркетинг
- чатgpt
- шаблоны
- эксплуатация и обслуживание Linux
- эластичный поиск
- элемент пользовательского интерфейса
- это идет
- этот
- яблоко-м1
- ямл
- 文件存储
JSch использует протокол sftp для реализации операций загрузки и выгрузки файлов на сервер
<p> <strong>Что такое Jsch? </strong> </p><p> JSch — это чистая Java-реализация SSH2. Он позволяет вам подключаться к sshd-серверу, использовать переадресацию портов, переадресацию X11, передачу файлов и многое другое. Вы можете интегрировать его функциональность в свои собственные программы. В то же время проект также предоставляет версию J2ME для прямого подключения к SSHD-серверу на мобильном телефоне </p><p>Jsch очень мощный инструмент, и блоггеры в основном используют его для операций с файлами </p><p> <strong>Как использовать? </strong> </p><p> Добавить зависимость jar </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"> com.jcraft jsch 0.1.53</code></pre><p>Я вставил свой SftpUtil ниже, комментарии вполне понятны </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * Content :sftp协议文件上传下载 * Created by kl on 2016/5/6. */ public class SftpUtil { /** * 上传文件到指定服务器 * @param ip 连接ip * @param user 用户名 * @param psw 密码 * @param port 端口 <=0 为默认端口 * @param fielPath 上传的服务器路径 * @param serverFileName 服务器保存的文件名 * @param instream 要上传的文件流 * @throws Exception */ public static void sftpFileUpload(String ip,int port, String user, String psw, String fielPath,String serverFileName,InputStream instream) throws Exception { Session session =getSession( ip, user, psw, port); Channel channel = null; try { //创建sftp通信通道 channel = (Channel) session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //进入服务器指定的文件夹 sftp.cd(fielPath); OutputStream outstream = sftp.put(serverFileName); byte b[] = new byte[1024*200];//每次传输200k int n; while ((n = instream.read(b)) != -1) { outstream.write(b, 0, n); } outstream.flush(); outstream.close(); instream.close(); } catch (Exception e) { e.printStackTrace(); } finally { session.disconnect(); if (channel!=null)channel.disconnect(); } } /** * 从指定服务器下载文件到本地 * @param ip 连接ip * @param user 用户名 * @param psw 密码 * @param port 端口 <=0 为默认端口 * @param fielPath 服务器文件路径 * @param serverFileName 要下载的文件名 * @param outputStream 输出到本地的文件流 * @throws Exception */ public static void sftpFileDownload(String ip,int port, String user, String psw, String fielPath,String serverFileName,OutputStream outputStream) throws Exception { Session session =getSession( ip, user, psw, port); Channel channel = null; try { //创建sftp通信通道 channel = (Channel) session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //进入服务器指定的文件夹 sftp.cd(fielPath); sftp.get(serverFileName,outputStream); } catch (Exception e) { e.printStackTrace(); } finally { session.disconnect(); if (channel!=null)channel.disconnect(); } } /** * 删除服务器指定文件 * @param ip 连接ip * @param user 用户名 * @param psw 密码 * @param port 端口 <=0 为默认端口 * @param fielPath 服务器文件路径 * @param serverFileName 要删除的文件名 * @throws Exception */ public static void sftpFileDelete(String ip,int port, String user, String psw, String fielPath,String serverFileName) throws Exception { Session session =getSession( ip, user, psw, port); Channel channel = null; try { //创建sftp通信通道 channel = (Channel) session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //进入服务器指定的文件夹 sftp.cd(fielPath); sftp.rm(serverFileName); } catch (Exception e) { e.printStackTrace(); } finally { session.disconnect(); if (channel!=null)channel.disconnect(); } } /** * 查看指定目录所有文件 * @param ip * @param user * @param psw * @param port * @param fielPath * @throws Exception */ public static Vector seeServerFileList(String ip, int port,String user, String psw, String fielPath)throws Exception{ Session session =getSession( ip, user, psw, port); Channel channel = null; Vector v=null; try { //创建sftp通信通道 channel = (Channel) session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //进入服务器指定的文件夹 sftp.cd(fielPath); //列出服务器指定的文件列表 v = sftp.ls(fielPath); } catch (Exception e) { e.printStackTrace(); } finally { session.disconnect(); if (channel!=null)channel.disconnect(); } return v; } /** * 连接服务器 * @param ip 服务器地址 * @param user 用户名 * @param psw 密码 * @param port 连接端口 * @return * @throws Exception */ public static Session getSession(String ip, String user, String psw, int port)throws Exception{ Session session = null; JSch jsch = new JSch(); if (port <= 0) { //连接服务器,采用默认端口 session = jsch.getSession(user, ip); } else { session = jsch.getSession(user, ip, port); } //如果服务器连接不上,则抛出异常 if (session == null) { throw new Exception("sftp session is null"); } session.setPassword(psw);//设置密码 //设置登陆超时时间 session.connect(30000);//30s return session; } }</code></pre><
2360243
None
Read more...
Подводные камни, возникающие при использовании Spring mvc для входа в валидатор параметров
<p> <strong>Предисловие</strong> </p><p>Во-первых, блоггер здесь не для того, чтобы писать о том, как использовать проверку параметров Spring mvc, потому что в Интернете много хороших статей, и блогерам незачем их дорабатывать, я лишь запишу один подводный камень, с которым я столкнулся во время использования.</p><p> <strong>Подводные камни заключаются в следующем</strong> </p><p>В проекте для проверки используется Hibernate-validator. Hibernate-validator реализует структуру проверки JSR-303 и поддерживает проверку в стиле аннотаций </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public void test(@Valid ValidateModel validateModel, BindingResult result){ if(result.hasErrors()){ } }</code></pre><p> Как указано выше, BindingResult должен находиться сразу за объектом @Valid. Никакие другие параметры не могут быть размещены посередине. Другие параметры могут быть размещены сзади. В противном случае в случае неудачной проверки будет выдано сообщение об исключении 400. Оно будет не вводить тело метода </p><p> <strong>Наконец, для справки прилагается подробная поясняющая таблица аннотаций проверки @Valid</strong> </p><p>Аннотации</p><p>Применимые типы данных</p><p>Описание</p><p>@AssertFalse</p><p>Логическое значение, логическое значение</p><p>Логическое значение, логическое значение</p><p>Убедитесь, что значение элемента аннотации является ложным</p><p>@AssertTrue</p><p>Убедитесь, что значение элемента аннотации истинно</p><p>@DecimalMax(value=x)</p><p>BigDecimal, BigInteger, String, byte,short, int, long и соответствующие оболочки примитивных типов. Дополнительно поддерживается HV: любой подтип Number и CharSequence.</p><p>BigDecimal, BigInteger, String, byte,short, int, long и соответствующие оболочки примитивных типов. Дополнительно поддерживается HV: любой подтип Number и CharSequence.</p><p>BigDecimal, BigInteger, String, byte,short, int, long и соответствующие оболочки примитивных типов. Дополнительно поддерживается HV: любой подтип Number и CharSequence.</p><p>Убедитесь, что значение аннотированного элемента меньше или равно значению, указанному @DecimalMax</p><p>@DecimalMin(value=x)</p><p>Убедитесь, что значение аннотированного элемента меньше или равно значению, указанному @DecimalMin</p><p>@Digits(integer=целые цифры, дробь=десятичные цифры)</p><p>Проверьте максимальное количество целых чисел и десятичных знаков для значения элемента аннотации</p><p>@Будущее</p><p>java.util.Date, java.util.Calendar; Дополнительно поддерживается HV, если API даты и времени Joda Time находится в пути к классу: любые реализации ReadablePartial и ReadableInstant.</p><p>java.util.Date, java.util.Calendar; Дополнительно поддерживается HV, если API даты и времени Joda Time находится в пути к классу: любые реализации ReadablePartial и ReadableInstant.</p><p>Убедитесь, что значение элемента аннотации (тип даты) позже текущего времени</p><p>@Макс(значение=x)</p><p>BigDecimal, BigInteger, byte, short,int, long и соответствующие оболочки примитивных типов. Дополнительно поддерживается HV: любой подтип CharSequence (оценивается числовое значение, представленное последовательностью символов), любой подтип Number.</p><p>Убедитесь, что значение элемента аннотации меньше или равно значению, указанному @Max</p><p>@Min(value=x)</p><p>BigDecimal, BigInteger, byte, short,int, long и соответствующие оболочки примитивных типов. Дополнительно поддерживается HV: любой подтип CharSequence (оценивается числовое значение, представленное последовательностью символов), любой подтип Number.</p><p>Убедитесь, что значение элемента аннотации больше или равно значению, указанному @Min</p><p>@NotNull</p><p>Любой тип</p><p>Любой тип</p><p>Убедитесь, что значение элемента аннотации не равно нулю</p><p>@Null</p><p>Убедитесь, что значение элемента аннотации равно нулю</p><p>@Прошлое</p><p>Убедитесь, что значение элемента аннотации (тип даты) предшествует текущему времени</p><p>@Pattern(regex=регулярное выражение, флаг=)</p><p>Строка. Дополнительно поддерживается HV: любой подтип CharSequence.</p><p>Убедитесь, что значение элемента аннотации соответствует указанному регулярному выражению</p><p>@Size(min=минимальное значение, max=максимальное значение)</p><p>Строка, коллекция, карта и массивы. Дополнительно поддерживается HV: любой подтип CharSequence.</p><p>Убедитесь, что значение элемента аннотации находится в пределах указанного минимального и максимального диапазона (включительно), например длины символа и установленного размера</p><p>@Валид</p><p>Любой не примитивный тип (ссылочный тип)</p><p>Проверьте связанные объекты. Например, если в объекте аккаунта есть объект заказа, укажите объект заказа проверки</p><p>@NotEmpty</p><p>CharSequence, Коллекция, Карта и Массивы</p><p>Убедитесь, что значение элемента аннотации не равно нулю и не пусто (длина строки не равна 0, а размер коллекции не равен 0)</p><p>@Range(min=минимальное значение, max=максимальное значение)</p><p>CharSequence, Collection, Map and Arrays, BigDecimal, BigInteger, CharSequence, byte, short, int, long и соответствующие оболочки примитивных типов</p><p>Убедитесь, что значение элемента аннотации находится между минимальным и максимальным значениями</p><p>@NotBlank</p><p>Символовая последовательность</p><p>Символовая последовательность</p><p>Символовая последовательность</p><p>Убедитесь, что значение элемента аннотации не пусто (не равно нулю и длина равна 0 после удаления первого пробела). В отличие от @NotEmpty, @NotBlank применяется только к строкам и удаляет пробелы из строк во время сравнения< /п ><p>@Length(min=нижний предел, max=верхний предел)</p><p>Убедитесь, что длина значения элемента аннотации находится в пределах минимального и максимального интервалов</p><p>@Электронная почта</p><p>Значение элемента аннотации проверки – электронная почта. Вы также можете указать собственный формат электронной почты с помощью регулярных выражений и флагов</p><
2360242
None
Read more...
Инструкции по общим операциям GIT
<p> <strong>Когда вы сейчас занимаетесь разработкой программного обеспечения и говорите, что никогда не использовали git, вас просто нет. Но когда блоггеры используют git, они используют либо клиент git черепахи, либо встроенную операцию git в IDE. Команд git, кроме клонирования, немного. Не смею сказать, что разбираюсь в git, так что делайте заметки здесь! Обязательно пригодится</strong> </p><p> master: ветка разработки по умолчанию; origin: удаленный репозиторий по умолчанию </p><p>Операции инициализации</p><p> $ git config -global user.name#Установить имя отправителя</p><p> $ git config -global user.email#Установить адрес электронной почты отправителя</p><p> $ git config -global core.editor#Установить текстовый редактор по умолчанию</p><p> $ git config -global merge.tool#Установить инструмент анализа различий при разрешении конфликтов слияния</p><p> $ git config -list #Проверить существующую информацию о конфигурации</p><p>Создать новый репозиторий</p><p> $ git clone#Клонировать удаленный репозиторий</p><p> $ git init #Инициализируем библиотеку локальных версий</p><p>Изменить и отправить</p><p> $ git add #Добавить все измененные файлы</p><p> $ git add#Добавить указанный файл</p><p> $ git mv#Переименование файла</p><p> $ git rm#удалить файл</p><p> $ git rm -cached#Остановить отслеживание файлов, но не удалять их</p><p> $ git commit -m#Отправить указанный файл</p><p> $ git commit -m «commit message» #Отправить все обновленные файлы</p><p> $ git commit -amend #Изменить последний коммит</p><p> $ git commit -C HEAD -a -amend #Дополнительная отправка (новая история отправки создаваться не будет)</p><p>Просмотреть историю отправки</p><p> $ git log #Просмотр истории отправки</p><p> $ git log -p#Просмотреть историю отправки указанного файла</p><p> $ git Assessment#Просмотр истории отправки указанного файла в виде списка</p><p> $ git #Просмотр текущей истории веток</p><p> $ git#Просмотр истории ветки</p><p> $ gitk --all #Просмотреть всю историю веток</p><p> $ git Branch -v #Последний коммит каждой ветки</p><p> $ git status #Просмотреть текущий статус</p><p> $ git diff #Просмотр изменений</p><p>Отменить операцию</p><p> $ git reset -hard HEAD #Отменить все изменения незафиксированных файлов в рабочем каталоге</p><p> $ git checkout HEAD#Отменить изменения указанного незафиксированного файла</p><p> $ git checkout HEAD. #Отменить все файлы</p><p> $ git revert#Отменить указанный коммит</p><p>Ветвь и тег</p><p> $ git Branch #Показать все локальные ветки</p><p> $ git checkout#Переключиться на указанную ветку или метку</p><p> $ git Branch#Создать новую ветку</p><p> $ git Branch -d#Удалить локальную ветку</p><p> $ git tag #Перечислить все локальные теги</p><p> $ git tag#Создать тег на основе последнего коммита</p><p> $ git tag -d#удалить тег</p><p>Объединить и перебазировать</p><p> $ git merge#Объединить указанную ветку с текущей</p><p> $ git rebase#Перебазировать указанную ветку в текущую</p><p>Удаленная работа</p><p> $ git Remote -v #Просмотр информации об удаленном репозитории</p><p> $ git Remote show#Просмотр указанной информации об удаленном репозитории</p><p> $ git Remote add#Добавить удаленный репозиторий</p><p> $ git fetch#Получить код из удаленной библиотеки</p><p> $ git pull#Загрузить код и быстро объединить</p><p> $ git push#Загрузить код и быстро объединить</p><p> $ git push:/#Удалить удаленную ветку или тег</p><p> $ git push -tags #Загрузить все теги</p><
2360241
None
Read more...
чрезвычайно быстрая среда разработки Java Web+orm Jfinal
<h2 id="7up91" name="%E5%89%8D%E8%A8%80"> Предисловие </h2><p> <strong>Сегодня блоггер представляет вам Jfinal, внутреннюю среду разработки Java с открытым исходным кодом. Блогер уже знаком с разработкой thinkphp, но до этого не знаком с PHP. По сути, чтобы приступить к работе, требуется около двух дней! Я обнаружил, что дизайн Jfinal похож на thinkphp, потому что я мало что знаю о Jfinal, но он кажется мне знакомым. Я считаю, что для использования Jfinal практически не требуется затрат на обучение. Это очень отличная среда разработки, и она того стоит. рекомендую</strong> </p><h2 id="1lj0k" name="JAVA-%E6%9E%81%E9%80%9FWEB+ORM%E6%A1%86%E6%9E%B6-JFinal"> JAVA Чрезвычайно быстрая WEB+ORM Framework JFinal </h2><p> JFinal — это чрезвычайно быстрая среда WEB + ORM, основанная на языке Java. Ее основные цели проектирования — быстрая разработка, небольшой объем кода, простое обучение, мощные функции, легкий вес, простота расширения и Restful. Обладая всеми преимуществами языка Java, вы также обладаете эффективностью разработки Ruby, Python и других динамических языков! Сэкономьте больше времени, чтобы провести его с любимым человеком, семьей и друзьями ;) </p><li>Архитектура MVC, изысканный дизайн и простота использования.</li><li> Следуйте принципам COC, нулевая конфигурация, никакой XML </li><li> Оригинальный режим Db + запись, гибкий и удобный </li><li> Поддержка ActiveRecord делает разработку баз данных чрезвычайно быстрой </li><li> Автоматически загружать измененные файлы Java, нет необходимости перезапускать веб-сервер во время разработки. </li><li> Поддержка АОП, гибкая настройка перехватчика и мощные функции </li><li> Архитектура плагинов, высокая масштабируемость </li><li> Поддержка нескольких представлений, поддержка FreeMarker, JSP, Velocity </li><li> Мощная функция внутренней проверки Validator </li><li> Полнофункциональный, обладающий большинством функций struts2 </li><li> Небольшой размер (всего 218 КБ), никаких сторонних зависимостей </li><p> Ниже приведен пример реализации управления блогами в JFinal: </p><p> 1. Контроллер (поддерживает FreeMarker, JSP, Velocity, JSON и т. д., а также рендеринг настраиваемых представлений) </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@Before(BlogInterceptor.class) public class BlogController extends Controller { public void index() { setAttr("blogList", Blog.dao.find("select * from blog")); } public void add() { } @Before(BlogValidator.class) public void save() { getModel(Blog.class).save(); } public void edit() { setAttr("blog", Blog.dao.findById(getParaToInt())); } @Before(BlogValidator.class) public void update() { getModel(Blog.class).update(); } public void delete() { Blog.dao.deleteById(getParaToInt()); } }</code></pre><p> 2.Модель (без XML, без аннотаций, без атрибутов, без геттеров и без сеттеров, новая строка кода Blog() не требуется) </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public class Blog extends Model { public static final Blog dao = new Blog(); }</code></pre><p> 3. Валидатор (проверка на основе API, в N раз удобнее, чем проверка xml, менее подвержена ошибкам при проверке кода) </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public class BlogValidator extends Validator { protected void validate(Controller controller) { validateRequiredString("blog.title", "titleMsg", "请输入Blog标题!"); validateRequiredString("blog.content", "contentMsg", "请输入Blog内容!"); } protected void handleError(Controller controller) { controller.keepModel(Blog.class); } }</code></pre><p> 4. Перехватчик (только пример в этой демонстрации, этот перехватчик для этой демонстрации не требуется) </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public class BlogInterceptor implements Interceptor { public void intercept(Invocation inv) { System.out.println("Before invoking " + inv.getActionKey()); inv.invoke(); System.out.println("After invoking " + inv.getActionKey()); } }</code></pre><p> JFinal 官方网站:<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.jfinal.com%2F" rel="nofollow noopener" style=" цвет:#0052D9" target="_blank">http://www.jfinal.com</a> </p><p> <strong>Окончательное онлайн-руководство по разработке, составленное блоггером:</strong><a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.kailing.pub %2Fjfinal2.2%2Fjfinal-2.2-kl.html" rel="nofollow noopener" style="color:#0052D9" target="_blank">http://www.kailing.pub/jfinal2.2/jfinal-2.2 -kl.html</a> </p><
2360240
None
Read more...
Spring boot интегрирует Springfox для создания спокойного API-документа в Интернете
<p> <strong>Что такое Springfox и для чего он используется? </strong> </p><p> Springfox основан на Swagger, который легче интегрировать в Spring Boot. Swagger — это стандартизированная и полная среда для создания, описания, вызова и визуализации веб-служб в стиле RESTful. Цель Swagger — определить стандартный, независимый от языка интерфейс для REST API, который позволит людям и компьютерам обнаруживать и понимать возможности службы без доступа к исходному коду, документации или мониторингу сетевого трафика. При правильном определении с помощью Swagger пользователи могут понимать удаленную службу и взаимодействовать с ней, используя минимальную логику реализации. Подобно интерфейсам, реализованным для низкоуровневого программирования, Swagger исключает необходимость догадок, которые могут возникнуть при вызове служб. </p><p> Springfox: <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fspringfox.github.io%2Fspringfox%2Fdocs%2Fsnapshot%2F" rel=" nofollow noopener" style="color:#0052D9" target="_blank">http://springfox.github.io/springfox/docs/snapshot/</a> </p><p> Адрес моего проекта интеграции: <a class="" href="https://coding.net/u/kailingchen/p/SwaggerDemo/git?from_column=20421&from=20421" style="color:#0052D9" target ="_blank">https://coding.net/u/kailingchen/p/SwaggerDemo/git</a> </p><p> <strong>Зависимости Springfox</strong> </p><p><зависимость></p><p><зависимость></p><p><groupId>io.springfox</groupId></p><p><groupId>io.springfox</groupId></p><p><artifactId>springfox-swagger2</artifactId></p><p><версия>2.4.0</версия></p><p><версия>2.4.0</версия></p><p></зависимость></p><p><artifactId>springfox-swagger-ui</artifactId></p><p></зависимость> </p><p> <strong>Конфигурация Springfox</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket demoApi() { return new Docket(DocumentationType.SWAGGER_2) .groupName("demo") .genericModelSubstitutes(DeferredResult.class) .useDefaultResponseMessages(false) .forCodeGeneration(false) //.pathMapping("/") //根路径 .select() .paths(PathSelectors.regex("/user/.*"))//筛选展示的接口,使用PathSelectors.any(),展示所有接口 .build() .apiInfo(demoApiInfo()) ; } //api信息 private ApiInfo demoApiInfo() { ApiInfo apiInfo = new ApiInfo("自己平台的api",//大标题 "swagger搭建api平台",//小标题 "1.0",//版本 "NO terms of service", "632104866@qq.com",//作者 "这是我的技术博客站点",//链接显示文字 "http://www.kailing.pub"//网站链接 ); return apiInfo; } }</code></pre><p><strong>Контроль тестирования</strong></p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@RestController @RequestMapping("/user") public class SwaggerDemoController { @RequestMapping(value = "/demo2",method = RequestMethod.POST) @ApiOperation(value="测试接口1", notes="测试接口详细描述") @ResponseBody ModelMap getDemo(@RequestBody User user) { ModelMap map = new ModelMap(); map.addAttribute("userId", 111); map.addAttribute("userName", "kl博客"); return map; } @ResponseBody @RequestMapping(value = "/demo3", method = RequestMethod.POST) @ApiOperation(value="测试接口2", notes="测试接口详细描述",code = 200,produces = "application/json") public ModelMap getDemoa(@RequestParam("name") String demoName, @RequestParam String content) { ModelMap map = new ModelMap(); map.addAttribute("result",demoName + "AAA"); return map; } @ResponseBody @ApiIgnore //使用这个注解忽略这个接口 @RequestMapping(value = "/demo4", method = RequestMethod.POST) public ModelMap getDemob(@RequestParam String content) { ModelMap map = new ModelMap(); map.addAttribute("result",new java.util.Date()); return map; } }</code></pre><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">在浏览器输入http://localhost:8080/swagger-ui.html,可查看是否整合成功</code></pre><p> <strong>На этом этапе интеграция онлайн-документов API завершена, ниже представлен рендеринг</strong> </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-cbd200f8.png"/><
2360239
None
Read more...
Пользовательская обработка Gson Календарная дата Тип даты и времени
<p> <strong>Что такое Gson? </strong> </p><p> Gson – это библиотека Java, предоставляемая Google для сопоставления объектов Java и данных JSON. Вы можете преобразовать строку JSON в объект Java и наоборот. У Gson нет проблем с сериализацией и десериализацией общих типов, но такие типы, как календарные даты, возможно, придется обрабатывать вручную </p><p> <strong>Возникли проблемы? </strong> </p><p> Тип времени Дата и тип даты Календарь по умолчанию сериализуются в следующий формат данных </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-164915d7.png"/><p>Конечно, нам нужны не такие данные? Давайте преобразим его </p><p> <strong>Для решения проблемы смотрите код с подробными комментариями</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * @author kl by 2016/4/19 * @boke www.kailing.pub */ public class GsonTest { @Test public void test(){ TestDemo demo=new TestDemo(); demo.setDate(new Date()); demo.setCalendar(Calendar.getInstance()); //使用GsonBuilder来实例Gson,注册一个自定义处理Calendar日期类型序列化和反序列话的适配器,处理Calendar //添加一个格式化Date类型的格式,处理Date类型 Gson gson= new GsonBuilder().registerTypeHierarchyAdapter(Calendar.class, new CalendarSerializer()).setDateFormat("yyyy-MM-dd").create(); System.out.println(gson.toJson(demo)); } public class CalendarSerializer implements JsonSerializer, JsonDeserializer{ // 实现JsonSerializer接口的serialize()方法,实现自定义序列化josn @Override public JsonElement serialize(Calendar src, Type typeOfSrc, JsonSerializationContext context) { if (src == null) { return null; } else { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //JsonElement是一个抽象类,实现类分别是JsonObject和JsonPrimitive JsonObject ob=new JsonObject(); ob.addProperty("date", format.format(src.getTime())); // return ob ;//结果{"id":0,"date":"2016-04-19","calendar":{"date":"2016-04-19 21:53:54"}} return new JsonPrimitive(format.format(src.getTime()));//结果{"id":0,"date":"2016-04-19","calendar":"2016-04-19 21:54:31"} } } //实现JsonDeserializer接口的deserialize()方法,实现自定义反序列化Object @Override public Calendar deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Date date = null; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { date = format.parse(json.getAsJsonObject().get("date").getAsString()); } catch (ParseException e) { date = null; } GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTime(date); return gregorianCalendar; } } }</code></pre><
2360238
None
Read more...
Пользовательская обработка Gson Календарная дата Тип даты и времени
<p> <strong>Что такое Gson? </strong> </p><p> Gson – это библиотека Java, предоставляемая Google для сопоставления объектов Java и данных JSON. Вы можете преобразовать строку JSON в объект Java и наоборот. У Gson нет проблем с сериализацией и десериализацией общих типов, но такие типы, как календарные даты, возможно, придется обрабатывать вручную </p><p> <strong>Возникли проблемы? </strong> </p><p> Тип времени Дата и тип даты Календарь по умолчанию сериализуются в следующий формат данных </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-164915d7.png"/><p>Конечно, нам нужны не такие данные? Давайте преобразим его </p><p> <strong>Для решения проблемы смотрите код с подробными комментариями</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * @author kl by 2016/4/19 * @boke www.kailing.pub */ public class GsonTest { @Test public void test(){ TestDemo demo=new TestDemo(); demo.setDate(new Date()); demo.setCalendar(Calendar.getInstance()); //使用GsonBuilder来实例Gson,注册一个自定义处理Calendar日期类型序列化和反序列话的适配器,处理Calendar //添加一个格式化Date类型的格式,处理Date类型 Gson gson= new GsonBuilder().registerTypeHierarchyAdapter(Calendar.class, new CalendarSerializer()).setDateFormat("yyyy-MM-dd").create(); System.out.println(gson.toJson(demo)); } public class CalendarSerializer implements JsonSerializer, JsonDeserializer{ // 实现JsonSerializer接口的serialize()方法,实现自定义序列化josn @Override public JsonElement serialize(Calendar src, Type typeOfSrc, JsonSerializationContext context) { if (src == null) { return null; } else { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //JsonElement是一个抽象类,实现类分别是JsonObject和JsonPrimitive JsonObject ob=new JsonObject(); ob.addProperty("date", format.format(src.getTime())); // return ob ;//结果{"id":0,"date":"2016-04-19","calendar":{"date":"2016-04-19 21:53:54"}} return new JsonPrimitive(format.format(src.getTime()));//结果{"id":0,"date":"2016-04-19","calendar":"2016-04-19 21:54:31"} } } //实现JsonDeserializer接口的deserialize()方法,实现自定义反序列化Object @Override public Calendar deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Date date = null; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { date = format.parse(json.getAsJsonObject().get("date").getAsString()); } catch (ParseException e) { date = null; } GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTime(date); return gregorianCalendar; } } }</code></pre><
2360237
None
Read more...
Использование инструмента загрузки Linux wget
<p><strong>Примеры использования:</strong></p><p> Команда: загрузить файл wordpress-3.1-zh_CN.zip в текущий каталог</p><p> wget http://www.minjieren.com/wordpress-3.1-zh_CN.zip </p><p> <strong>Ниже приведены подробные параметры команды</strong> </p><p> <strong>1. Формат команды: </strong> </p><p> wget [параметр] [URL-адрес] </p><p> <strong>2. Функция команды: </strong> </p><p> используется для загрузки ресурсов из Интернета. Если каталог не указан, загружаемые ресурсы по умолчанию будут находиться в текущем каталоге. Несмотря на то, что wget является мощным инструментом, его по-прежнему относительно просто использовать: </p><p> 1) Поддержка функции загрузки точек останова; в то время это также было самым большим преимуществом Internet Ant и FlashGet. Теперь Wget также может использовать эту функцию, поэтому пользователи с плохими условиями сети могут быть уверены; </p><p> 2) Поддерживает методы загрузки как по FTP, так и по HTTP; хотя большую часть программного обеспечения теперь можно загрузить с помощью HTTP, иногда для загрузки программного обеспечения все равно необходимо использовать FTP; </p><p> 3) Поддержка прокси-сервера; для систем с высоким уровнем безопасности они обычно не подключают свои системы напрямую к Интернету, поэтому поддержка прокси-сервера является обязательной функцией для загрузки программного обеспечения; </p><p>4) Удобен и прост в настройке, возможно, пользователи, привыкшие к графическим интерфейсам, уже не привыкли к командной строке. Однако командная строка на самом деле имеет больше преимуществ в настройке. Как минимум, можно нажать кнопку мыши во много раз меньше, так что не волнуйтесь. Вы нажали не ту мышь?</p><p> 5) Программа маленькая и полностью бесплатная; маленькую программу можно игнорировать, потому что текущий жесткий диск слишком велик; следует рассмотреть полностью бесплатную программу. Хотя в Интернете много так называемого бесплатного программного обеспечения. , реклама этого программного обеспечения. Но это не то, что нам нравится. </p><p> <strong>3. Параметры команды: </strong> </p><p> <strong>Параметры запуска:</strong> </p><p> -V, –version отображает версию wget и завершает работу </p><p> -h, –help вывести справку по синтаксису </p><p> -b, –background Перейти в фоновый режим после запуска </p><p> -e, –execute=КОМАНДА Выполнять команды в формате .wgetrc. Формат wgetrc см. в /etc/wgetrc или ~/.wgetrc </p><p> <strong>Запишите и введите параметры файла:</strong> </p><p> -o, –output-file=FILE Записывать записи в файл FILE </p><p> -a, –append-output=FILE Добавить записи в файл FILE </p><p> -d, –debug распечатать выходные данные отладки </p><p> -q, –quiet Тихий режим (без вывода) </p><p> -v, –verbose подробный режим (это настройка по умолчанию) </p><p> -nv, –non-verbose отключает подробный режим, но не тихий режим </p><p> -i, –input-file=FILE URL-адреса загрузки, которые появляются в файле FILE </p><p> -F, –force-html Обрабатывать входной файл как файл формата HTML </p><p> -B, –base=URL Использовать URL-адрес в качестве префикса для относительных ссылок, которые появляются в файле, указанном параметром -F -i </p><p> –sslcertfile=ФАЙЛ необязательный сертификат клиента </p><p> –sslcertkey=KEYFILE Необязательный сертификат клиента KEYFILE </p><p> –egd-file=FILE указывает имя файла сокета EGD </p><p> <strong>Параметры загрузки: </strong> </p><p> –bind-address=ADDRESS указывает локальный адрес (имя хоста или IP-адрес, используется при наличии нескольких локальных IP-адресов или имен) </p><p> -t, –tries=NUMBER устанавливает максимальное количество попыток подключения (0 означает неограниченное количество).</p><p> -O –output-document=FILE записывает документ в файл FILE </p><p> -nc, –no-clobber Не перезаписывать существующие файлы и не использовать префикс .# </p><p> -c, –continue, затем загрузите незавершенные файлы </p><p> –progress=TYPE Установить отметку индикатора выполнения </p><p> -N, –timestamping Не загружать повторно файлы, если они не новее локальных файлов </p><p> -S, –server-response ответ сервера печати </p><p> –паук ничего не загружает </p><p> -T, –timeout=SECONDS Установить количество секунд для таймаута ответа </p><p> -w, –wait=SECONDS СЕКУНДЫ секунд между попытками </p><p> –waitretry=SECONDS Подождите 1…SECONDS секунд между повторными подключениями </p><p> –random-wait Подождите 0…2*WAIT секунд между загрузками </p><p> -Y, –proxy=on/off Включить или выключить прокси </p><p> -Q, –quota=NUMBER Установить ограничение емкости загрузки </p><p> –limit-rate=RATE Ограничить скорость загрузки </p><p> <strong>Параметры каталога: </strong> </p><p> -nd –no-directory Не создавать каталоги </p><p> -x, –force-directories Принудительное создание каталога </p><p> -nH, –no-host-directory Не создавать каталоги хоста </p><p> -P, –directory-prefix=PREFIX Сохраните файл в каталоге PREFIX/… </p><p> –cut-dirs=НОМЕР Игнорировать удаленные каталоги на уровне НОМЕР </p><p> <strong>Параметры параметров HTTP:</strong> </p><p> –http-user=USER Установите имя пользователя HTTP как USER. </p><p> –http-passwd=PASS Установите пароль http на PASS </p><p> -C, –cache=on/off разрешает/запрещает кэширование данных на стороне сервера (обычно разрешено) </p><p> -E, –html-extension Сохранить все текстовые/html-документы с расширением .html </p><p> –ignore-length игнорирует поле заголовка Content-Length </p><p> –header=STRING вставляет строку STRING в заголовки </p><p> –proxy-user=ПОЛЬЗОВАТЕЛЬ Установите имя пользователя прокси-сервера ПОЛЬЗОВАТЕЛЬ </p><p> –proxy-passwd=PASS Установить пароль прокси-сервера PASS </p><p> –referer=URL включает заголовок «Referer: URL» в HTTP-запрос </p><p> -s, –save-headers Сохранять заголовки HTTP в файл </p><p> -U, –user-agent=AGENT устанавливает имя агента AGENT вместо Wget/VERSION </p><p> –no-http-keep-alive Отключить активные ссылки HTTP (постоянные ссылки) </p><p> –cookies=off Не использовать файлы cookie </p><p> –load-cookies=FILE Загружать файлы cookie из файла FILE перед началом сеанса </p><p> –save-cookies=FILE Сохранять файлы cookie в файл FILE после сеанса </p><p> <strong>Параметры FTP-опции:</strong> </p><p> -nr, –dont-remove-listing Не удалять файлы `.listing' </p><p> -g, –glob=on/off Включить или выключить механизм подстановки имен файлов </p><p> –passive-ftp Использовать пассивный режим передачи (по умолчанию). </p><p> –active-ftp Использовать активный режим передачи </p><p> --retr-symlinks указывает ссылки на файлы (а не на каталоги) при рекурсии </p><p> <strong>Параметры рекурсивной загрузки:</strong> </p><p> -r, –recursive Рекурсивная загрузка — используйте с осторожностью! </p><p> -l, –level=NUMBER Максимальная глубина рекурсии (inf или 0 представляет бесконечность) </p><p> --delete-after частично удаляет файлы после завершения </p><p> -k, –convert-links Преобразовать неотносительные ссылки в относительные </p><p> -K, –backup-converted Создайте резервную копию файла X как X.orig перед его преобразованием </p><p> -m, –mirror эквивалентно -r -N -l inf -nr </p><p> -p, –page-реквизиты Загрузить все изображения, отображаемые в файлах HTML </p><p> <strong>Включение и исключение (принятие/отклонение) при рекурсивных загрузках:</strong> </p><p> -A, –accept=LIST Список принятых расширений, разделенных точкой с запятой </p><p> -R, –reject=LIST Список неприемлемых расширений, разделенных точкой с запятой </p><p> -D, –domains=LIST Список принятых доменов, разделенных точкой с запятой </p><p> –exclude-domains=LIST Список неприемлемых доменов, разделенных точкой с запятой </p><p> –follow-ftp следует по FTP-ссылкам в HTML-документах </p><p> –follow-tags=LIST Список отслеживаемых HTML-тегов, разделенных точкой с запятой </p><p> -G, –ignore-tags=LIST Список игнорируемых HTML-тегов, разделенных точкой с запятой </p><p> -H, –span-hosts Перейти на внешний хост при рекурсии </p><p> -L, –relative Переходить только по относительным ссылкам </p><p> -I, –include-directories=СПИСОК Список разрешенных каталогов </p><p> -X, –exclude-directories=СПИСОК Список каталогов, которые не следует включать </p><p> -np, –no-parent Не выполнять обратную трассировку до родительского каталога </p><p> wget -S – URL-адрес паука не загружается, а только отображает процесс </p><
2360236
None
Read more...
Использование команды scp для удаленного копирования между хостами Linux
<p><strong>Команда: scp</strong></p><p>Копирование файлов между разными хостами Linux</p><p>Копирование файла с безопасностью на основе входа в систему по ssh. </p><p>Некоторые дистрибутивы Linux не включают scp, поэтому его необходимо установить</p><p># yum -y install openssh-clients</p><p><strong>Основной синтаксис: </strong></p><p># исходный объект scp [параметр]</p><p><strong>Общие параметры </strong></p><p>-v: отображение прогресса, может использоваться для проверки ошибок соединения, аутентификации или конфигурации</p><p>-r: Каталог назначения</p><p>-C: включить опцию сжатия </p><p>-P: выбрать порт</p><p>-4: принудительно использовать адреса IPV4</p><p>-6: принудительно использовать адреса IPV6</p><p><strong>Общее использование:</strong></p><p><strong>Копировать локально на удаленный</strong>Копировать папку (включая саму папку)</p><p>scp -r /home/wwwroot/www/charts/util root@192.168.1.65:/home/wwwroot/limesurvey_back/scp</p><p>Скопируйте все файлы в папке (кроме самой папки)</p><p>scp /home/wwwroot/www/charts/util/* root@192.168.1.65:/home/wwwroot/limesurvey_back/scp</p><p><strong>Чтобы скопировать с удаленного компьютера на локальный, просто замените локальный путь и удаленный адрес, например</strong></p><p>scp root@192.168.1.65:/home/wwwroot/limesurvey_back/scp /home/wwwroot/www/charts/util/*</p><p><strong>Примечание:</strong></p><p>4.1: Если удаленный сервер меняет ssh-порт, scp должен использовать измененный порт. Если ssh-порт удаленного сервера равен 2222, вам необходимо добавить параметр -P: </p><p># scp -p 2222 /doiido/hello.sh dodo@192.168.100.2:/doiido</p><
2360235
None
Read more...
Вопросы и ответы на первое собеседование с Alibaba Java
<p> <strong>Запишите здесь вопросы Али для интервью. Путь долгий, и нам еще многое предстоит изучить</strong> </p><p> (1) Представьтесь. </p><p> (2) Как JVM загружает класс? Какие методы есть в модели родительского делегирования? </p><p>С момента загрузки класса в память виртуальной машины до момента его выгрузки из памяти весь его жизненный цикл включает семь этапов: загрузка, проверка, подготовка, разбор, инициализация, использование и выгрузка. Процесс загрузки класса включает пять этапов: загрузка, проверка, подготовка, синтаксический анализ и инициализация. Среди этих пяти этапов порядок, в котором происходят четыре этапа загрузки, проверки, подготовки и инициализации, является детерминированным, в то время как этап синтаксического анализа не является обязательным. В некоторых случаях он может начинаться после этапа инициализации. Это необходимо для поддержки языка Java A. привязка времени выполнения (также известная как динамическая привязка или поздняя привязка). Также обратите внимание, что здесь несколько этапов запускаются последовательно, а не выполняются или завершаются по порядку, поскольку эти этапы обычно чередуются и смешиваются друг с другом, обычно вызывая или активируя другой этап во время выполнения одного этапа. </p><p> Модель родительского делегирования требует, чтобы в дополнение к загрузчику классов запуска верхнего уровня все остальные загрузчики классов имели собственный загрузчик родительских классов. Отношения родитель-потомок этих загрузчиков классов реализуются не путем наследования, а с помощью комбинированных отношений для повторного использования кода родительского загрузчика. </p><p> Рабочий процесс модели родительского делегирования: если загрузчик классов получает запрос на загрузку класса, он не пытается сначала загрузить сам класс, а делегирует запрос родительскому загрузчику классов для завершения на каждом уровне. Это верно для всех загрузчиков классов. Таким образом, все запросы на загрузку в конечном итоге должны передаваться загрузчику запускаемых классов верхнего уровня. Только когда обратная связь родительского загрузчика не может завершить запрос на загрузку (нужный класс не найден в его области поиска), дочерний загрузчик попытается загрузить его самостоятельно. . </p><p> findLoadedClass(имя); loadClass (имя, ложь); НайтиКласс (имя); разрешитьКласс (с); </p><p>(3) Как реализован HashMap? </p><p>Хеш-таблица состоит из массива + связанного списка. Далее я объясню наиболее часто используемый метод – метод Zipper, который мы можем понимать как "массив связанных списков"</p><p>(4) Разница между HashMap и ConcurrentHashMap. Является ли Concurrent HashMap потокобезопасной хеш-таблицей? Как ConcurrentHashMap обеспечивает потокобезопасность? </p><p> Сегментированная блокировка </p><p> Как видно из кода ConcurrentHashMap, он вводит концепцию «блокировки сегмента», которую можно понимать как разделение большой карты на N маленьких HashTables и принятие решения в соответствии с key.hashCode(), в которой HashTable является ключом. размещен. </p><p> В ConcurrentHashMap карта разделена на сегменты N. При вводе и получении сегмент рассчитывается на основе key.hashCode()</p><p>(5) Разница между HashMap и HashTable: является ли HashTable потокобезопасным? </p><p>HashMap — это облегченная реализация Hashtable (непотокобезопасная реализация). Они оба дополняют интерфейс Map. Основное отличие состоит в том, что HashMap допускает пустые (нулевые) значения ключа (key). Поскольку он не является потоковым -безопасно, возможно, это будет более эффективно в Hashtable. HashMap позволяет использовать значение null в качестве ключа или значения записи, а Hashtable — нет. HashMap удалил метод contains из Hashtable и заменил его на containsvalue и containsKey. Потому что метод contains легко ввести в заблуждение. Hashtable наследует класс Dictionary, а HashMap — это реализация интерфейса Map, представленного в Java 1.2. Самая большая разница заключается в том, что метод Hashtable является синхронизированным, а метод HashMap — нет. Когда несколько потоков обращаются к Hashtable, вам не нужно самостоятельно синхронизировать его методы, в то время как HashMap должен обеспечить для него внешнюю синхронизацию. Алгоритмы хеширования/перехеширования, используемые Hashtable и HashMap, примерно одинаковы, поэтому большой разницы в производительности не будет.</p><p>(6) Каковы методы межпроцессного взаимодействия? </p><p> 1. Несколько методов межпроцессного взаимодействия</p><p> # Pipe (труба): Pipe — это полудуплексный метод связи. Данные могут передаваться только в одном направлении и могут использоваться только между связанными процессами. Сходство процессов обычно относится к отношениям родитель-потомок процесса. </p><p> # Именованный канал: Именованный канал также является полудуплексным методом связи, но он позволяет осуществлять связь между несвязанными процессами. </p><p> # Семафор (семофор): Семафор — это счетчик, который можно использовать для управления доступом к общим ресурсам нескольких процессов. Он часто используется в качестве механизма блокировки, чтобы предотвратить доступ других процессов к общему ресурсу, когда процесс обращается к ресурсу. Поэтому он в основном используется как средство синхронизации между процессами и между различными потоками внутри одного процесса. </p><p> # Очередь сообщений (очередь сообщений): Очередь сообщений представляет собой связанный список сообщений, который хранится в ядре и идентифицируется идентификатором очереди сообщений. Очереди сообщений преодолевают недостатки меньшего количества передаваемой информации, каналы могут передавать только неформатированные потоки байтов и ограниченные размеры буфера. </p><p> # Сигнал (sinal): Сигнал — это относительно сложный метод связи, используемый для уведомления принимающего процесса о произошедшем событии. </p><p> # Общая память (разделяемая память): Общая память предназначена для отображения раздела памяти, к которому могут получить доступ другие процессы. Эта общая память создается одним процессом, но к ней могут обращаться несколько процессов. Общая память — это самый быстрый метод IPC, специально разработанный для устранения неэффективности других методов межпроцессного взаимодействия. Он часто используется в сочетании с другими механизмами связи, такими как сигналы, для достижения синхронизации и связи между процессами. </p><p>#Socket (сокет): Сокет также является механизмом межпроцессного взаимодействия.В отличие от других механизмов связи, он может использоваться для связи между различными и межпроцессными процессами. </p><p>(7) На какие области разделена JVM и что делает каждая область? </p><p>Большинство JVM делят область памяти на область методов, Heap (куча), Program Counter Register (счетчик программ), VM Stack (стек виртуальной машины Java), Native Method Stack (локальный стек методов)</p><p> Область метода: общая область потока, данные класса объекта (данные определения класса загруженных классов) хранятся в области метода. Кроме того, в области методов также находятся константы, статические переменные и JIT-компилятор (JIT-компилятор). </p><p> Счетчик программы — это небольшая область памяти, которую можно рассматривать как индикатор позиции байт-кода, выполняемого текущим потоком. Базовые функции, такие как ветвления, циклы, переходы, обработка исключений и восстановление потоков, выполняются с помощью этого калькулятора, и сказать особо нечего. </p><p> Стек виртуальной машины Java: стек виртуальной машины Java является частным для потока и имеет тот же жизненный цикл, что и поток. Он описывает модель памяти выполнения метода Java. (При выполнении каждого метода стек кадров (Strack Frame) создается для хранения таблицы локальных переменных, стека операндов, динамической ссылки, выхода метода и другой информации)</p><p> Куча — это самая большая часть памяти, управляемая виртуальной машиной. Это область памяти, совместно используемая потоками. Она создается при запуске JVM и специально используется для сохранения экземпляров объектов. </p><p> Стек собственных методов. Подобно VM Strack, VM Strack предоставляет JVM службы для выполнения методов JAVA, а стек собственных методов предоставляет JVM службы для использования собственных методов. </p><p>(8) Как JVM выполняет сборщик мусора? Какие большие объекты хранятся в новом поколении, старом поколении и постоянном поколении? </p><p> Используйте алгоритм коллекции поколений, новое поколение использует алгоритм копирования, а старое поколение использует алгоритм сортировки по меткам. </p><p>Новое поколение – вновь созданные объекты</p><p>Старое поколение – объекты или большие объекты, которые не были переработаны после нескольких сборок мусора.</p><p> Постоянное поколение – память, используемая JVM, включая информацию о классах и т. д.</p><p>(9) Какие объекты в алгоритме анализа достижимости ссылок, используемом GC, можно использовать в качестве корневых объектов GC? </p><p> Для Younggc объекты gcroot включают: </p><p> 1. Все объекты старого поколения</p><p> 2. Все глобальные объекты</p><p> 3. Все дескрипторы jni</p><p> 4. Все заблокированные объекты</p><p> 5. Объекты, хранящиеся в jvmti</p><p> 6. Фрагмент кода code_cache</p><p> 7. Все загрузчики классов и загруженные ими классы</p><p> 8. Все словари</p><p> 9. Flat_profiler и управление</p><p> 10. Самое главное — это переменные ссылочного типа в стеке всех запущенных потоков. </p><p>(10) Быстрая сортировка, процесс, сложность? </p><p>Быстрая сортировка – это усовершенствованная версия пузырьковой сортировки. </p><p> Разделите данные, подлежащие сортировке, на две независимые части с помощью однопроходной сортировки. Все данные в одной части меньше, чем все данные в другой части. Затем используйте этот метод для быстрой сортировки двух частей данных по отдельности. Весь процесс сортировки может выполняться рекурсивно, так что все данные становятся упорядоченной последовательностью. </p><p> nln(n)</p><p>(11) Что такое двоичное сбалансированное дерево, как вставлять узлы, удалять узлы и рассказывать ключевые шаги. </p><p> Это пустое дерево или абсолютное значение разницы высот между его левым и правым поддеревьями не превышает 1. То есть коэффициент баланса каждого узла AVL-дерева может быть только -1, 0 и 1 (высота левого поддерева минус высота правого поддерева). И левое, и правое поддеревья являются сбалансированными двоичными деревьями. </p><p> Для регулировки баланса требуется вращение: всего существует четыре ситуации: лево-лево, лево-право, право-право и право-лево. </p><p>Разница между левым и правым потомками не превышает 1, двойной поворот в четырех ситуациях</p><p>(12) Как TCP обеспечивает надежную передачу? Процесс трехстороннего рукопожатия? </p><p> TCP использует трехэтапное рукопожатие и механизм скользящего окна для обеспечения надежности передачи и управления потоком. </p><p>Первое рукопожатие:</p><p> Клиент отправляет TCP-пакет с флагом SYN, установленным в 1, указывающим порт сервера, к которому клиент намеревается подключиться, и начальный порядковый номер X, который хранится в поле Sequence Number заголовка пакета. </p><p>Второе рукопожатие:</p><p> Сервер отправляет обратно ответ в виде пакета подтверждения (ACK). То есть, когда бит флага SYN и бит флага ACK равны 1, номер подтверждения (номер подтверждения) устанавливается равным I S N клиента плюс 1. То есть X+1. </p><p>Третье рукопожатие.</p><p> Клиент снова отправляет пакет подтверждения (ACK) с битом флага SYN, установленным в 0, и битом флага ACK, установленным в 1. Он также добавляет 1 в поле порядкового номера ACK, отправленного сервером, и помещает его в поле поле подтверждения и отправляет его собеседнику. И помещает в раздел данных. +1 за написание ISN</p><p>(13) В чем разница между TCP и UDP? </p><p> TCP — протокол управления передачей обеспечивает ориентированные на соединение и надежные службы потоков байтов. Прежде чем клиент и сервер смогут обмениваться данными друг с другом, между двумя сторонами должно быть установлено TCP-соединение, прежде чем данные смогут быть переданы. TCP обеспечивает повторную передачу по тайм-ауту, удаление повторяющихся данных, проверку данных, управление потоком и другие функции, гарантирующие возможность передачи данных с одного конца на другой. </p><p> UDP — протокол пользовательских дейтаграмм — это простой протокол транспортного уровня, ориентированный на дейтаграммы. UDP не обеспечивает надежности: он лишь отправляет дейтаграммы, передаваемые приложением, на уровень IP, но нет никакой гарантии, что они дойдут до места назначения. Поскольку UDP не требуется устанавливать соединение между клиентом и сервером перед передачей дейтаграммы, и нет такого механизма, как повторная передача по тайм-ауту, скорость передачи очень высокая</p><p> (14) Алгоритм скользящего окна? </p><p> Мы можем примерно взглянуть на модель на картинке выше: </p><p> 1. Сначала между AB происходит трехстороннее рукопожатие для установления TCP-соединения. Во время обмена сообщениями A отправляет размер своего буфера (размер окна) 3 B, а B делает то же самое, чтобы обе стороны знали размер окна другого конца. </p><p> 2. A начинает отправлять данные, а A непрерывно отправляет 3 единицы данных, потому что он знает размер буфера B. После отправки этой волны данных A больше не может ее отправлять и ему необходимо дождаться подтверждения от B. </p><p> 3. Данные, отправленные A, постепенно заполняют буфер. </p><p> 4. В это время сообщение в буфере считывается процессом, и в буфере есть свободное место, поэтому B отправляет ACK A. Это сообщение указывает, что размер окна равен 1. </p><p> A получает сообщение ACK от B и знает, что B установил размер окна на 1, поэтому он отправляет только одну единицу данных и ждет следующего подтверждающего сообщения от B. </p><p>5. Неоднократно. </p><p>(15) Как планировать процессы в Linux? </p><p> В Linux процессы не могут работать дольше, чем назначенный им интервал времени.Они используют вытесняющую многозадачность, поэтому процессы могут приостанавливать и продолжать работу без взаимодействия друг с другом. </p><p> 4 типа, критическая секция, мьютекс, семафор, </p><p>(16) Какие команды вы чаще всего используете в Linux? </p><p> pwd отображает текущий каталог ls просматривает содержимое каталога cd изменяет каталог cat отображает содержимое файла grep ищет символ в файле cp копирует файл touch создает файл mv перемещает файл rm удаляет файл rmdir удаляет каталог</p><p>(17) При каких обстоятельствах операционная система заблокируется? </p><p> Причины тупиковой ситуации: во-первых, количество ресурсов, предоставляемых системой, ограничено и не может удовлетворить использование каждого процесса; во-вторых, при запуске нескольких программ порядок продвижения процессов является необоснованным. </p><p> Необходимыми условиями взаимоблокировки являются: 1. Условие взаимного исключения 2. Условие неизбежности (невытеснения) 3. Частичное распределение 4. Ожидание цикла. </p><p>(18) Какие алгоритмы хэширования обычно используются? </p><p> Алгоритмы общего хеширования включают MD5 и SHA, но алгоритм обобщенного хеширования относится к отображению большого диапазона в малый диапазон. Если это соответствует вашему определению, то это не в счет. Это обобщенный алгоритм хеширования. </p><p>(19) Что такое последовательное хеширование? </p><p> Алгоритм последовательного хеширования — это алгоритм реализации распределенного хеширования (DHT). Целью разработки является решение проблемы «горячих точек» в Интернете. Первоначальная цель очень похожа на CARP. Согласованное хеширование устраняет проблемы, вызванные простым алгоритмом хеширования, используемым CARP, позволяя по-настоящему применять распределенное хеширование (DHT) в среде P2P. </p><p> Алгоритм последовательного хеширования предлагает четыре определения для определения качества алгоритма хеширования в динамически изменяющейся среде кэша:</p><p> 1. Баланс: Баланс означает, что результаты хеширования могут быть максимально распределены по всем буферам, чтобы можно было использовать все буферное пространство. Многие алгоритмы хеширования могут удовлетворять этому условию. </p><p> 2. Монотонность: Монотонность означает, что если некоторый контент уже был распределен в соответствующий буфер посредством хеширования, то в систему добавляется новый буфер. Результат хэширования должен гарантировать, что исходное выделенное содержимое может быть сопоставлено с исходным или новым буфером и не будет сопоставлено с другими буферами в старом наборе буферов. </p><p> 3. Дисперсия (Spread): В распределенной среде терминал может видеть не все буферы, а только часть из них. Когда терминал надеется сопоставить контент с буфером посредством процесса хеширования, диапазон буфера, видимый разными терминалами, может быть разным, что приводит к противоречивым результатам хэширования. Конечный результат заключается в том, что один и тот же контент отображается в разные буферы разными терминалами. буфер. Очевидно, что такой ситуации следует избегать, поскольку она приводит к тому, что один и тот же контент сохраняется в разных буферах, что снижает эффективность системного хранилища. Дисперсия определяется как серьезность вышеуказанных явлений. Хороший алгоритм хэширования должен уметь максимально избегать несогласованностей, то есть максимально уменьшать дисперсию. </p><p> 4. Нагрузка. Проблема нагрузки фактически рассматривает проблему дисперсии под другим углом. Поскольку разные терминалы могут отображать один и тот же контент в разные буферы, конкретный буфер также может быть сопоставлен с различным контентом разными пользователями. Подобно дисперсии, этой ситуации следует избегать, поэтому хороший алгоритм хеширования должен минимизировать нагрузку на буфер. </p><p>(20) Как понимать распределенные блокировки? </p><p> Распределенные блокировки — это способ управления синхронным доступом к общим ресурсам между распределенными системами. В распределенных системах часто возникает необходимость координировать свои действия. Если разные системы или разные хосты одной системы совместно используют один или группу ресурсов, то при доступе к этим ресурсам часто требуется взаимное исключение для предотвращения взаимных помех и обеспечения согласованности.В этом случае необходимо использовать распределенные блокировки. </p><p>(21) Каковы парадигмы базы данных? </p><p> Первая нормальная форма: обеспечить атомарность каждого столбца.</p><p> Если каждый столбец (или каждый атрибут) представляет собой наименьшую единицу данных, которую нельзя разделить далее (также называемую наименьшей атомарной единицей), он удовлетворяет первой нормальной форме.</p><p> Например: таблица клиентов (имя, номер, адрес...), где столбец «адрес» также можно разделить на страны, провинции, города, районы и т. д. </p><p> Вторая нормальная форма: шаг вперед на основе первой нормальной формы. Цель – гарантировать, что каждый столбец в таблице связан с первичным ключом.</p><p> Если связь удовлетворяет первой нормальной форме и все остальные столбцы, кроме первичного ключа, зависят от первичного ключа, она удовлетворяет второй нормальной форме.</p><p> Например: таблица заказов (номер заказа, номер продукта, дата заказа, цена,...), «номер заказа» является первичным ключом, а «номер продукта» не имеет прямой связи со столбцом первичного ключа, что То есть столбец «Номер продукта» не зависит от. Для столбцов первичного ключа этот столбец следует удалить. </p><p> Третья нормальная форма: шаг вперед на основе второй нормальной формы. Цель – обеспечить, чтобы каждый столбец был напрямую связан со столбцом первичного ключа, а не косвенно.</p><p> Если связь удовлетворяет второй нормальной форме и другие столбцы, за исключением первичного ключа, не зависят от столбца первичного ключа, она удовлетворяет третьей нормальной форме.</p><p> Чтобы понять третью нормальную форму, необходимо определить транзитивную зависимость в соответствии с одним из километров Армстронга. Предположим, что А, В и С — три атрибута связи R. Если А->В и В->С, то из этих функциональных зависимостей можно вывести А->С. Как говорилось выше, зависимость от А->С C — транзитивные зависимости. </p><p> Например: таблица заказов (номер заказа, дата заказа, номер клиента, имя клиента...). На первый взгляд с таблицей нет проблем. Она удовлетворяет второй нормальной форме. Каждый столбец связан с столбец первичного ключа "номер заказа". Давайте углубимся в подробности. Если вы посмотрите на него, вы обнаружите, что "имя клиента" связано с "номером клиента", "номер клиента" и "номер заказа" связаны, и, наконец, через транзитивную зависимость «имя клиента» также связано с «номером заказа». Чтобы удовлетворить третью нормальную форму, столбец «Имя клиента» следует удалить и поместить в таблицу клиентов. </p><p>(22) Какова структура индекса в базе данных? При каких обстоятельствах целесообразно создавать индекс? </p><p> (23) Что такое NIO, BIO и AIO в Java? </p><p> Синхронная блокировка ввода-вывода (JAVA BIO):</p><p>Синхронизация и блокировка, режим реализации сервера - одно соединение и один поток, то есть, когда у клиента есть запрос на соединение, серверу необходимо запустить поток для обработки. Если это соединение ничего не делает, это вызовет ненужные накладные расходы на потоки.Конечно, это можно улучшить с помощью механизма пула потоков. </p><p> Синхронный неблокирующий ввод-вывод (Java NIO): Синхронный неблокируемый режим реализации сервера — один запрос на поток, то есть запрос на соединение, отправленный клиентом, будет зарегистрирован в мультиплексоре, и мультиплексор опрашивает A поток запускается для обработки только при наличии запроса ввода-вывода для соединения. Пользовательскому процессу также необходимо время от времени спрашивать, готова ли операция ввода-вывода, что требует, чтобы пользовательский процесс продолжал запрашивать. </p><p> Асинхронный блокирующий ввод-вывод (Java NIO): </p><p>Этот метод означает, что после того, как приложение инициирует операцию ввода-вывода, оно не ждет завершения операции ввода-вывода ядра. После того, как ядро завершит операцию ввода-вывода, оно уведомит приложение. На самом деле это самое критическое различие между синхронный и асинхронный Синхронизация должна ждать или активно спрашивать, завершен ли ввод-вывод, так почему же он считается заблокированным? Потому что это делается через системный вызов select, а реализация самой функции select является блокирующей. Преимущество использования функции select заключается в том, что она может контролировать несколько дескрипторов файлов одновременно (если вы посмотрите на это с точки зрения UNP). , выбор — это синхронизированная операция, поскольку после выбора процессу все равно необходимо читать и записывать данные), тем самым улучшая параллелизм системы! </p><p> (Java AIO(NIO.2)) Асинхронный неблокирующий ввод-вывод: </p><p> В этом режиме пользовательскому процессу необходимо только инициировать операцию ввода-вывода, а затем немедленно вернуться. После фактического завершения операции ввода-вывода приложение будет уведомлено о завершении операции ввода-вывода. В это время только пользовательский процесс Ну, нет необходимости выполнять фактические операции чтения и записи ввода-вывода, поскольку реальные операции чтения или записи ввода-вывода были завершены ядром. </p><p>(24) Какие инструменты используются для отладки программ? JConsole, ты ею пользовался? </p><p> JConsole — это встроенный анализатор производительности Java, </p><p> 概述: отображает обзорную информацию о виртуальной машине Java и отслеживаемых значениях.</p><p> Память: отображение информации об использовании памяти</p><p> Тема: отображение информации об использовании темы</p><p> Класс: отображение информации о загрузке класса.</p><p> *Сводка по виртуальной машине:*Отображение информации о виртуальной машине Java</p><p> MBeans: отображение MBeans.</p><p>(25) Сейчас зависает процесс.Как с помощью инструментов узнать причину? </p><p>(26) Какова связь между синхронизацией потоков и блокировкой? Обязательно ли блокируется синхронизация? Должна ли блокировка быть синхронной? </p><p> 1. Синхронизация означает, что поток ожидает завершения выполнения предыдущего потока, прежде чем приступить к выполнению текущего потока. </p><p> 1. Синхронизация означает, что поток ожидает завершения выполнения предыдущего потока, прежде чем приступить к выполнению текущего потока. </p><p> 2. Асинхронность означает, что при выполнении одного потока его следующему потоку не нужно ждать завершения выполнения, прежде чем начать выполнение. </p><p> 2. Асинхронность означает, что при выполнении одного потока его следующему потоку не нужно ждать завершения выполнения, прежде чем начать выполнение. </p><p>(27) В чем разница между синхронным и асинхронным? </p><p>(28) Вы когда-нибудь использовали пул потоков? </p><p> Пул потоков — это форма многопоточной обработки, при которой задачи добавляются в очередь, а затем автоматически запускаются после создания потоков. Потоки пула потоков являются фоновыми потоками. Каждый поток использует размер стека по умолчанию, выполняется с приоритетом по умолчанию и находится в многопоточном подразделении. Если поток в управляемом коде простаивает (например, ожидает события), пул потоков вставит другой рабочий поток, чтобы все процессоры были заняты. Если все потоки пула потоков все время остаются занятыми, но очередь содержит ожидающие работы, пул потоков через некоторое время создаст еще один рабочий поток, но количество потоков никогда не превысит максимальное значение. Потоки, превышающие максимальное значение, могут быть поставлены в очередь, но они не запускаются до тех пор, пока не завершатся другие потоки. </p><p>(29) Как создать одноэлементный шаблон? Говоря о двойной проверке, он сказал, что она не является потокобезопасной. Как эффективно создать эффективный синглтон? </p><p> 1. Режим отложенной загрузки одноэлементного режима разработки должен быть синхронизирован, что снижает производительность системы. Чтобы решить эту проблему, можно внести следующие улучшения:</p><p> публичный класс StaticSingleton{</p><p> частный StaticSingleton(){</p><p> System.out.println("StaticSingleton создан");</p><p> </p><p> </p><p> </p><p> частный статический класс SingletonHolder{</p><p> частный статический экземпляр StaticSingleton = новый StaticSingleton();</p><p> public static StaticSingleton getInstance(){</p><p> верните SingletonHolder.instance;</p><p> </p><p> В этой реализации режим Singleton использует внутренние классы для поддержки экземпляров Singleton. Когда StaticSingleton загружается, его внутренний класс не будет инициализирован. Таким образом, можно гарантировать, что при загрузке класса StaticSingleton в JVM он будет не быть инициализирован. Инициализируйте класс Singleton, и при вызове метода getInstance() будет загружен StaticSingleton для инициализации экземпляра. В то же время, поскольку создание экземпляра завершается при загрузке класса, он по своей сути ориентирован на потоки, и метод getInstance() использовать не нужно. Ключевое слово Sync. Таким образом, эта реализация имеет преимущества как отложенной, так и неотложенной загрузки. </p><p> Примечание. Сериализация и десериализация могут уничтожить синглтоны. Вообще говоря, сериализация и десериализация синглтонов встречаются редко, но если они существуют, вам следует уделять больше внимания. </p><p>(30) Что вы использовали в пакете concurrent? </p><p> Исполнитель: исполнитель конкретной задачи Runnable. Пул потоков</p><p> ExecutorService: менеджер пула потоков, существует множество классов реализации, я представлю некоторые из них. Мы можем отправить Runnable и Callable в пул для планирования. </p><p>Семафор: счетный семафор</p><p> ReentrantLock: реентерабельная взаимоисключающая блокировка, аналогичная по функциям синхронизированной, но гораздо более мощная. </p><p> Будущее: это интерфейс для взаимодействия с Runnable и Callable, например, для получения возвращаемого результата после выполнения потока и т. д. Он также обеспечивает отмену для завершения потока. </p><p>BlockingQueue: очередь блокировки. </p><p> CompletionService: расширение ExecutorService, которое может получать результаты выполнения потока.</p><p>CountDownLatch: вспомогательный класс синхронизации, который позволяет одному или нескольким потокам ждать перед завершением набора операций, выполняемых в других потоках. </p><p> CyclicBarrier: вспомогательный класс синхронизации, который позволяет группе потоков ждать друг друга, пока не будет достигнута общая точка барьера </p><p> Будущее: Будущее представляет собой результат асинхронных вычислений. </p><p> ScheduledExecutorService: служба ExecutorService, которая планирует запуск команд после заданной задержки или через регулярные промежутки времени.</p><p>(31) Какие базы данных обычно используются? Вы когда-нибудь использовали Redis? </p><p>(32) Вы понимаете Hadoop? Каковы компоненты Hadoop? hdfs, улей, hbase, Zookeeper. Давайте поговорим о модели программирования mapreduce. </p><p> (33) Какие протоколы с открытым исходным кодом вы знаете? </p><p> (34) Какое программное обеспечение с открытым исходным кодом вы знаете? </p><p> (35) Какие книги вы читаете в последнее время? </p><p> (36) У вас есть вопросы ко мне? </p><p>(+1) В каких ситуациях вы использовали TreeMap? Как TreeMap реализован внутри? </p><p> TreeMap — это упорядоченный набор значений ключа, реализованный посредством красно-черных деревьев. </p><p> TreeMap наследует от AbstractMap, поэтому это Map, то есть набор значений ключа. </p><p> TreeMap реализует интерфейс NavigableMap, а это означает, что он поддерживает ряд методов навигации. Например, верните упорядоченную коллекцию ключей. </p><p> TreeMap реализует интерфейс Cloneable, что означает, что его можно клонировать. </p><p> TreeMap реализует интерфейс java.io.Serializable, что означает поддержку сериализации. </p><p> TreeMap реализован на основе красно-черного дерева. Карта сортируется в соответствии с естественным порядком ее ключей или в соответствии с компаратором, предоставленным при создании карты, в зависимости от используемого конструктора. </p><p> Временная сложность основных операций TreeMap containsKey, get, put и delete равна log(n). </p><p> Кроме того, TreeMap является асинхронным. Итератор, возвращаемый его методом итератора, является отказоустойчивым. </p><p>(37) Какие шаблоны проектирования вы знаете? Расскажите, какие шаблоны проектирования вы использовали</p><p> Шаблоны проектирования делятся на: 3 типа и 23 шаблона: Шаблоны проектирования в основном делятся на три типа: творческие, структурные и поведенческие. </p><p>(38) Как определить, есть ли в односвязном списке цикл? </p><p> Если есть два указателя на головной узел, один движется быстро, а другой движется медленно, то через несколько шагов быстрый указатель всегда будет превосходить медленный указатель на один круг. </p><
2360234
None
Read more...
Настройка и использование пула подключений к базе данных Druid, включение sql-мониторинга
<p> <strong>Предисловие</strong> </p><p>Проект блоггера построен с использованием maven и контейнеров Spring. Если у вас есть вопросы о том, что такое пул соединений с базой данных Druid, вы можете обратиться к этой моей записи в блоге: <a class="" href="/developer/tools/ blog-entry ?target=http%3A%2F%2Fwww.kailing.pub%2Farticle%2Findex%2Farcid%2F91.html" rel="nofollow noopener" style="color:#0052D9" target="_blank">Подключение к базе данных Обзор пула Друид </a> </p><p> <strong>Давайте пошагово рассмотрим, как использовать Druid в вашем проекте</strong> </p><p> <strong>1. Сначала настройте pom.xml и добавьте зависимость Druid</strong> </p><p><зависимость></p><p><groupId>com.<em style="font-style:italic">alibaba</em></groupId></p><p><artifactId>друид</artifactId></p><p><версия>1.0.18</версия></p><p></зависимость> </p><p> <strong>2. Конфигурация источника данных следующим образом</strong> </p><p> <strong>Информация о моем подключении:</strong> </p><p> jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/webside?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&autoReconnect=true jdbc.username=корень jdbc.password=саса #jdbc.password=onF4ELsLxPYSYcuq4e6dihnGZhInVdUcHsSjA9RFoT druid.initialSize=10 druid.minIdle=10 druid.maxActive=50 druid.maxWait=60000 druid.timeBetweenEvictionRunsMillis=60000 druid.minEvictableIdleTimeMillis=300000 druid.validationQuery=ВЫБРАТЬ 'x' druid.testWhileIdle=истина druid.testOnBorrow=false druid.testOnReturn=ложь druid.poolPreparedStatements=истина druid.maxPoolPreparedStatementPerConnectionSize=20 druid.maxOpenPreparedStatements=100 druid.timeBetweenLogStatsMillis=300000 druid.filters=config,wall,log4j #加上如下配置可以加解密 数据库连接密码 #druid.connectionProperties==true;.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKZN4rjl druid.useGlobalDataSourceStat=истина druid.removeAbandoned=истина druid.removeAbandonedTimeout=1800 druid.logAbandoned=false <strong>Компонент источника данных</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 基本属性 url、user、password --> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${druid.initialSize}" /> <property name="minIdle" value="${druid.minIdle}" /> <property name="maxActive" value="${druid.maxActive}" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="${druid.maxWait}" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${druid.validationQuery}" /> <property name="testWhileIdle" value="${druid.testWhileIdle}" /> <property name="testOnBorrow" value="${druid.testOnBorrow}" /> <property name="testOnReturn" value="${druid.testOnReturn}" /> <!-- 打开PSCache,并且指定每个连接上PSCache的大小 --> <property name="poolPreparedStatements" value="${druid.poolPreparedStatements}" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="${druid.maxPoolPreparedStatementPerConnectionSize}" /> <property name="maxOpenPreparedStatements" value="${druid.maxOpenPreparedStatements}" /> <!-- 打开removeAbandoned功能 --> <property name="removeAbandoned" value="${druid.removeAbandoned}" /> <!-- 1800秒,也就是30分钟,超过30分钟,连接会自动关闭 --> <property name="removeAbandonedTimeout" value="${druid.removeAbandonedTimeout}" /> <!-- 关闭abanded连接时输出错误日志 --> <property name="logAbandoned" value="${druid.logAbandoned}" /> <!-- 配置监控统计拦截的filters --> <property name="filters" value="${druid.filters}" /> <property name="proxyFilters"> <list> <ref bean="stat-filter" /> </list> </property> <!--使用此配置数据库连接密码将采用 密文模式<property name="connectionProperties" value="${druid.connectionProperties}" />--> <property name="useGlobalDataSourceStat" value="${druid.useGlobalDataSourceStat}" /> </bean></code></pre><p> <strong>3. Настройте web.xml для включения функции мониторинга sql</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"> DruidWebStatFilter com.alibaba.druid.support.http.WebStatFilter exclusions *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* principalCookieName webside.cookieid sessionStatMaxCount 1000 sessionStatEnable true profileEnable true DruidWebStatFilter /* DruidStatView com.alibaba.druid.support.http.StatViewServlet resetEnable true loginUsername druid loginPassword druid allow 127.0.0.1/24,127.0.0.1 deny 172.101.106.13 DruidStatView /druid/*</code></pre><p> <strong>Интерфейс мониторинга sql выглядит следующим образом:</strong> </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-a8bd84dc.png"/><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-79e0d09d.png"/><
2360233
None
Read more...
Использование кода подтверждения Google Kaptcha
<h2 id="291kh" name="Капча%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F"> Что такое капча? </h2><p> kaptcha — это очень практичный инструмент для генерации проверочного кода с открытым исходным кодом от Google, основанный на проекте с открытым исходным кодом SimpleCaptcha. Генерировать проверочные коды с помощью капчи легко, а параметры можно настроить. Просто добавьте пакет jar и настройте его для его использования. Посредством конфигурации вы можете определить размер, цвет проверочного кода, отображаемые символы и т. д. Поговорим о том, как с помощью капчи генерировать коды проверки и выносить коды проверки на серверную часть для проверки. </p><h2 id="choll" name="%E6%80%8E%E4%B9%88%E4%BD%BF%E7%94%A8Kaptcha%EF%BC%9F"> Как использовать капчу? </h2><p> <strong>1. Прежде всего, если проект использует капчу, он должен полагаться на jar капчи. Если это проект maven, добавьте следующие зависимости напрямую. Для проектов, отличных от maven, просто загрузите пакет jar самостоятельно </strong> </p><p><зависимость></p><p><groupId>com.github.axet</groupId></p><p><artifactId>капча</artifactId></p><p><версия>0.0.9</версия></p><p></зависимость></p><p> <strong>2. Настройте капчу</strong> </p><p> На примере проекта Spring настройте компонент Kaptcha по умолчанию следующим образом </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"> kaptcha.code no black com.google.code.kaptcha.impl.WaterRipple com.google.code.kaptcha.impl.NoNoise 90 33 25 4 5 247,247,247 247,247,247</code></pre><p> <strong>3. Сохраните сгенерированный код проверки в сеансе и выведите поток изображений, сгенерированный кодом проверки, на страницу</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"> @Autowired private Producer captchaProducer; @RequestMapping(value = "/kaptchaImage", method = RequestMethod.GET) public void kaptcha(HttpServletRequest req, HttpServletResponse rsp) { ServletOutputStream out = null; try { HttpSession session = req.getSession(); rsp.setDateHeader("Expires", 0); rsp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); rsp.addHeader("Cache-Control", "post-check=0, pre-check=0"); rsp.setHeader("Pragma", "no-cache"); rsp.setContentType("image/jpeg"); String capText = captchaProducer.createText(); session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText); BufferedImage image = captchaProducer.createImage(capText); out = rsp.getOutputStream(); ImageIO.write(image, "jpg", out); out.flush(); }catch(IOException e) { throw new SystemException(e); } finally { try { out.close(); } catch (IOException e) { throw new SystemException(e); } } }</code></pre><p> <strong>4. Убедитесь, что код подтверждения, введенный пользователем, соответствует коду, сохраненному в сеансе, для достижения цели проверки</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@RequestMapping(value = "/login", method = RequestMethod.POST, produces = "text/html; charset=utf-8") public String userLogin(String accountName, String password, String captcha, Boolean rememberMe, HttpServletRequest request) { //从session中取出kaptcha生成的验证码text值 String expected = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); //获取用户页面输入的验证码 if(!captcha.equalsIgnoreCase(expected)) { request.setAttribute("error", "验证码错误!"); return "/login"; }else { xxxx验证码后的后续逻辑 } }</code></pre><h2 id="1hg3e" name="%E6%9B%B4%E8%AF%A6%E7%BB%86%E7%9A%84Kaptcha%E9%AA%8C%E8%AF%81%E7%A0 %81%E9%85%8D%E7%BD%AE%EF%BC%9F"> Более подробная конфигурация кода проверки капчи? </h2><li> kaptcha.border Есть ли граница, по умолчанию — true, мы можем сами установить да, нет </li><li> Цвет границы kaptcha.border.color по умолчанию равен Color.BLACK </li><li> kaptcha.border.thickness толщина границы по умолчанию равна 1 </li><li> Генератор кода проверки kaptcha.producer.impl по умолчанию использует значение DefaultKaptcha </li><li> Генератор текста кода проверки kaptcha.textproducer.impl по умолчанию имеет значение DefaultTextCreator </li><li> kaptcha.textproducer.char.string Диапазон содержимого текстовых символов кода проверки. По умолчанию — abcde2345678gfynmnpwx </li><li> kaptcha.textproducer.char.length Длина символов текста кода проверки по умолчанию равна 5 </li><li> kaptcha.textproducer.font.names Стиль шрифта текста кода проверки по умолчанию — new Font("Arial", 1, FontSize), new Font("Courier", 1, FontSize) </li><li> kaptcha.textproducer.font.size Размер символов текста кода проверки по умолчанию равен 40 </li><li> kaptcha.textproducer.font.color Цвет текстового символа кода проверки. По умолчанию — Color.BLACK </li><li> kaptcha.textproducer.char.space Интервал между символами текста кода проверки по умолчанию равен 2 </li><li> kaptcha.noise.impl объект генерации шума кода проверки по умолчанию имеет значение DefaultNoise </li><li> kaptcha.noise.color Цвет шума кода проверки. По умолчанию — Color.BLACK </li><li> Для механизма стиля кода проверки kaptcha.obscurificator.impl по умолчанию используется WaterRipple </li><li> kaptcha.word.impl Отображение текста кода проверки. По умолчанию используется DefaultWordRenderer </li><li> Фоновый генератор кода проверки kaptcha.background.impl по умолчанию имеет значение DefaultBackground </li><li> kaptcha.background.clear.from Градиент цвета фона кода проверки. По умолчанию — Color.LIGHT_GRAY </li><li> kaptcha.background.clear.to Градиент цвета фона кода проверки. По умолчанию — Color.WHITE </li><li> kaptcha.image.width Ширина изображения кода проверки по умолчанию равна 200 </li><li> kaptcha.image.height Высота изображения кода проверки по умолчанию равна 50 </li><h2 id="5bnv6" name="%E6%95%88%E6%9E%9C%E5%9B%BE%E5%A6%82%E4%B8%8B"> Визуализация выглядит следующим образом </h2 ><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-2674f2a5.png"/><
2360232
None
Read more...
Не найден объект для исключения запроса jpa
<p> <strong>Что такое jpa? </strong> </p><p> Полное название JPA — Java Persistence API. JPA описывает отношения объектно-реляционного сопоставления таблиц посредством аннотаций JDK 5.0 или XML и сохраняет объекты сущностей во время выполнения в базе данных. </p><p>JPA — это один из стандартов Java EE, выпущенный организацией JCP. Поэтому любая платформа, которая утверждает, что соответствует стандарту JPA, имеет одну и ту же архитектуру и предоставляет один и тот же API доступа. Это гарантирует, что корпоративные приложения, разработанные на основе JPA, могут разрабатываться с небольшим количеством модификаций и работать в различных средах JPA</p><p>JPA требует, чтобы провайдер реализовывал свои функции. Hibernate — очень сильный провайдер JPA. Следует сказать, что никто не может его превзойти. Функционально JPA является подмножеством функций Hibernate. Hibernate совместим с JPA начиная с версии 3.2. Hibernate3.2 получил сертификат совместимости Sun TCK JPA (Java Persistence API). </p><p> <strong>Проблемы</strong> </p><p> Я использовал jpa для сохранения данных на работе. Во время отладки было выдано исключение типа "Нет объекта для запроса". Объект запроса не найден. Основной причиной этой проблемы было использование метода getSingleResult() для вернуть объект. Давайте посмотрим исходный код, чтобы выяснить причину</p><p> <strong>Ниже приведен исходный код реализации getSingleResult</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"> @SuppressWarnings({ "unchecked", "RedundantCast" }) public X getSingleResult() { try { final Listresult = query.list(); if ( result.size() == 0 ) { NoResultException nre = new NoResultException( "No entity found for query" ); getEntityManager().handlePersistenceException( nre ); throw nre; } else if ( result.size() > 1 ) { final SetuniqueResult = new HashSet(result); if ( uniqueResult.size() > 1 ) { NonUniqueResultException nure = new NonUniqueResultException( "result returns more than one elements" ); getEntityManager().handlePersistenceException( nure ); throw nure; } else { return uniqueResult.iterator().next(); } } else { return result.get( 0 ); } } catch (QueryExecutionRequestException he) { throw new IllegalStateException(he); } catch( TypeMismatchException e ) { throw new IllegalArgumentException(e); } catch (HibernateException he) { throw getEntityManager().convert( he ); } }</code></pre><p><strong>Анализируйте и решайте проблемы</strong></p><p> Из решения if в реализации исходного кода мы видим, что если вы используете getSingleResult() для возврата объекта, исключение будет выдано, если результат равен 0 или больше 1. Если вы не уверены, что объект, к которому вы запрашиваете, существует и существует только один, обычно рекомендуется использовать getResultList() для получения набора результатов для возвращаемого объекта, а затем выполнить соответствующую обработку, например: </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"> Listlist=entityManager().createQuery("SELECT o FROM User o where o.userId=?1", User.class) .setParameter(1, userId) .getResultList(); if(list!=null && list.size()!=0){ return list.get(0); } return null ;</code></pre><p> Сначала определите размер набора результатов, а затем определите, возвращать ли значение null или взять первое значение в зависимости от размера набора результатов.</p><
2360231
None
Read more...
Класс реализации коллекции, анализирующий ArrayList, LinkedList, Vector
<p> <strong>Предисловие</strong> </p><p> В повседневной разработке часто используются операции сбора данных, такие как List. Вот краткое изложение </p><p> <strong>Коллекция Java</strong> </p><p> Коллекции в Java делятся на две категории: List и Set. Ниже приводится информация о диаграмме классов </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-455deb98.png"/><p> <strong>Характеристики классов реализации списка ArrayList, LinkedList и Vector</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * 有序集合List接口的实现类LinkedLIst,ArrayList,Vector,Stack * (1)ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问, * 当数组大小不满足时会增加存储能力,将已有数组数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时, * 需要对数组进行拷贝,移动,代价比较高。因此,它适合随即查找和遍历,不适合频繁插入和删除财操作。 * (2)Vector与ArrayList一样,也是通过数组实现的。不同的是它支持线程的同步,即一时刻只有一个线程能够写Vector, * 避免多线程同时写引起的不一致性。但实现同步需要很高的花费, 因此,访问它比访问ArrayList慢。 * 2.1 Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%. * 2.2 Vector和ArrayList都是用数组实现的,所以,在添加和插入时,最好从表尾操作,而不要从中间或者表头开始,以避免数组移动引起的开销! * (3)LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随即访问和遍历速度比较慢。另外,由于它实现了接口Deque, * 它还提供了List没有定义的方法,专门用于操作表头和表尾元素。 * (4)可以为每个List生成ListIterator,支持双向遍历List,而且能够在ListIterator位置插入和删除元素。 * (5)Stack堆栈类继承Vector,它总是对列表的尾部数据进行操作,采用了先进后出的策略,自定义了push(),peek(),pop(),empty(),search()几个方法。 */</code></pre><p><strong>Характеристики классов реализации Set HashSet, LinkedHashSet и TreeSet</strong></p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * 无序集合Set的实现类HashSet,LinkedHashSet,TreeSet *(1)Set不允许存放相同的元素,判断的依据是根据存放元素的equals方法和hashCode来判断的,如有需要可以重写这两个方法 *(2) HashSet:基于HashMap实现,哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放 *(3)LinkedHashSet:基于LinkedHashMap实现,以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代。 LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet *(4)TreeSet:基于TreeMap实现,Set里唯一现实了SortedSet接口的实现类,默认按元素的实现接口Comparable的方法CompareTo(Object obj)升序, 如有需要,元素可实现Comparable */</code></pre><p><strong>Пример кода</strong></p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * @author kl by 2016/4/5 * @boke www.kailing.pub */ public class CollectionTest { public void initCollection(Collection collection){ collection.add(1); collection.add(2); collection.add(3); collection.add(4); collection.add(5); collection.add(6); } @Test public void linkListTest(){ LinkedList list = new LinkedList(); //初始化数据 initCollection(list); //迭代方式一 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i).toString()); } System.out.println("-------------------------迭代方式一华丽分割线----------------------------"); //迭代方式二 for (Object o : list) { System.out.println(o.toString()); //list.add(3);//这样写直接抛异常,有这种业务需要的直接用ListIterator迭代 } System.out.println("-------------------------迭代方式二华丽分割线----------------------------"); //迭代方式三 封装了Iterator ListIterator listIterator = list.listIterator(); while (listIterator.hasNext()) { /** * 在迭代的同时可以操作当前的listIterator,对集合做增删改的操作,其他的迭代方式在迭代的时候不能直接操作集合 * ListIterator没有直接更新的方法,通过删除和添加来达到更新的目的 */ Object value=listIterator.next().toString();// if (value.equals("3")){ listIterator.remove();//删除某个元素 listIterator.add(0);//添加某个元素 }else{ System.out.println(value); } } System.out.println("-------------------------迭代方式三华丽分割线----------------------------"); //迭代方式四 ps:java.util.Iterator Iterator iterable = list.iterator(); while (iterable.hasNext()) { System.out.println(iterable.next()); } System.out.println("-------------------------迭代方式四华丽分割线----------------------------"); System.out.println("是否存在 " + list.contains(9)); //使用indexOf函数现实 System.out.println("在集合的哪个位置 " + list.indexOf(3)); //不存在返回-1 System.out.println("在集合的哪个位置 " + list.lastIndexOf(3));//从集合的最后索引往前找 list.remove(0);//移除指定下标元素 Object str[] =list.toArray();//转换成数组,感觉一般不会有这个操作 List list1=list.subList(2,6);//分割一个集合 for (Object o : list1) { System.out.println("list1 "+o.toString()); //list.add(3);//这样写直接抛异常,有这种业务需要的直接用ListIterator迭代 } list.removeFirst(); list1= (List) list.clone();//复制一份list,和直接list1=list的不同之处在于对list操作不影响list1 /*以上操作迭代LinkedList,ArrayList,Vector都可用*/ /*以下操作方式是LinkedList特有的,是实现Deque中的方法*/ list.addFirst(10); list.addLast(10); System.out.println("链表头数据 "+list.getFirst().toString()); System.out.println("链表尾数据 "+list.getLast().toString()); list.removeFirst();//移除第一个元素 list.offer(11);//方法内部使用了add方法 list.removeLast();//移除最后一个元素 } @Test public void StackTest(){ Stack list=new Stack(); initCollection(list); System.out.println("pop :"+list.pop());// pop() 移除栈顶的值,并返回移除的Obj System.out.println("push :"+list.push(5));// push() 压栈,并返回Obj System.out.println("peek :"+list.peek());// 取栈顶的值 System.out.println("empty :"+list.empty());// 判空方法,是否为空栈 System.out.println("search :"+list.search(99));//查找元素的位置,不存在返回-1,可以用来判断是否存在某个值 Enumeration en= list.elements(); //Vector特有的迭代方式 while (en.hasMoreElements()){ if(list.empty()){ }else System.out.println(en.nextElement()); } } @Test public void arrayListTest(){ ArrayList list=new ArrayList(); initCollection(list); for(Object o:list){ System.out.println(o.toString()); } } @Test public void VectorTest(){ Vector v=new Vector(); Enumeration en= v.elements(); //Vector特有的迭代方式 while (en.hasMoreElements()){ System.out.println(en.nextElement()); } } @Test public void SetTest(){ HashSet hs = new HashSet(); initSet(hs); System.out.println("HashSet 顺序:"+hs); LinkedHashSet lhs = new LinkedHashSet(); initSet(lhs); System.out.println("LinkedHashSet 顺序:"+lhs); TreeSet ts = new TreeSet(); initSet(ts); System.out.println("TreeSet 顺序:"+ts); for(Object s:hs){ System.out.println("value:"+s); } } public void initSet(Set set){ set.add("G"); set.add("B"); set.add("A"); set.add("E"); set.add("D"); set.add("C"); set.add("F"); }</code></pre><
2360230
None
Read more...
Java использует Jsoup для точного сканирования информации о наборе персонала <Lagou.com>
<p> <strong>Предисловие</strong> </p><p> Недавно я познакомился с поисковыми роботами для изучения поисковых систем и захотел сделать что-нибудь интересное. В дополнение к предыдущим статьям о CSDN, сегодня я просматриваю информацию о вакансиях на Lagou.com </p><p> <strong>Понимание JSOUP</strong> </p><p> jsoup — это анализатор Java HTML, который может напрямую анализировать URL-адрес и текстовое содержимое HTML. Он предоставляет очень простой API для извлечения данных и управления ими с помощью DOM, CSS и методов манипуляции, подобных jQuery. </p><p> <strong>Основные функции jsoup следующие:</strong> 1. Анализ HTML из URL, файла или строки; 2. Используйте селекторы DOM или CSS для поиска и получения данных; 3. Рабочие HTML-элементы, атрибуты и текст; <strong>Инструкция по использованию, адрес китайского API:</strong><a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.open-open.com%2Fjsoup % 2F" rel="nofollow noopener" style="color:#0052D9" target="_blank"><strong>http://www.open-open.com/jsoup/</strong></a> Объект элементов jsoup поддерживает синтаксис селектора, аналогичный CSS (или jquery), для достижения очень мощных и гибких возможностей поиска. . Этот метод выбора можно использовать в объектах Document, Element или Elements. И он контекстно-зависим, поэтому может реализовать фильтрацию указанных элементов или доступ к выбору цепочки. Метод Select вернет коллекцию Elements и предоставит набор методов для извлечения и обработки результатов. Обзор селектора имя тега: поиск элементов по тегу, например: a ns|tag: поиск элементов в пространстве имен с помощью тегов. Например, вы можете использовать синтаксис fb|name для поиска элементов. #id: поиск элементов по идентификатору, например: #logo. .class: поиск элементов по имени класса, например: .masthead. [атрибут]: используйте атрибуты для поиска элементов, например: [href] [^attr]: используйте префикс имени атрибута для поиска элементов, например: вы можете использовать [^data-] для поиска элементов с атрибутом набора данных HTML5. [attr=value]: используйте значение атрибута для поиска элементов, например: [width=500] [attr^=значение], [attr$=значение], [attr*=значение]: находите элементы, сопоставляя начало, конец или содержащее значение атрибута, например: [href*=/path/] [attr~=regex]: используйте значения атрибутов для сопоставления регулярных выражений и поиска элементов, например: img[src~=(?i)\.(png|jpe?g)] *: Этот символ будет соответствовать всем элементам. Использование комбинации селектора селектора el#id: элемент+ID, например: div#logo el.class: элемент + класс, например: div.masthead el[attr]: элемент+класс, например: a[href] Любая комбинация, например: a[href].highlight дочерний элемент-предок: найдите дочерние элементы в определенном элементе, например: вы можете использовать .body p, чтобы найти все элементы p в элементе «body». родительский > дочерний: найдите прямые дочерние элементы под определенным родительским элементом. Например, вы можете использовать div.content > p, чтобы найти элемент p, или вы можете использовать body > *, чтобы найти все прямые дочерние элементы под тегом body. siblingA + siblingB: Найдите первый родственный элемент B перед элементом A, например: div.head + div. siblingA ~ siblingX: найдите одноуровневые элементы X перед элементом A, например: h1 ~ p el, el, el: комбинация нескольких селекторов для поиска уникальных элементов, соответствующих любому селектору, например: div.masthead, div.logo. Селекторы псевдоселекторов :lt(n): Найдите, какие элементы имеют значения индекса одного из братьев (его положение в дереве DOM относительно его родительского узла) меньше n, например: td:lt(3) означает элементы менее трех столбцов. :gt(n): Найдите, какие элементы имеют значения родственного индекса больше n, например: div p:gt(2) указывает, какие элементы div содержат более 2 элементов p. :eq(n): Найдите элементы, у которых значения индекса родственного элемента равны n, например: form input:eq(1) указывает на элемент формы, содержащий входной тег. :has(seletor): Найдите элементы, соответствующие селектору, содержащему элементы, например: div:has(p) указывает, какие элементы div содержат p элементов. :not(selector): найти элементы, которые не соответствуют селектору, например: div:not(.logo) означает список всех элементов div, которые не содержат элементы class=logo. :contains(text): поиск элементов, содержащих заданный текст. Поиск не чувствителен к регистру, например: p:contains(jsoup) :containsOwn(text): найти элементы, которые непосредственно содержат заданный текст. :matches(regex): Найдите текст каких элементов соответствует указанному регулярному выражению, например: div:matches((?i)login) :matchesOwn(regex): найти элементы, содержащие текст, соответствующий указанному регулярному выражению. Примечание. Приведенный выше индекс псевдоселектора начинается с 0, то есть значение индекса первого элемента равно 0, значение индекса второго элемента равно 1 и т. д. Вы можете просмотреть справочник по API Selector для получения более подробной информации. </p><p> <strong>Фокус внизу</strong> </p><p> jsoup может гибко извлекать любые данные в формате html </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@Component public class LaGouCrawler extends BreadthCrawler { @Autowired private ILaGouDao iLaGouDao; public LaGouCrawler(){ super("crawler", true); } @Override public void visit(Page page, CrawlDatums next) { if(page.matchUrl("http://www.lagou.com/jobs/xxxx.html")) { String title = page.select("title").first().text(); Elements position= page.select("dd[class=job_request]").first().getAllElements();//职位信息 String job=title.split("-")[0];//职位 String jobSalary=page.select("span[class=red]").first().text();//薪资 String jobAddress=position.get(3).text();//地区 String jobExperience=position.get(4).text();//经验要求 String jobEducation=position.get(5).text();//学历要求 String jobAttribute=position.get(6).text();//全职或兼职 String jobWelfare=position.get(7).text();//职位福利 String jobRelease=position.get(8).text();//发布时间 String jobPositionDetails=page.select("dd[class=job_bt]").text();//职位详情 String jobHandleRate=page.select("span[class=data]").first().text();//简历处理率 String jobHandleDate=page.select("span[class=data]").last().text();//处理用时 Elements companyOne=page.select("ul[class=c_feature]").first().getAllElements();//公司信息1 String companyName=title.split("-")[1];//公司名 String companyField=companyOne.get(1).text();//公司领域 String companyScale=companyOne.get(3).text();//公司规模 String companyHomepag=companyOne.get(7).text();//公司主页 Elements companyTwo=page.select("ul[class=c_feature]").last().getAllElements();//公司信息2 String companyPresentSituation=companyTwo.get(1).text();//目前阶段 Elements companyThree=page.select("dl[class=job_company]").first().getAllElements();//公司信息3 String companyDetailedAddress=companyThree.get(22).text();//公司详细地址 System.out.println("持久化--->"+job+"<---岗位"); LaGou laGou= new LaGou( job, jobSalary, jobAddress, jobExperience, jobEducation, jobAttribute, jobWelfare, jobRelease, jobPositionDetails, jobHandleRate, jobHandleDate, companyName, companyField, companyScale, companyHomepag, companyPresentSituation, companyDetailedAddress); iLaGouDao.save(laGou); } }</code></pre><p><strong>Используйте данные, чтобы увидеть результаты</strong></p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-ef533d44.png"/><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-1f4ef534.png"/><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-e6deab6f.png"/><
2360229
None
Read more...
Сканер Java сканирует сообщество Elastic Chinese и использует его в качестве тестовых данных
<p> <u><strong>Предисловие</strong></u> </p><p> <u>Чтобы проверить идеальную работу es, автор использовал сканер для сканирования большого количества данных из сообщества Elastic Chinese и CSDN в целях тестирования. Вот краткое введение в процесс tossing</. ты> </p><p> <strong>Познакомьтесь с WebCollector</strong> </p><p> WebCollector — это платформа (ядро) сканера JAVA, не требующая настройки и легко поддающаяся вторичной разработке. Он предоставляет оптимизированный API и требует лишь небольшого количества кода для реализации мощного сканера. WebCollector-Hadoop — это версия WebCollector для Hadoop, поддерживающая распределенное сканирование. </p><p> WebCollector стремится поддерживать стабильное и масштабируемое ядро сканера, чтобы облегчить разработчикам гибкую вторичную разработку. Ядро обладает высокой масштабируемостью, и пользователи могут разрабатывать на основе ядра нужные ему сканеры. Jsoup интегрирован в исходный код для обеспечения точного анализа веб-страниц. Selenium интегрирован в версию 2.x и может обрабатывать данные, сгенерированные JavaScript. </p><p> Пример: <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fcrawlscript.github.io%2FWebCollector%2F" rel="nofollow noopener" style= "color:#0052D9" target="_blank">http://crawlscript.github.io/WebCollector/</a> </p><p> <strong>Этапы использования</strong> </p><p> Импортируйте зависимости jar, автор — проект maven, добавьте все следующие зависимости pom.xml </p><р> cn.edu.hfut.dmic.webcollector ВебКоллектор 2.29 </p><p>ps: Здесь автор использует последнюю версию. Последняя версия склада maven — 2.09, поэтому, если вы используете последнюю версию, просто скачайте и упакуйте ее самостоятельно </p><p> После того, как среда установлена, непосредственно создайте новый класс, который наследует класс BreadthCrawler, и повторно посетите метод. Вся ваша логика обработки находится в методе посещения. Автор опубликует мой код ниже </p><p> <strong>Сканирование ресурсов Elastic китайского сообщества</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * Created by 小陈 on 2016/3/29. */ @Component public class ElasticCrawler extends BreadthCrawler { @Autowired IpaDao ipaDao; public ElasticCrawler() { super("crawl", true); /*start page*/ this.addSeed("xxxx“); /*fetch url like http://news.hfut.edu.cn/show-xxxxxxhtml*/ this.addRegex("xxx"); /*do not fetch jpg|png|gif*/ this.addRegex("-.*\\.(jpg|png|gif).*"); /*do not fetch url contains #*/ // this.addRegex("-.*#.*"); } @Override public void visit(Page page, CrawlDatums next) { String url = page.getUrl(); String content=""; try { content = ContentExtractor.getContentByUrl(url); }catch (Exception e){ e.printStackTrace(); } /*抽取标题*/ String title=page.getDoc().title(); System.out.println("-------------------->"+title); if(!title.isEmpty() && ! content.isEmpty()){ Pa pa=new Pa(title,content); ipaDao.save(pa);//持久化到数据库 } }</code></pre><p> Сканирование ресурсов CSDN </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * @author kl by 2016/3/29 * @boke www.kailing.pub */ @Component public class CSDNCrawler extends BreadthCrawler { @Autowired IpaDao ipaDao; public CSDNCrawler() { super("crawl", true); /*start page*/ this.addSeed("http://blog.csdn.net/.*");//添加种子地址 /*fetch url like http://news.hfut.edu.cn/show-xxxxxxhtml*/ this.addRegex("http://blog.csdn.net/.*/article/details/.*"); /*do not fetch jpg|png|gif*/ this.addRegex("-.*\\.(jpg|png|gif).*"); /*do not fetch url contains #*/ // this.addRegex("-.*#.*"); } @Override public void visit(Page page, CrawlDatums next) { String url = page.getUrl(); String content=""; try { content = ContentExtractor.getContentByUrl(url); }catch (Exception e){ e.printStackTrace(); } if (page.matchUrl("http://blog.csdn.net/.*/article/details/.*")) { String title = page.select("div[class=article_title]").first().text(); String author = page.select("div[id=blog_userface]").first().text();//获取作者名 System.out.println("title:" + title + "\tauthor:" + author); if(!title.isEmpty() && ! content.isEmpty()){ Pa pa=new Pa(title,content); ipaDao.save(pa); } } }</code></pre><p>ps: Правила сканирования в сообществе Elastic Chinese гармоничны. Автор любит это сообщество. Вы можете с уверенностью сканировать CSDN. WebCollector очень мощный инструмент. Одним из ключей к сканированию является знание правил URL-адресов веб-сайта. Если вам интересно, вы можете. После некоторых исследований я обнаружил, что в Elastic не так много данных, и достаточно нескольких минут. Я сканировал CSDN в течение 5 или 6 минут, не выполняя какого-либо углубленного сканирования. Мне потребовалось около 200 000, чтобы 300 000 фрагментов данных, взяли только заголовок и текст</p><p> Ниже приведен скриншот того, как я импортировал данные в ES после сканирования данных </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-0d979792.png"/><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-19e7353a.png"/><
2360228
None
Read more...
Список последних конфигураций Spring Boot
<pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"># =================================================================== # COMMON SPRING BOOT PROPERTIES # # This sample file is provided as a guideline. Do NOT copy it in its # entirety to your own application. ^^^ # =================================================================== # ---------------------------------------- # CORE PROPERTIES # ---------------------------------------- # BANNER banner.charset=UTF-8 # Banner file encoding. banner.location=classpath:banner.txt # Banner file location. banner.image.location=classpath:banner.gif # Banner image file location (jpg/png can also be used). banner.image.width= # Width of the banner image in chars (default 76) banner.image.height= # Height of the banner image in chars (default based on image height) banner.image.margin= # Left hand image margin in chars (default 2) banner.image.invert= # If images should be inverted for dark terminal themes (default false) # LOGGING logging.config= # Location of the logging configuration file. For instance `classpath:logback.xml` for Logback logging.exception-conversion-word=%wEx # Conversion word used when logging exceptions. logging.file= # Log file name. For instance `myapp.log` logging.level.*= # Log levels severity mapping. For instance `logging.level.org.springframework=DEBUG` logging.path= # Location of the log file. For instance `/var/log` logging.pattern.console= # Appender pattern for output to the console. Only supported with the default logback setup. logging.pattern.file= # Appender pattern for output to the file. Only supported with the default logback setup. logging.pattern.level= # Appender pattern for log level (default %5p). Only supported with the default logback setup. logging.register-shutdown-hook=false # Register a shutdown hook for the logging system when it is initialized. # AOP spring.aop.auto=true # Add @EnableAspectJAutoProxy. spring.aop.proxy-target-class=false # Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false). # IDENTITY ({sc-spring-boot}/context/ContextIdApplicationContextInitializer.{sc-ext}[ContextIdApplicationContextInitializer]) spring.application.index= # Application index. spring.application.name= # Application name. # ADMIN ({sc-spring-boot-autoconfigure}/admin/SpringApplicationAdminJmxAutoConfiguration.{sc-ext}[SpringApplicationAdminJmxAutoConfiguration]) spring.application.admin.enabled=false # Enable admin features for the application. spring.application.admin.jmx-name=org.springframework.boot:type=Admin,name=SpringApplication # JMX name of the application admin MBean. # AUTO-CONFIGURATION spring.autoconfigure.exclude= # Auto-configuration classes to exclude. # SPRING CORE spring.beaninfo.ignore=true # Skip search of BeanInfo classes. # SPRING CACHE ({sc-spring-boot-autoconfigure}/cache/CacheProperties.{sc-ext}[CacheProperties]) spring.cache.cache-names= # Comma-separated list of cache names to create if supported by the underlying cache manager. spring.cache.caffeine.spec= # The spec to use to create caches. Check CaffeineSpec for more details on the spec format. spring.cache.couchbase.expiration=0 # Entry expiration in milliseconds. By default the entries never expire. spring.cache.ehcache.config= # The location of the configuration file to use to initialize EhCache. spring.cache.guava.spec= # The spec to use to create caches. Check CacheBuilderSpec for more details on the spec format. spring.cache.hazelcast.config= # The location of the configuration file to use to initialize Hazelcast. spring.cache.infinispan.config= # The location of the configuration file to use to initialize Infinispan. spring.cache.jcache.config= # The location of the configuration file to use to initialize the cache manager. spring.cache.jcache.provider= # Fully qualified name of the CachingProvider implementation to use to retrieve the JSR-107 compliant cache manager. Only needed if more than one JSR-107 implementation is available on the classpath. spring.cache.type= # Cache type, auto-detected according to the environment by default. # SPRING CONFIG - using environment property only ({sc-spring-boot}/context/config/ConfigFileApplicationListener.{sc-ext}[ConfigFileApplicationListener]) spring.config.location= # Config file locations. spring.config.name=application # Config file name. # HAZELCAST ({sc-spring-boot-autoconfigure}/hazelcast/HazelcastProperties.{sc-ext}[HazelcastProperties]) spring.hazelcast.config= # The location of the configuration file to use to initialize Hazelcast. # PROJECT INFORMATION ({sc-spring-boot-autoconfigure}/info/ProjectInfoProperties.{sc-ext}[ProjectInfoProperties]) spring.info.build.location=classpath:META-INF/build-info.properties # Location of the generated build-info.properties file. spring.info.git.location=classpath:git.properties # Location of the generated git.properties file. # JMX spring.jmx.default-domain= # JMX domain name. spring.jmx.enabled=true # Expose management beans to the JMX domain. spring.jmx.server=mbeanServer # MBeanServer bean name. # Email ({sc-spring-boot-autoconfigure}/mail/MailProperties.{sc-ext}[MailProperties]) spring.mail.default-encoding=UTF-8 # Default MimeMessage encoding. spring.mail.host= # SMTP server host. For instance `smtp.example.com` spring.mail.jndi-name= # Session JNDI name. When set, takes precedence to others mail settings. spring.mail.password= # Login password of the SMTP server. spring.mail.port= # SMTP server port. spring.mail.properties.*= # Additional JavaMail session properties. spring.mail.protocol=smtp # Protocol used by the SMTP server. spring.mail.test-connection=false # Test that the mail server is available on startup. spring.mail.username= # Login user of the SMTP server. # APPLICATION SETTINGS ({sc-spring-boot}/SpringApplication.{sc-ext}[SpringApplication]) spring.main.banner-mode=console # Mode used to display the banner when the application runs. spring.main.sources= # Sources (class name, package name or XML resource location) to include in the ApplicationContext. spring.main.web-environment= # Run the application in a web environment (auto-detected by default). # FILE ENCODING ({sc-spring-boot}/context/FileEncodingApplicationListener.{sc-ext}[FileEncodingApplicationListener]) spring.mandatory-file-encoding= # Expected character encoding the application must use. # INTERNATIONALIZATION ({sc-spring-boot-autoconfigure}/MessageSourceAutoConfiguration.{sc-ext}[MessageSourceAutoConfiguration]) spring.messages.always-use-message-format=false # Set whether to always apply the MessageFormat rules, parsing even messages without arguments. spring.messages.basename=messages # Comma-separated list of basenames, each following the ResourceBundle convention. spring.messages.cache-seconds=-1 # Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles are cached forever. spring.messages.encoding=UTF-8 # Message bundles encoding. spring.messages.fallback-to-system-locale=true # Set whether to fall back to the system Locale if no files for a specific Locale have been found. # OUTPUT spring.output.ansi.enabled=detect # Configure the ANSI output (can be "detect", "always", "never"). # PID FILE ({sc-spring-boot-actuator}/system/ApplicationPidFileWriter.{sc-ext}[ApplicationPidFileWriter]) spring.pid.fail-on-write-error= # Fail if ApplicationPidFileWriter is used but it cannot write the PID file. spring.pid.file= # Location of the PID file to write (if ApplicationPidFileWriter is used). # PROFILES spring.profiles.active= # Comma-separated list of active profiles. spring.profiles.include= # Unconditionally activate the specified comma separated profiles. # SENDGRID ({sc-spring-boot-autoconfigure}/sendgrid/SendGridAutoConfiguration.{sc-ext}[SendGridAutoConfiguration]) spring.sendgrid.api-key= # SendGrid api key (alternative to username/password) spring.sendgrid.username= # SendGrid account username spring.sendgrid.password= # SendGrid account password spring.sendgrid.proxy.host= # SendGrid proxy host spring.sendgrid.proxy.port= # SendGrid proxy port # ---------------------------------------- # WEB PROPERTIES # ---------------------------------------- # EMBEDDED SERVER CONFIGURATION ({sc-spring-boot-autoconfigure}/web/ServerProperties.{sc-ext}[ServerProperties]) server.address= # Network address to which the server should bind to. server.compression.enabled=false # If response compression is enabled. server.compression.excluded-user-agents= # List of user-agents to exclude from compression. server.compression.mime-types= # Comma-separated list of MIME types that should be compressed. For instance `text/html,text/css,application/json` server.compression.min-response-size= # Minimum response size that is required for compression to be performed. For instance 2048 server.connection-timeout= # Time in milliseconds that connectors will wait for another HTTP request before closing the connection. When not set, the connector's container-specific default will be used. Use a value of -1 to indicate no (i.e. infinite) timeout. server.context-parameters.*= # Servlet context init parameters. For instance `server.context-parameters.a=alpha` server.context-path= # Context path of the application. server.display-name=application # Display name of the application. server.max-http-header-size=0 # Maximum size in bytes of the HTTP message header. server.max-http-post-size=0 # Maximum size in bytes of the HTTP post content. server.error.include-stacktrace=never # When to include a "stacktrace" attribute. server.error.path=/error # Path of the error controller. server.error.whitelabel.enabled=true # Enable the default error page displayed in browsers in case of a server error. server.jetty.acceptors= # Number of acceptor threads to use. server.jetty.selectors= # Number of selector threads to use. server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet # The class name of the JSP servlet. server.jsp-servlet.init-parameters.*= # Init parameters used to configure the JSP servlet server.jsp-servlet.registered=true # Whether or not the JSP servlet is registered server.port=8080 # Server HTTP port. server.server-header= # Value to use for the Server response header (no header is sent if empty) server.servlet-path=/ # Path of the main dispatcher servlet. server.use-forward-headers= # If X-Forwarded-* headers should be applied to the HttpRequest. server.session.cookie.comment= # Comment for the session cookie. server.session.cookie.domain= # Domain for the session cookie. server.session.cookie.http-only= # "HttpOnly" flag for the session cookie. server.session.cookie.max-age= # Maximum age of the session cookie in seconds. server.session.cookie.name= # Session cookie name. server.session.cookie.path= # Path of the session cookie. server.session.cookie.secure= # "Secure" flag for the session cookie. server.session.persistent=false # Persist session data between restarts. server.session.store-dir= # Directory used to store session data. server.session.timeout= # Session timeout in seconds. server.session.tracking-modes= # Session tracking modes (one or more of the following: "cookie", "url", "ssl"). server.ssl.ciphers= # Supported SSL ciphers. server.ssl.client-auth= # Whether client authentication is wanted ("want") or needed ("need"). Requires a trust store. server.ssl.enabled= # Enable SSL support. server.ssl.enabled-protocols= # Enabled SSL protocols. server.ssl.key-alias= # Alias that identifies the key in the key store. server.ssl.key-password= # Password used to access the key in the key store. server.ssl.key-store= # Path to the key store that holds the SSL certificate (typically a jks file). server.ssl.key-store-password= # Password used to access the key store. server.ssl.key-store-provider= # Provider for the key store. server.ssl.key-store-type= # Type of the key store. server.ssl.protocol=TLS # SSL protocol to use. server.ssl.trust-store= # Trust store that holds SSL certificates. server.ssl.trust-store-password= # Password used to access the trust store. server.ssl.trust-store-provider= # Provider for the trust store. server.ssl.trust-store-type= # Type of the trust store. server.tomcat.accesslog.directory=logs # Directory in which log files are created. Can be relative to the tomcat base dir or absolute. server.tomcat.accesslog.enabled=false # Enable access log. server.tomcat.accesslog.pattern=common # Format pattern for access logs. server.tomcat.accesslog.prefix=access_log # Log file name prefix. server.tomcat.accesslog.rename-on-rotate=false # Defer inclusion of the date stamp in the file name until rotate time. server.tomcat.accesslog.suffix=.log # Log file name suffix. server.tomcat.background-processor-delay=30 # Delay in seconds between the invocation of backgroundProcess methods. server.tomcat.basedir= # Tomcat base directory. If not specified a temporary directory will be used. server.tomcat.internal-proxies=10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\ 192\\.168\\.\\d{1,3}\\.\\d{1,3}|\\ 169\\.254\\.\\d{1,3}\\.\\d{1,3}|\\ 127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\ 172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\ 172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\ 172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3} # regular expression matching trusted IP addresses. server.tomcat.max-threads=0 # Maximum amount of worker threads. server.tomcat.min-spare-threads=0 # Minimum amount of worker threads. server.tomcat.port-header=X-Forwarded-Port # Name of the HTTP header used to override the original port value. server.tomcat.protocol-header= # Header that holds the incoming protocol, usually named "X-Forwarded-Proto". server.tomcat.protocol-header-https-value=https # Value of the protocol header that indicates that the incoming request uses SSL. server.tomcat.redirect-context-root= # Whether requests to the context root should be redirected by appending a / to the path. server.tomcat.remote-ip-header= # Name of the http header from which the remote ip is extracted. For instance `X-FORWARDED-FOR` server.tomcat.uri-encoding=UTF-8 # Character encoding to use to decode the URI. server.undertow.accesslog.dir= # Undertow access log directory. server.undertow.accesslog.enabled=false # Enable access log. server.undertow.accesslog.pattern=common # Format pattern for access logs. server.undertow.buffer-size= # Size of each buffer in bytes. server.undertow.buffers-per-region= # Number of buffer per region. server.undertow.direct-buffers= # Allocate buffers outside the Java heap. server.undertow.io-threads= # Number of I/O threads to create for the worker. server.undertow.worker-threads= # Number of worker threads. # FREEMARKER ({sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[FreeMarkerAutoConfiguration]) spring.freemarker.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.freemarker.allow-session-override=false # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.freemarker.cache=false # Enable template caching. spring.freemarker.charset=UTF-8 # Template encoding. spring.freemarker.check-template-location=true # Check that the templates location exists. spring.freemarker.content-type=text/html # Content-Type value. spring.freemarker.enabled=true # Enable MVC view resolution for this technology. spring.freemarker.expose-request-attributes=false # Set whether all request attributes should be added to the model prior to merging with the template. spring.freemarker.expose-session-attributes=false # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.freemarker.expose-spring-macro-helpers=true # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.freemarker.prefer-file-system-access=true # Prefer file system access for template loading. File system access enables hot detection of template changes. spring.freemarker.prefix= # Prefix that gets prepended to view names when building a URL. spring.freemarker.request-context-attribute= # Name of the RequestContext attribute for all views. spring.freemarker.settings.*= # Well-known FreeMarker keys which will be passed to FreeMarker's Configuration. spring.freemarker.suffix= # Suffix that gets appended to view names when building a URL. spring.freemarker.template-loader-path=classpath:/templates/ # Comma-separated list of template paths. spring.freemarker.view-names= # White list of view names that can be resolved. # GROOVY TEMPLATES ({sc-spring-boot-autoconfigure}/groovy/template/GroovyTemplateAutoConfiguration.{sc-ext}[GroovyTemplateAutoConfiguration]) spring.groovy.template.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.groovy.template.allow-session-override=false # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.groovy.template.cache= # Enable template caching. spring.groovy.template.charset=UTF-8 # Template encoding. spring.groovy.template.check-template-location=true # Check that the templates location exists. spring.groovy.template.configuration.*= # See GroovyMarkupConfigurer spring.groovy.template.content-type=test/html # Content-Type value. spring.groovy.template.enabled=true # Enable MVC view resolution for this technology. spring.groovy.template.expose-request-attributes=false # Set whether all request attributes should be added to the model prior to merging with the template. spring.groovy.template.expose-session-attributes=false # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.groovy.template.expose-spring-macro-helpers=true # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.groovy.template.prefix= # Prefix that gets prepended to view names when building a URL. spring.groovy.template.request-context-attribute= # Name of the RequestContext attribute for all views. spring.groovy.template.resource-loader-path=classpath:/templates/ # Template path. spring.groovy.template.suffix=.tpl # Suffix that gets appended to view names when building a URL. spring.groovy.template.view-names= # White list of view names that can be resolved. # SPRING HATEOAS ({sc-spring-boot-autoconfigure}/hateoas/HateoasProperties.{sc-ext}[HateoasProperties]) spring.hateoas.use-hal-as-default-json-media-type=true # Specify if application/hal+json responses should be sent to requests that accept application/json. # HTTP message conversion spring.http.converters.preferred-json-mapper=jackson # Preferred JSON mapper to use for HTTP message conversion. Set to "gson" to force the use of Gson when both it and Jackson are on the classpath. # HTTP encoding ({sc-spring-boot-autoconfigure}/web/HttpEncodingProperties.{sc-ext}[HttpEncodingProperties]) spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses. Added to the "Content-Type" header if not set explicitly. spring.http.encoding.enabled=true # Enable http encoding support. spring.http.encoding.force= # Force the encoding to the configured charset on HTTP requests and responses. spring.http.encoding.force-request= # Force the encoding to the configured charset on HTTP requests. Defaults to true when "force" has not been specified. spring.http.encoding.force-response= # Force the encoding to the configured charset on HTTP responses. # MULTIPART ({sc-spring-boot-autoconfigure}/web/MultipartProperties.{sc-ext}[MultipartProperties]) spring.http.multipart.enabled=true # Enable support of multi-part uploads. spring.http.multipart.file-size-threshold=0 # Threshold after which files will be written to disk. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. spring.http.multipart.location= # Intermediate location of uploaded files. spring.http.multipart.max-file-size=1Mb # Max file size. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. spring.http.multipart.max-request-size=10Mb # Max request size. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. # JACKSON ({sc-spring-boot-autoconfigure}/jackson/JacksonProperties.{sc-ext}[JacksonProperties]) spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance `yyyy-MM-dd HH:mm:ss`. spring.jackson.default-property-inclusion= # Controls the inclusion of properties during serialization. spring.jackson.deserialization.*= # Jackson on/off features that affect the way Java objects are deserialized. spring.jackson.generator.*= # Jackson on/off features for generators. spring.jackson.joda-date-time-format= # Joda date time format string. If not configured, "date-format" will be used as a fallback if it is configured with a format string. spring.jackson.locale= # Locale used for formatting. spring.jackson.mapper.*= # Jackson general purpose on/off features. spring.jackson.parser.*= # Jackson on/off features for parsers. spring.jackson.property-naming-strategy= # One of the constants on Jackson's PropertyNamingStrategy. Can also be a fully-qualified class name of a PropertyNamingStrategy subclass. spring.jackson.serialization.*= # Jackson on/off features that affect the way Java objects are serialized. spring.jackson.serialization-inclusion= # Controls the inclusion of properties during serialization. Configured with one of the values in Jackson's JsonInclude.Include enumeration. spring.jackson.time-zone= # Time zone used when formatting dates. For instance `America/Los_Angeles` # JERSEY ({sc-spring-boot-autoconfigure}/jersey/JerseyProperties.{sc-ext}[JerseyProperties]) spring.jersey.application-path= # Path that serves as the base URI for the application. Overrides the value of "@ApplicationPath" if specified. spring.jersey.filter.order=0 # Jersey filter chain order. spring.jersey.init.*= # Init parameters to pass to Jersey via the servlet or filter. spring.jersey.servlet.load-on-startup=-1 # Load on startup priority of the Jersey servlet. spring.jersey.type=servlet # Jersey integration type. Can be either "servlet" or "filter". # SPRING MOBILE DEVICE VIEWS ({sc-spring-boot-autoconfigure}/mobile/DeviceDelegatingViewResolverAutoConfiguration.{sc-ext}[DeviceDelegatingViewResolverAutoConfiguration]) spring.mobile.devicedelegatingviewresolver.enable-fallback=false # Enable support for fallback resolution. spring.mobile.devicedelegatingviewresolver.enabled=false # Enable device view resolver. spring.mobile.devicedelegatingviewresolver.mobile-prefix=mobile/ # Prefix that gets prepended to view names for mobile devices. spring.mobile.devicedelegatingviewresolver.mobile-suffix= # Suffix that gets appended to view names for mobile devices. spring.mobile.devicedelegatingviewresolver.normal-prefix= # Prefix that gets prepended to view names for normal devices. spring.mobile.devicedelegatingviewresolver.normal-suffix= # Suffix that gets appended to view names for normal devices. spring.mobile.devicedelegatingviewresolver.tablet-prefix=tablet/ # Prefix that gets prepended to view names for tablet devices. spring.mobile.devicedelegatingviewresolver.tablet-suffix= # Suffix that gets appended to view names for tablet devices. # SPRING MOBILE SITE PREFERENCE ({sc-spring-boot-autoconfigure}/mobile/SitePreferenceAutoConfiguration.{sc-ext}[SitePreferenceAutoConfiguration]) spring.mobile.sitepreference.enabled=true # Enable SitePreferenceHandler. # MUSTACHE TEMPLATES ({sc-spring-boot-autoconfigure}/mustache/MustacheAutoConfiguration.{sc-ext}[MustacheAutoConfiguration]) spring.mustache.allow-request-override= # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.mustache.allow-session-override= # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.mustache.cache= # Enable template caching. spring.mustache.charset= # Template encoding. spring.mustache.check-template-location= # Check that the templates location exists. spring.mustache.content-type= # Content-Type value. spring.mustache.enabled= # Enable MVC view resolution for this technology. spring.mustache.expose-request-attributes= # Set whether all request attributes should be added to the model prior to merging with the template. spring.mustache.expose-session-attributes= # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.mustache.expose-spring-macro-helpers= # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.mustache.prefix=classpath:/templates/ # Prefix to apply to template names. spring.mustache.request-context-attribute= # Name of the RequestContext attribute for all views. spring.mustache.suffix=.html # Suffix to apply to template names. spring.mustache.view-names= # White list of view names that can be resolved. # SPRING MVC ({sc-spring-boot-autoconfigure}/web/WebMvcProperties.{sc-ext}[WebMvcProperties]) spring.mvc.async.request-timeout= # Amount of time (in milliseconds) before asynchronous request handling times out. spring.mvc.date-format= # Date format to use. For instance `dd/MM/yyyy`. spring.mvc.dispatch-trace-request=false # Dispatch TRACE requests to the FrameworkServlet doService method. spring.mvc.dispatch-options-request=true # Dispatch OPTIONS requests to the FrameworkServlet doService method. spring.mvc.favicon.enabled=true # Enable resolution of favicon.ico. spring.mvc.ignore-default-model-on-redirect=true # If the content of the "default" model should be ignored during redirect scenarios. spring.mvc.locale= # Locale to use. By default, this locale is overridden by the "Accept-Language" header. spring.mvc.locale-resolver=accept-header # Define how the locale should be resolved. spring.mvc.log-resolved-exception=false # Enable warn logging of exceptions resolved by a "HandlerExceptionResolver". spring.mvc.media-types.*= # Maps file extensions to media types for content negotiation. spring.mvc.message-codes-resolver-format= # Formatting strategy for message codes. For instance `PREFIX_ERROR_CODE`. spring.mvc.servlet.load-on-startup=-1 # Load on startup priority of the Spring Web Services servlet. spring.mvc.static-path-pattern=/** # Path pattern used for static resources. spring.mvc.throw-exception-if-no-handler-found=false # If a "NoHandlerFoundException" should be thrown if no Handler was found to process a request. spring.mvc.view.prefix= # Spring MVC view prefix. spring.mvc.view.suffix= # Spring MVC view suffix. # SPRING RESOURCES HANDLING ({sc-spring-boot-autoconfigure}/web/ResourceProperties.{sc-ext}[ResourceProperties]) spring.resources.add-mappings=true # Enable default resource handling. spring.resources.cache-period= # Cache period for the resources served by the resource handler, in seconds. spring.resources.chain.cache=true # Enable caching in the Resource chain. spring.resources.chain.enabled= # Enable the Spring Resource Handling chain. Disabled by default unless at least one strategy has been enabled. spring.resources.chain.gzipped=false # Enable resolution of already gzipped resources. spring.resources.chain.html-application-cache=false # Enable HTML5 application cache manifest rewriting. spring.resources.chain.strategy.content.enabled=false # Enable the content Version Strategy. spring.resources.chain.strategy.content.paths=/** # Comma-separated list of patterns to apply to the Version Strategy. spring.resources.chain.strategy.fixed.enabled=false # Enable the fixed Version Strategy. spring.resources.chain.strategy.fixed.paths=/** # Comma-separated list of patterns to apply to the Version Strategy. spring.resources.chain.strategy.fixed.version= # Version string to use for the Version Strategy. spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ # Locations of static resources. # SPRING SESSION ({sc-spring-boot-autoconfigure}/session/SessionProperties.{sc-ext}[SessionProperties]) spring.session.hazelcast.map-name=spring:session:sessions # Name of the map used to store sessions. spring.session.jdbc.initializer.enabled=true # Create the required session tables on startup if necessary. spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema. spring.session.jdbc.table-name=SPRING_SESSION # Name of database table used to store sessions. spring.session.mongo.collection-name=sessions # Collection name used to store sessions. spring.session.redis.flush-mode= # Flush mode for the Redis sessions. spring.session.redis.namespace= # Namespace for keys used to store sessions. spring.session.store-type= # Session store type. # SPRING SOCIAL ({sc-spring-boot-autoconfigure}/social/SocialWebAutoConfiguration.{sc-ext}[SocialWebAutoConfiguration]) spring.social.auto-connection-views=false # Enable the connection status view for supported providers. # SPRING SOCIAL FACEBOOK ({sc-spring-boot-autoconfigure}/social/FacebookAutoConfiguration.{sc-ext}[FacebookAutoConfiguration]) spring.social.facebook.app-id= # your application's Facebook App ID spring.social.facebook.app-secret= # your application's Facebook App Secret # SPRING SOCIAL LINKEDIN ({sc-spring-boot-autoconfigure}/social/LinkedInAutoConfiguration.{sc-ext}[LinkedInAutoConfiguration]) spring.social.linkedin.app-id= # your application's LinkedIn App ID spring.social.linkedin.app-secret= # your application's LinkedIn App Secret # SPRING SOCIAL TWITTER ({sc-spring-boot-autoconfigure}/social/TwitterAutoConfiguration.{sc-ext}[TwitterAutoConfiguration]) spring.social.twitter.app-id= # your application's Twitter App ID spring.social.twitter.app-secret= # your application's Twitter App Secret # THYMELEAF ({sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[ThymeleafAutoConfiguration]) spring.thymeleaf.cache=true # Enable template caching. spring.thymeleaf.check-template-location=true # Check that the templates location exists. spring.thymeleaf.content-type=text/html # Content-Type value. spring.thymeleaf.enabled=true # Enable MVC Thymeleaf view resolution. spring.thymeleaf.encoding=UTF-8 # Template encoding. spring.thymeleaf.excluded-view-names= # Comma-separated list of view names that should be excluded from resolution. spring.thymeleaf.mode=HTML5 # Template mode to be applied to templates. See also StandardTemplateModeHandlers. spring.thymeleaf.prefix=classpath:/templates/ # Prefix that gets prepended to view names when building a URL. spring.thymeleaf.suffix=.html # Suffix that gets appended to view names when building a URL. spring.thymeleaf.template-resolver-order= # Order of the template resolver in the chain. spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved. # VELOCITY TEMPLATES ({sc-spring-boot-autoconfigure}/velocity/VelocityAutoConfiguration.{sc-ext}[VelocityAutoConfiguration]) spring.velocity.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.velocity.allow-session-override=false # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.velocity.cache= # Enable template caching. spring.velocity.charset=UTF-8 # Template encoding. spring.velocity.check-template-location=true # Check that the templates location exists. spring.velocity.content-type=text/html # Content-Type value. spring.velocity.date-tool-attribute= # Name of the DateTool helper object to expose in the Velocity context of the view. spring.velocity.enabled=true # Enable MVC view resolution for this technology. spring.velocity.expose-request-attributes=false # Set whether all request attributes should be added to the model prior to merging with the template. spring.velocity.expose-session-attributes=false # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.velocity.expose-spring-macro-helpers=true # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.velocity.number-tool-attribute= # Name of the NumberTool helper object to expose in the Velocity context of the view. spring.velocity.prefer-file-system-access=true # Prefer file system access for template loading. File system access enables hot detection of template changes. spring.velocity.prefix= # Prefix that gets prepended to view names when building a URL. spring.velocity.properties.*= # Additional velocity properties. spring.velocity.request-context-attribute= # Name of the RequestContext attribute for all views. spring.velocity.resource-loader-path=classpath:/templates/ # Template path. spring.velocity.suffix=.vm # Suffix that gets appended to view names when building a URL. spring.velocity.toolbox-config-location= # Velocity Toolbox config location. For instance `/WEB-INF/toolbox.xml` spring.velocity.view-names= # White list of view names that can be resolved. # SPRING WEB SERVICES ({sc-spring-boot-autoconfigure}/webservices/WebServicesProperties.{sc-ext}[WebServicesProperties]) spring.webservices.path=/services # Path that serves as the base URI for the services. spring.webservices.servlet.init= # Servlet init parameters to pass to Spring Web Services. spring.webservices.servlet.load-on-startup=-1 # Load on startup priority of the Spring Web Services servlet. # ---------------------------------------- # SECURITY PROPERTIES # ---------------------------------------- # SECURITY ({sc-spring-boot-autoconfigure}/security/SecurityProperties.{sc-ext}[SecurityProperties]) security.basic.authorize-mode=role # Security authorize mode to apply. security.basic.enabled=true # Enable basic authentication. security.basic.path=/** # Comma-separated list of paths to secure. security.basic.realm=Spring # HTTP basic realm name. security.enable-csrf=false # Enable Cross Site Request Forgery support. security.filter-order=0 # Security filter chain order. security.filter-dispatcher-types=ASYNC, FORWARD, INCLUDE, REQUEST # Security filter chain dispatcher types. security.headers.cache=true # Enable cache control HTTP headers. security.headers.content-type=true # Enable "X-Content-Type-Options" header. security.headers.frame=true # Enable "X-Frame-Options" header. security.headers.hsts= # HTTP Strict Transport Security (HSTS) mode (none, domain, all). security.headers.xss=true # Enable cross site scripting (XSS) protection. security.ignored= # Comma-separated list of paths to exclude from the default secured paths. security.require-ssl=false # Enable secure channel for all requests. security.sessions=stateless # Session creation policy (always, never, if_required, stateless). security.user.name=user # Default user name. security.user.password= # Password for the default user name. A random password is logged on startup by default. security.user.role=USER # Granted roles for the default user name. # SECURITY OAUTH2 CLIENT ({sc-spring-boot-autoconfigure}/security/oauth2/OAuth2ClientProperties.{sc-ext}[OAuth2ClientProperties] security.oauth2.client.client-id= # OAuth2 client id. security.oauth2.client.client-secret= # OAuth2 client secret. A random secret is generated by default # SECURITY OAUTH2 RESOURCES ({sc-spring-boot-autoconfigure}/security/oauth2/resource/ResourceServerProperties.{sc-ext}[ResourceServerProperties] security.oauth2.resource.id= # Identifier of the resource. security.oauth2.resource.jwt.key-uri= # The URI of the JWT token. Can be set if the value is not available and the key is public. security.oauth2.resource.jwt.key-value= # The verification key of the JWT token. Can either be a symmetric secret or PEM-encoded RSA public key. security.oauth2.resource.prefer-token-info=true # Use the token info, can be set to false to use the user info. security.oauth2.resource.service-id=resource # security.oauth2.resource.token-info-uri= # URI of the token decoding endpoint. security.oauth2.resource.token-type= # The token type to send when using the userInfoUri. security.oauth2.resource.user-info-uri= # URI of the user endpoint. # SECURITY OAUTH2 SSO ({sc-spring-boot-autoconfigure}/security/oauth2/client/OAuth2SsoProperties.{sc-ext}[OAuth2SsoProperties] security.oauth2.sso.filter-order= # Filter order to apply if not providing an explicit WebSecurityConfigurerAdapter security.oauth2.sso.login-path=/login # Path to the login page, i.e. the one that triggers the redirect to the OAuth2 Authorization Server # ---------------------------------------- # DATA PROPERTIES # ---------------------------------------- # FLYWAY ({sc-spring-boot-autoconfigure}/flyway/FlywayProperties.{sc-ext}[FlywayProperties]) flyway.baseline-description= # flyway.baseline-version=1 # version to start migration flyway.baseline-on-migrate= # flyway.check-location=false # Check that migration scripts location exists. flyway.clean-on-validation-error= # flyway.enabled=true # Enable flyway. flyway.encoding= # flyway.ignore-failed-future-migration= # flyway.init-sqls= # SQL statements to execute to initialize a connection immediately after obtaining it. flyway.locations=classpath:db/migration # locations of migrations scripts flyway.out-of-order= # flyway.password= # JDBC password if you want Flyway to create its own DataSource flyway.placeholder-prefix= # flyway.placeholder-replacement= # flyway.placeholder-suffix= # flyway.placeholders.*= # flyway.schemas= # schemas to update flyway.sql-migration-prefix=V # flyway.sql-migration-separator= # flyway.sql-migration-suffix=.sql # flyway.table= # flyway.url= # JDBC url of the database to migrate. If not set, the primary configured data source is used. flyway.user= # Login user of the database to migrate. flyway.validate-on-migrate= # # LIQUIBASE ({sc-spring-boot-autoconfigure}/liquibase/LiquibaseProperties.{sc-ext}[LiquibaseProperties]) liquibase.change-log=classpath:/db/changelog/db.changelog-master.yaml # Change log configuration path. liquibase.check-change-log-location=true # Check the change log location exists. liquibase.contexts= # Comma-separated list of runtime contexts to use. liquibase.default-schema= # Default database schema. liquibase.drop-first=false # Drop the database schema first. liquibase.enabled=true # Enable liquibase support. liquibase.labels= # Comma-separated list of runtime labels to use. liquibase.parameters.*= # Change log parameters. liquibase.password= # Login password of the database to migrate. liquibase.rollback-file= # File to which rollback SQL will be written when an update is performed. liquibase.url= # JDBC url of the database to migrate. If not set, the primary configured data source is used. liquibase.user= # Login user of the database to migrate. # COUCHBASE ({sc-spring-boot-autoconfigure}/couchbase/CouchbaseProperties.{sc-ext}[CouchbaseProperties]) spring.couchbase.bootstrap-hosts= # Couchbase nodes (host or IP address) to bootstrap from. spring.couchbase.bucket.name=default # Name of the bucket to connect to. spring.couchbase.bucket.password= # Password of the bucket. spring.couchbase.env.endpoints.key-value=1 # Number of sockets per node against the Key/value service. spring.couchbase.env.endpoints.query=1 # Number of sockets per node against the Query (N1QL) service. spring.couchbase.env.endpoints.view=1 # Number of sockets per node against the view service. spring.couchbase.env.ssl.enabled= # Enable SSL support. Enabled automatically if a "keyStore" is provided unless specified otherwise. spring.couchbase.env.ssl.key-store= # Path to the JVM key store that holds the certificates. spring.couchbase.env.ssl.key-store-password= # Password used to access the key store. spring.couchbase.env.timeouts.connect=5000 # Bucket connections timeout in milliseconds. spring.couchbase.env.timeouts.key-value=2500 # Blocking operations performed on a specific key timeout in milliseconds. spring.couchbase.env.timeouts.query=7500 # N1QL query operations timeout in milliseconds. spring.couchbase.env.timeouts.socket-connect=1000 # Socket connect connections timeout in milliseconds. spring.couchbase.env.timeouts.view=7500 # Regular and geospatial view operations timeout in milliseconds. # DAO ({sc-spring-boot-autoconfigure}/dao/PersistenceExceptionTranslationAutoConfiguration.{sc-ext}[PersistenceExceptionTranslationAutoConfiguration]) spring.dao.exceptiontranslation.enabled=true # Enable the PersistenceExceptionTranslationPostProcessor. # CASSANDRA ({sc-spring-boot-autoconfigure}/cassandra/CassandraProperties.{sc-ext}[CassandraProperties]) spring.data.cassandra.cluster-name= # Name of the Cassandra cluster. spring.data.cassandra.compression= # Compression supported by the Cassandra binary protocol. spring.data.cassandra.connect-timeout-millis= # Socket option: connection time out. spring.data.cassandra.consistency-level= # Queries consistency level. spring.data.cassandra.contact-points=localhost # Comma-separated list of cluster node addresses. spring.data.cassandra.fetch-size= # Queries default fetch size. spring.data.cassandra.keyspace-name= # Keyspace name to use. spring.data.cassandra.load-balancing-policy= # Class name of the load balancing policy. spring.data.cassandra.port= # Port of the Cassandra server. spring.data.cassandra.password= # Login password of the server. spring.data.cassandra.read-timeout-millis= # Socket option: read time out. spring.data.cassandra.reconnection-policy= # Reconnection policy class. spring.data.cassandra.retry-policy= # Class name of the retry policy. spring.data.cassandra.serial-consistency-level= # Queries serial consistency level. spring.data.cassandra.schema-action= # Schema action to take at startup. spring.data.cassandra.ssl=false # Enable SSL support. spring.data.cassandra.username= # Login user of the server. # DATA COUCHBASE ({sc-spring-boot-autoconfigure}/data/couchbase/CouchbaseDataProperties.{sc-ext}[CouchbaseDataProperties]) spring.data.couchbase.auto-index=false # Automatically create views and indexes. spring.data.couchbase.consistency=read-your-own-writes # Consistency to apply by default on generated queries. spring.data.couchbase.repositories.enabled=true # Enable Couchbase repositories. # ELASTICSEARCH ({sc-spring-boot-autoconfigure}/data/elasticsearch/ElasticsearchProperties.{sc-ext}[ElasticsearchProperties]) spring.data.elasticsearch.cluster-name=elasticsearch # Elasticsearch cluster name. spring.data.elasticsearch.cluster-nodes= # Comma-separated list of cluster node addresses. If not specified, starts a client node. spring.data.elasticsearch.properties.*= # Additional properties used to configure the client. spring.data.elasticsearch.repositories.enabled=true # Enable Elasticsearch repositories. # MONGODB ({sc-spring-boot-autoconfigure}/mongo/MongoProperties.{sc-ext}[MongoProperties]) spring.data.mongodb.authentication-database= # Authentication database name. spring.data.mongodb.database=test # Database name. spring.data.mongodb.field-naming-strategy= # Fully qualified name of the FieldNamingStrategy to use. spring.data.mongodb.grid-fs-database= # GridFS database name. spring.data.mongodb.host=localhost # Mongo server host. spring.data.mongodb.password= # Login password of the mongo server. spring.data.mongodb.port=27017 # Mongo server port. spring.data.mongodb.repositories.enabled=true # Enable Mongo repositories. spring.data.mongodb.uri=mongodb://localhost/test # Mongo database URI. When set, host and port are ignored. spring.data.mongodb.username= # Login user of the mongo server. # DATA REDIS spring.data.redis.repositories.enabled=true # Enable Redis repositories. # NEO4J ({sc-spring-boot-autoconfigure}/neo4j/Neo4jProperties.{sc-ext}[Neo4jProperties]) spring.data.neo4j.compiler= # Compiler to use. spring.data.neo4j.embedded.enabled=true # Enable embedded mode if the embedded driver is available. spring.data.neo4j.password= # Login password of the server. spring.data.neo4j.repositories.enabled=true # Enable Neo4j repositories. spring.data.neo4j.session.scope=singleton # Scope (lifetime) of the session. spring.data.neo4j.uri= # URI used by the driver. Auto-detected by default. spring.data.neo4j.username= # Login user of the server. # DATA REST ({sc-spring-boot-autoconfigure}/data/rest/RepositoryRestProperties.{sc-ext}[RepositoryRestProperties]) spring.data.rest.base-path= # Base path to be used by Spring Data REST to expose repository resources. spring.data.rest.default-page-size= # Default size of pages. spring.data.rest.enable-enum-translation= # Enable enum value translation via the Spring Data REST default resource bundle. spring.data.rest.limit-param-name= # Name of the URL query string parameter that indicates how many results to return at once. spring.data.rest.max-page-size= # Maximum size of pages. spring.data.rest.page-param-name= # Name of the URL query string parameter that indicates what page to return. spring.data.rest.return-body-on-create= # Return a response body after creating an entity. spring.data.rest.return-body-on-update= # Return a response body after updating an entity. spring.data.rest.sort-param-name= # Name of the URL query string parameter that indicates what direction to sort results. # SOLR ({sc-spring-boot-autoconfigure}/solr/SolrProperties.{sc-ext}[SolrProperties]) spring.data.solr.host=http://127.0.0.1:8983/solr # Solr host. Ignored if "zk-host" is set. spring.data.solr.repositories.enabled=true # Enable Solr repositories. spring.data.solr.zk-host= # ZooKeeper host address in the form HOST:PORT. # DATASOURCE ({sc-spring-boot-autoconfigure}/jdbc/DataSourceAutoConfiguration.{sc-ext}[DataSourceAutoConfiguration] & {sc-spring-boot-autoconfigure}/jdbc/DataSourceProperties.{sc-ext}[DataSourceProperties]) spring.datasource.continue-on-error=false # Do not stop if an error occurs while initializing the database. spring.datasource.data= # Data (DML) script resource reference. spring.datasource.data-username= # User of the database to execute DML scripts (if different). spring.datasource.data-password= # Password of the database to execute DML scripts (if different). spring.datasource.dbcp.*= # Commons DBCP specific settings spring.datasource.dbcp2.*= # Commons DBCP2 specific settings spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. spring.datasource.hikari.*= # Hikari specific settings spring.datasource.initialize=true # Populate the database using 'data.sql'. spring.datasource.jmx-enabled=false # Enable JMX support (if provided by the underlying pool). spring.datasource.jndi-name= # JNDI location of the datasource. Class, url, username & password are ignored when set. spring.datasource.name=testdb # Name of the datasource. spring.datasource.password= # Login password of the database. spring.datasource.platform=all # Platform to use in the schema resource (schema-${platform}.sql). spring.datasource.schema= # Schema (DDL) script resource reference. spring.datasource.schema-username= # User of the database to execute DDL scripts (if different). spring.datasource.schema-password= # Password of the database to execute DDL scripts (if different). spring.datasource.separator=; # Statement separator in SQL initialization scripts. spring.datasource.sql-script-encoding= # SQL scripts encoding. spring.datasource.tomcat.*= # Tomcat datasource specific settings spring.datasource.type= # Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath. spring.datasource.url= # JDBC url of the database. spring.datasource.username= # JEST (Elasticsearch HTTP client) ({sc-spring-boot-autoconfigure}/jest/JestProperties.{sc-ext}[JestProperties]) spring.elasticsearch.jest.connection-timeout=3000 # Connection timeout in milliseconds. spring.elasticsearch.jest.password= # Login password. spring.elasticsearch.jest.proxy.host= # Proxy host the HTTP client should use. spring.elasticsearch.jest.proxy.port= # Proxy port the HTTP client should use. spring.elasticsearch.jest.read-timeout=3000 # Read timeout in milliseconds. spring.elasticsearch.jest.uris=http://localhost:9200 # Comma-separated list of the Elasticsearch instances to use. spring.elasticsearch.jest.username= # Login user. # H2 Web Console ({sc-spring-boot-autoconfigure}/h2/H2ConsoleProperties.{sc-ext}[H2ConsoleProperties]) spring.h2.console.enabled=false # Enable the console. spring.h2.console.path=/h2-console # Path at which the console will be available. spring.h2.console.settings.trace=false # Enable trace output. spring.h2.console.settings.web-allow-others=false # Enable remote access. # JOOQ ({sc-spring-boot-autoconfigure}/jooq/JooqAutoConfiguration.{sc-ext}[JooqAutoConfiguration]) spring.jooq.sql-dialect= # SQLDialect JOOQ used when communicating with the configured datasource. For instance `POSTGRES` # JPA ({sc-spring-boot-autoconfigure}/orm/jpa/JpaBaseConfiguration.{sc-ext}[JpaBaseConfiguration], {sc-spring-boot-autoconfigure}/orm/jpa/HibernateJpaAutoConfiguration.{sc-ext}[HibernateJpaAutoConfiguration]) spring.data.jpa.repositories.enabled=true # Enable JPA repositories. spring.jpa.database= # Target database to operate on, auto-detected by default. Can be alternatively set using the "databasePlatform" property. spring.jpa.database-platform= # Name of the target database to operate on, auto-detected by default. Can be alternatively set using the "Database" enum. spring.jpa.generate-ddl=false # Initialize the schema on startup. spring.jpa.hibernate.ddl-auto= # DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. Default to "create-drop" when using an embedded database, "none" otherwise. spring.jpa.hibernate.naming.implicit-strategy= # Hibernate 5 implicit naming strategy fully qualified name. spring.jpa.hibernate.naming.physical-strategy= # Hibernate 5 physical naming strategy fully qualified name. spring.jpa.hibernate.naming.strategy= # Hibernate 4 naming strategy fully qualified name. Not supported with Hibernate 5. spring.jpa.hibernate.use-new-id-generator-mappings= # Use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE. spring.jpa.open-in-view=true # Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request. spring.jpa.properties.*= # Additional native properties to set on the JPA provider. spring.jpa.show-sql=false # Enable logging of SQL statements. # JTA ({sc-spring-boot-autoconfigure}/transaction/jta/JtaAutoConfiguration.{sc-ext}[JtaAutoConfiguration]) spring.jta.enabled=true # Enable JTA support. spring.jta.log-dir= # Transaction logs directory. spring.jta.transaction-manager-id= # Transaction manager unique identifier. # ATOMIKOS ({sc-spring-boot}/jta/atomikos/AtomikosProperties.{sc-ext}[AtomikosProperties]) spring.jta.atomikos.connectionfactory.borrow-connection-timeout=30 # Timeout, in seconds, for borrowing connections from the pool. spring.jta.atomikos.connectionfactory.ignore-session-transacted-flag=true # Whether or not to ignore the transacted flag when creating session. spring.jta.atomikos.connectionfactory.local-transaction-mode=false # Whether or not local transactions are desired. spring.jta.atomikos.connectionfactory.maintenance-interval=60 # The time, in seconds, between runs of the pool's maintenance thread. spring.jta.atomikos.connectionfactory.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.atomikos.connectionfactory.max-lifetime=0 # The time, in seconds, that a connection can be pooled for before being destroyed. 0 denotes no limit. spring.jta.atomikos.connectionfactory.max-pool-size=1 # The maximum size of the pool. spring.jta.atomikos.connectionfactory.min-pool-size=1 # The minimum size of the pool. spring.jta.atomikos.connectionfactory.reap-timeout=0 # The reap timeout, in seconds, for borrowed connections. 0 denotes no limit. spring.jta.atomikos.connectionfactory.unique-resource-name=jmsConnectionFactory # The unique name used to identify the resource during recovery. spring.jta.atomikos.datasource.borrow-connection-timeout=30 # Timeout, in seconds, for borrowing connections from the pool. spring.jta.atomikos.datasource.default-isolation-level= # Default isolation level of connections provided by the pool. spring.jta.atomikos.datasource.login-timeout= # Timeout, in seconds, for establishing a database connection. spring.jta.atomikos.datasource.maintenance-interval=60 # The time, in seconds, between runs of the pool's maintenance thread. spring.jta.atomikos.datasource.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.atomikos.datasource.max-lifetime=0 # The time, in seconds, that a connection can be pooled for before being destroyed. 0 denotes no limit. spring.jta.atomikos.datasource.max-pool-size=1 # The maximum size of the pool. spring.jta.atomikos.datasource.min-pool-size=1 # The minimum size of the pool. spring.jta.atomikos.datasource.reap-timeout=0 # The reap timeout, in seconds, for borrowed connections. 0 denotes no limit. spring.jta.atomikos.datasource.test-query= # SQL query or statement used to validate a connection before returning it. spring.jta.atomikos.datasource.unique-resource-name=dataSource # The unique name used to identify the resource during recovery. spring.jta.atomikos.properties.checkpoint-interval=500 # Interval between checkpoints. spring.jta.atomikos.properties.console-file-count=1 # Number of debug logs files that can be created. spring.jta.atomikos.properties.console-file-limit=-1 # How many bytes can be stored at most in debug logs files. spring.jta.atomikos.properties.console-file-name=tm.out # Debug logs file name. spring.jta.atomikos.properties.console-log-level= # Console log level. spring.jta.atomikos.properties.default-jta-timeout=10000 # Default timeout for JTA transactions. spring.jta.atomikos.properties.enable-logging=true # Enable disk logging. spring.jta.atomikos.properties.force-shutdown-on-vm-exit=false # Specify if a VM shutdown should trigger forced shutdown of the transaction core. spring.jta.atomikos.properties.log-base-dir= # Directory in which the log files should be stored. spring.jta.atomikos.properties.log-base-name=tmlog # Transactions log file base name. spring.jta.atomikos.properties.max-actives=50 # Maximum number of active transactions. spring.jta.atomikos.properties.max-timeout=300000 # Maximum timeout (in milliseconds) that can be allowed for transactions. spring.jta.atomikos.properties.output-dir= # Directory in which to store the debug log files. spring.jta.atomikos.properties.serial-jta-transactions=true # Specify if sub-transactions should be joined when possible. spring.jta.atomikos.properties.service= # Transaction manager implementation that should be started. spring.jta.atomikos.properties.threaded-two-phase-commit=true # Use different (and concurrent) threads for two-phase commit on the participating resources. spring.jta.atomikos.properties.transaction-manager-unique-name= # Transaction manager's unique name. # BITRONIX spring.jta.bitronix.connectionfactory.acquire-increment=1 # Number of connections to create when growing the pool. spring.jta.bitronix.connectionfactory.acquisition-interval=1 # Time, in seconds, to wait before trying to acquire a connection again after an invalid connection was acquired. spring.jta.bitronix.connectionfactory.acquisition-timeout=30 # Timeout, in seconds, for acquiring connections from the pool. spring.jta.bitronix.connectionfactory.allow-local-transactions=true # Whether or not the transaction manager should allow mixing XA and non-XA transactions. spring.jta.bitronix.connectionfactory.apply-transaction-timeout=false # Whether or not the transaction timeout should be set on the XAResource when it is enlisted. spring.jta.bitronix.connectionfactory.automatic-enlisting-enabled=true # Whether or not resources should be enlisted and delisted automatically. spring.jta.bitronix.connectionfactory.cache-producers-consumers=true # Whether or not produces and consumers should be cached. spring.jta.bitronix.connectionfactory.defer-connection-release=true # Whether or not the provider can run many transactions on the same connection and supports transaction interleaving. spring.jta.bitronix.connectionfactory.ignore-recovery-failures=false # Whether or not recovery failures should be ignored. spring.jta.bitronix.connectionfactory.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.bitronix.connectionfactory.max-pool-size=10 # The maximum size of the pool. 0 denotes no limit. spring.jta.bitronix.connectionfactory.min-pool-size=0 # The minimum size of the pool. spring.jta.bitronix.connectionfactory.password= # The password to use to connect to the JMS provider. spring.jta.bitronix.connectionfactory.share-transaction-connections=false # Whether or not connections in the ACCESSIBLE state can be shared within the context of a transaction. spring.jta.bitronix.connectionfactory.test-connections=true # Whether or not connections should be tested when acquired from the pool. spring.jta.bitronix.connectionfactory.two-pc-ordering-position=1 # The position that this resource should take during two-phase commit (always first is Integer.MIN_VALUE, always last is Integer.MAX_VALUE). spring.jta.bitronix.connectionfactory.unique-name=jmsConnectionFactory # The unique name used to identify the resource during recovery. spring.jta.bitronix.connectionfactory.use-tm-join=true Whether or not TMJOIN should be used when starting XAResources. spring.jta.bitronix.connectionfactory.user= # The user to use to connect to the JMS provider. spring.jta.bitronix.datasource.acquire-increment=1 # Number of connections to create when growing the pool. spring.jta.bitronix.datasource.acquisition-interval=1 # Time, in seconds, to wait before trying to acquire a connection again after an invalid connection was acquired. spring.jta.bitronix.datasource.acquisition-timeout=30 # Timeout, in seconds, for acquiring connections from the pool. spring.jta.bitronix.datasource.allow-local-transactions=true # Whether or not the transaction manager should allow mixing XA and non-XA transactions. spring.jta.bitronix.datasource.apply-transaction-timeout=false # Whether or not the transaction timeout should be set on the XAResource when it is enlisted. spring.jta.bitronix.datasource.automatic-enlisting-enabled=true # Whether or not resources should be enlisted and delisted automatically. spring.jta.bitronix.datasource.cursor-holdability= # The default cursor holdability for connections. spring.jta.bitronix.datasource.defer-connection-release=true # Whether or not the database can run many transactions on the same connection and supports transaction interleaving. spring.jta.bitronix.datasource.enable-jdbc4-connection-test= # Whether or not Connection.isValid() is called when acquiring a connection from the pool. spring.jta.bitronix.datasource.ignore-recovery-failures=false # Whether or not recovery failures should be ignored. spring.jta.bitronix.datasource.isolation-level= # The default isolation level for connections. spring.jta.bitronix.datasource.local-auto-commit= # The default auto-commit mode for local transactions. spring.jta.bitronix.datasource.login-timeout= # Timeout, in seconds, for establishing a database connection. spring.jta.bitronix.datasource.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.bitronix.datasource.max-pool-size=10 # The maximum size of the pool. 0 denotes no limit. spring.jta.bitronix.datasource.min-pool-size=0 # The minimum size of the pool. spring.jta.bitronix.datasource.prepared-statement-cache-size=0 # The target size of the prepared statement cache. 0 disables the cache. spring.jta.bitronix.datasource.share-transaction-connections=false # Whether or not connections in the ACCESSIBLE state can be shared within the context of a transaction. spring.jta.bitronix.datasource.test-query= # SQL query or statement used to validate a connection before returning it. spring.jta.bitronix.datasource.two-pc-ordering-position=1 # The position that this resource should take during two-phase commit (always first is Integer.MIN_VALUE, always last is Integer.MAX_VALUE). spring.jta.bitronix.datasource.unique-name=dataSource # The unique name used to identify the resource during recovery. spring.jta.bitronix.datasource.use-tm-join=true Whether or not TMJOIN should be used when starting XAResources. spring.jta.bitronix.properties.allow-multiple-lrc=false # Allow multiple LRC resources to be enlisted into the same transaction. spring.jta.bitronix.properties.asynchronous2-pc=false # Enable asynchronously execution of two phase commit. spring.jta.bitronix.properties.background-recovery-interval-seconds=60 # Interval in seconds at which to run the recovery process in the background. spring.jta.bitronix.properties.current-node-only-recovery=true # Recover only the current node. spring.jta.bitronix.properties.debug-zero-resource-transaction=false # Log the creation and commit call stacks of transactions executed without a single enlisted resource. spring.jta.bitronix.properties.default-transaction-timeout=60 # Default transaction timeout in seconds. spring.jta.bitronix.properties.disable-jmx=false # Enable JMX support. spring.jta.bitronix.properties.exception-analyzer= # Set the fully qualified name of the exception analyzer implementation to use. spring.jta.bitronix.properties.filter-log-status=false # Enable filtering of logs so that only mandatory logs are written. spring.jta.bitronix.properties.force-batching-enabled=true # Set if disk forces are batched. spring.jta.bitronix.properties.forced-write-enabled=true # Set if logs are forced to disk. spring.jta.bitronix.properties.graceful-shutdown-interval=60 # Maximum amount of seconds the TM will wait for transactions to get done before aborting them at shutdown time. spring.jta.bitronix.properties.jndi-transaction-synchronization-registry-name= # JNDI name of the TransactionSynchronizationRegistry. spring.jta.bitronix.properties.jndi-user-transaction-name= # JNDI name of the UserTransaction. spring.jta.bitronix.properties.journal=disk # Name of the journal. Can be 'disk', 'null' or a class name. spring.jta.bitronix.properties.log-part1-filename=btm1.tlog # Name of the first fragment of the journal. spring.jta.bitronix.properties.log-part2-filename=btm2.tlog # Name of the second fragment of the journal. spring.jta.bitronix.properties.max-log-size-in-mb=2 # Maximum size in megabytes of the journal fragments. spring.jta.bitronix.properties.resource-configuration-filename= # ResourceLoader configuration file name. spring.jta.bitronix.properties.server-id= # ASCII ID that must uniquely identify this TM instance. Default to the machine's IP address. spring.jta.bitronix.properties.skip-corrupted-logs=false # Skip corrupted transactions log entries. spring.jta.bitronix.properties.warn-about-zero-resource-transaction=true # Log a warning for transactions executed without a single enlisted resource. # NARAYANA ({sc-spring-boot}/jta/narayana/NarayanaProperties.{sc-ext}[NarayanaProperties]) spring.jta.narayana.default-timeout=60 # Transaction timeout in seconds. spring.jta.narayana.expiry-scanners=com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner # Comma-separated list of expiry scanners. spring.jta.narayana.log-dir= # Transaction object store directory. spring.jta.narayana.one-phase-commit=true # Enable one phase commit optimisation. spring.jta.narayana.periodic-recovery-period=120 # Interval in which periodic recovery scans are performed in seconds. spring.jta.narayana.recovery-backoff-period=10 # Back off period between first and second phases of the recovery scan in seconds. spring.jta.narayana.recovery-db-pass= # Database password to be used by recovery manager. spring.jta.narayana.recovery-db-user= # Database username to be used by recovery manager. spring.jta.narayana.recov</code></pre><
2360227
None
Read more...
Java использует jest-соединение для управления индексом в Elasticsearch2.2.0
<p> <strong>Предисловие</strong> </p><p> Узнайте о<a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fsearchbox-io%2FJest%2Ftree%2Fmaster%2Fjest" rel=" nofollow noopener" style="color:#0052D9" target="_blank">jest</a>, автор пытался использовать официальный API Elasticsearch Java для подключения к службе es, но по какой-то причине следующее сообщение об исключении было сообщено.После длительного поиска в Google все они сказали, что проблема была вызвана несовместимыми версиями JVM, но я тестировал ее локально, и JVM должна быть согласованной.Эта проблема еще не решена, но как может ли это помешать мне изучить es, так что позвольте мне открыть для себя j<a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fsearchbox-io%2FJest% 2Ftree%2Fmaster%2Fjest" rel="nofollow noopener" style="color:#0052D9" target="_blank">этот фреймворк</a> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">org.elasticsearch.transport.RemoteTransportException: Failed to deserialize exception response from stream Caused by: org.elasticsearch.transport.TransportSerializationException: Failed to deserialize exception response from stream</code></pre><p> Мой тестовый код относится к официальному экземпляру API. Официальный адрес API: <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fwww.elastic.co% 2Fguide%2Fen%2Felasticsearch%2Fclient%2Fjava-api%2Fcurrent%2Findex.html" rel="nofollow noopener" style="color:#0052D9" target="_blank">Elasticsearch Java API</a>, код такой: следует: </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">Client client = new TransportClient().addTransportAddress(new InetSocketTransportAddress("127.0.0.1", 9300)); QueryBuilder queryBuilder = QueryBuilders.termQuery("content", "搜"); SearchResponse searchResponse = client.prepareSearch("indexdata").setTypes("fulltext") .setQuery(queryBuilder) .execute() .actionGet(); SearchHits hits = searchResponse.getHits(); System.out.println("查询到记录数:" + hits.getTotalHits()); SearchHit[] searchHists = hits.getHits(); for(SearchHit sh : searchHists){ System.out.println("content:"+sh.getSource().get("content")); } client.close();</code></pre><p>Если кто-нибудь знает, что происходит, расскажите, пожалуйста, автору, чтобы он понял. Буду очень благодарен. Моя es-версия 2.2.0 </p><p> <strong>Перейдем к делу</strong> </p><p> Узнайте о шутке </p><p> Jest — это набор инструментов API на основе HTTP Rest для подключения к службам ES. Он мощный и может использовать операторы запросов ES Java API. Проект с открытым исходным кодом, адрес GitHub: <a class="" href=" /developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fsearchbox-io%2FJest" rel="nofollow noopener" style="color:#0052D9" target="_blank">https:/ /github.com/searchbox-io/Jest</a> </p><p> <strong>Мои тестовые примеры</strong> </p><p> <strong>Токенизатор:</strong>ik, адрес токенизатора: <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fmedcl %2Felasticsearch -anaанализ-ik" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/medcl/elasticsearch-anasis-ik</a>, существует множество все функции предоставляются на основе плагинов. После обновления версии es до 2.2.0 способ установки плагина будет другим. Если у вас возникли проблемы с установкой плагина сегментации слов ik, нажмите qq в правый верхний угол, чтобы связаться с блоггером</p><p> <strong>Новый индекс</strong> </p><p> curl -XPUT http://localhost:9200/indexdata </p><p> Создайте сопоставление индексов и укажите разделитель слов </p><p> curl -XPOST http://localhost:9200/indexdata/fulltext/_mapping </p><р> { "полный текст": { "_все": { "analyzer": "ik_max_word", "search_analyzer": "ik_max_word", "term_vector": "нет", "магазин": "ложь" }, "характеристики": { "содержание": { "тип": "строка", "хранить нет", "term_vector": "with_positions_offsets", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word", "include_in_all": "истина", "ускорение": 8 }, "описание": { "тип": "строка", "хранить нет", "term_vector": "with_positions_offsets", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word", "include_in_all": "истина", "ускорение": 8 }, "заголовок": { "тип": "строка", "хранить нет", "term_vector": "with_positions_offsets", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word", "include_in_all": "истина", "ускорение": 8 }, "ключевое слово": { "тип": "строка", "хранить нет", "term_vector": "with_positions_offsets", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word", "include_in_all": "истина", "ускорение": 8 } } } } </p><p> Информацию о сопоставлении можно просмотреть с помощью подключаемого модуля head следующим образом </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-9e281a08.png"/><р> <strong>Импортируйте данные и запросы, посмотрите код</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = ElasticSearchTestApplication.class) public class JestTestApplicationTests { @Autowired private KlarticleDao klarticleDao; //得到JestClient实例 public JestClient getClient()throws Exception{ JestClientFactory factory = new JestClientFactory(); factory.setHttpClientConfig(new HttpClientConfig .Builder("http://127.0.0.1:9200") .multiThreaded(true) .build()); return factory.getObject(); } /** * 导入数据库数据到es * @throws Exception */ @Test public void contextLoads() throws Exception{ JestClient client=getClient(); Listlists=klarticleDao.findAll(); for(Klarticle k:lists){ Index index = new Index.Builder(k).index("indexdata").type("fulltext").id(k.getArcid()+"").build(); System.out.println("添加索引----》"+k.getTitle()); client.execute(index); } //批量新增的方式,效率更高 Bulk.Builder bulkBuilder = new Bulk.Builder(); for(Klarticle k:lists){ Index index = new Index.Builder(k).index("indexdata").type("fulltext").id(k.getArcid()+"").build(); bulkBuilder.addAction(index); } client.execute(bulkBuilder.build()); client.shutdownClient(); } //搜索测试 @Test public void JestSearchTest()throws Exception{ SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchQuery("content", "搜索")); Search search = new Search.Builder(searchSourceBuilder.toString()) // multiple index or types can be added. .addIndex("indexdata") .build(); JestClient client =getClient(); SearchResult result= client.execute(search); // List> hits = result.getHits(Klarticle.class); Listarticles = result.getSourceAsObjectList(Klarticle.class); for(Klarticle k:articles){ System.out.println("------->:"+k.getTitle()); } } }</code></pre><p> <strong>Ниже приведены зависимые проекты jar и maven</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"><!--jest依赖--> <dependency> <groupId>io.searchbox</groupId> <artifactId>jest</artifactId> <version>2.0.0</version> </dependency> <!--jest 日志依赖--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>2.2.0</version> </dependency> </dependencies></code></pre><
2360226
None
Read more...
Предварительное исследование Elasticsearch, построения среды и настройки кластера под Windows
<p> <strong>Предисловие, понимание Elasticsearch</strong> </p><p> ElasticSearch — поисковый сервер на основе Lucene. Он предоставляет распределенную многопользовательскую систему полнотекстового поиска на основе веб-интерфейса RESTful. </p><p> Elasticsearch, разработанная на Java и выпущенная с открытым исходным кодом на условиях лицензии Apache, является популярной поисковой системой корпоративного уровня. Создан для использования в облачных вычислениях. </p><p> Возможность поиска в реальном времени, стабильная, надежная, быстрая, простая в установке и использовании. Мы создаем веб-сайт или приложение и хотим добавить функции поиска, и нас поражает тот факт, что поиск сложен. Мы хотим, чтобы наши поисковые решения работали быстро, </p><p> Мы хотим иметь нулевую конфигурацию и полностью бесплатную модель поиска, мы хотим иметь возможность индексировать данные, просто используя JSON через HTTP, и мы хотим, чтобы наш поисковый сервер был всегда доступен, </p><p> Мы хотим начать с одного и масштабировать его до сотен, нам нужен поиск в реальном времени, нам нужна простая мультиарендность и мы хотим создать облачное решение. </p><p> Цель Elasticsearch — решить все эти и многие другие проблемы. </p><p> <strong>Создание кластерной среды ES в Windows</strong> </p><p> Сначала перейдите на официальный сайт, чтобы загрузить последнюю версию ES, по адресу: <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fdownload.elasticsearch.org%2Felasticsearch %2Frelease%2Forg %2Felasticsearch%2Fdistribution%2Fzip%2Felasticsearch%2F2.2.1%2Felasticsearch-2.2.1.zip" rel="nofollow noopener" style="color:#0052D9" target="_blank">Нажмите меня, чтобы загрузить < /a> , эта ссылка предназначена для версии Windows, а загруженный файл представляет собой сжатый zip-архив. Структура распакованного файла следующая: </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-e302086a.png"/><p> Фактически, теперь вы можете использовать cmd для входа в каталог bin и напрямую запускать elasticsearch.bat для запуска вашего сервиса. Однако, чтобы легко запустить наш es-сервис в любом каталоге, нам нужно добавить каталог bin в In переменных среды, конкретные операции следующие: </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-5b7f32fd.png"/><p> Далее укажите ссылку ES_HOME в переменной пути </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-cff2e92c.png"/><p> Теперь вы можете использовать elasticsearch в любом каталоге для запуска службы. После запуска службы, если файл конфигурации не изменен, служба http по умолчанию прослушивает порт 9200. </p><p> Вы можете ввести localhost:9200 в адресной строке, чтобы подключиться к службе ES. Если служба работает нормально, она ответит информацией, аналогичной следующей </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">{ "name" : "node-1", "cluster_name" : "elasticsearch", "version" : { "number" : "2.2.1", "build_hash" : "d045fc29d1932bce18b2e65ab8b297fbf6cd41a1", "build_timestamp" : "2016-03-09T09:38:54Z", "build_snapshot" : false, "lucene_version" : "5.4.1" }, "tagline" : "You Know, for Search" }</code></pre><p><strong>Установить плагин ES</strong></p><p> <strong>Плагин головы</strong> </p><p> У ES есть множество плагинов на выбор. На этом этапе нам пригодится плагин заголовка инструмента управления кластером, который представляет собой независимую программу веб-страницы, написанную на HTML5 и созданную с помощью grunt. < /п><p> Вы можете интегрировать его в es с помощью подключаемых модулей. Любой, кто имеет опыт работы с базами данных, знает, что каждая база данных предоставляет программное обеспечение для управления клиентами. Если мы сравним es с базой данных, </p><p> Тогда этот головной плагин — это наше программное обеспечение для управления клиентами базы данных. Установить плагин очень просто. Его можно установить в автономном режиме или с помощью команд. Здесь рекомендуется использовать командную установку. </p><p>Это удобно и быстро, поскольку мы настроили переменные среды.При установке плагинов вы также можете ввести следующую команду в любой каталог:</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-0dec7989.png"/><p>После завершения установки в каталоге наших плагинов появится дополнительная папка head. Чтобы использовать плагин, вам необходимо перезапустить службу. После завершения запуска добавьте /_plugin/head/ после вашего es адрес службы, </p><p> Например: http://localhost:9200/_plugin/head/, если служба работает нормально, вы увидите следующую страницу, которая содержит много описаний служб ES и понятную информацию о данных с первого взгляда < /п><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-ca25537e.png"/><p> <strong>Плагин сегментации китайских слов</strong> </p><p> Конечно, для домашнего использования также необходим плагин сегментации китайских слов. Сегментация слов Elasticsearch по умолчанию не очень хорошо поддерживает китайский язык. Сегментация униарных слов — это просто разделение одного слова без знаков препинания. Здесь мы устанавливаем smartcn Chinese сегментация слов. Об этом упоминается в статье о сегментации китайских слов Lucene<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.kailing.pub%2Farticle%2Findex% 2Farcid% 2F76.html" rel="nofollow noopener" style="color:#0052D9" target="_blank">http://www.kailing.pub/article/index/arcid/76.html</a> < /п ><p> Установите сегментацию слов: плагин install Analysis-smartcn. После завершения установки перезапустите нашу службу es, и вы сможете напрямую протестировать эффект сегментации слов. Вот результаты моего теста: </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-2afe8f76.png"/><p> <strong>Конфигурация узла кластера</strong> </p><p>После выполнения вышеуказанных шагов мы еще не трогали файл конфигурации службы ES, поскольку ES выполнил за нас обработку по умолчанию, такую как порт прослушивания http 9200, а также путь хранения данных, путь журнала и т. д. </p><p> Когда нам нужно несколько узлов для формирования кластера, мы должны что-то настроить. Конкретная конфигурация следующая. У меня есть последняя версия. Я не знаю, есть ли большая разница между версиями: </p ><p>cluster.name:elasticsearch #Имя приложения кластера </p><p> node.name: node-1 #Существительное узла </p><p> network.host: 127.0.0.1 #Адрес публикации подключения к службе </p><p> http.port: 9200 #http-порт прослушивания службы </p><p> Просто оставьте пока остальные конфигурации по умолчанию </p><p> После завершения настройки запустите службу, а затем скопируйте распакованный каталог ES. Файл конфигурации изменяется следующим образом: </p><p> node.name: node-2 #Существительное узла http.port: 9201 #Порт прослушивания службы http </p><p>Все остальное остается неизменным.Обязательно убедитесь, что имена приложений кластера совпадают.Затем перейдите в каталог bin копии ES, чтобы запустить службу.После успеха используйте головной плагин для ее просмотра. Вы можете увидеть два узла узла следующим образом: </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-97c8dd9f.png"/><
2360224
None
Read more...
Обучение Lucene5.5 (10) — используйте маркер для выделения ключевых слов
<p> <strong>Предисловие</strong> </p><p> Когда мы используем поисковые системы, такие как Baidu и Google, вы обнаружите, что поисковая система отображает введенные нами ключевые слова красным шрифтом, чтобы подчеркнуть точность результатов. Это использование выделения. Сцена</p><p> <strong>Подготовка</strong> </p><p> Чтобы использовать Highlighter, вам необходимо импортировать соответствующий jar-пакет. Проект maven может добавить следующие зависимости </p><р> org.apache.lucene Lucene-хайлайтер 5.5.0 </p><p> <strong>Просмотрите код напрямую</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * @author kl by 2016/3/19 * @boke www.kailing.pub */ public class FieldSetBoostTest { //索引目录 String indexDir="E:\\LuceneIndex"; //测试数据 String theme="中国"; String []title={"中国是一个伟大的国家","我爱你的的祖国,美丽的中国","是什么,中国令美日等国虎视眈眈"}; /** * Lucence5.5返回IndexWriter实例 * @param directory * @return */ public IndexWriter getIndexWriter(Directory directory){ Analyzer analyzer=new CJKAnalyzer();//中日韩二元分词 IndexWriterConfig writerConfig=new IndexWriterConfig(analyzer); IndexWriter writer=null; try { writer =new IndexWriter(directory,writerConfig); }catch (Exception e){ e.printStackTrace(); } return writer; } public Directory getDirctory(String indexDir){ Directory directory=null; try { directory=FSDirectory.open(Paths.get(indexDir)); }catch (IOException e){ e.printStackTrace(); } return directory; } /** * 创建索引不加权 * @throws Exception */ public void Indexer()throws Exception{ IndexWriter writer=getIndexWriter(getDirctory(indexDir)); Document doc=null; for(String str:title){ doc=new Document(); //Lucence5.5 Fileld有多个实现,StringFIeld不分词 TextField分词 doc.add(new StringField("theme",theme, Field.Store.YES)); Field field=new TextField("title",str, Field.Store.YES); doc.add(field); writer.addDocument(doc); } writer.close(); } /** * 关键命中词高亮输出处理 * @param query * @param context * @return * @throws Exception */ public static String getHighlighterString(Query query,String context)throws Exception{ //对促成文档匹配的实际项进行评分 QueryScorer scorer=new QueryScorer(query); //设置高亮的HTML标签格式 Formatter simpleHTMLFormatter=new SimpleHTMLFormatter("",""); //实例化高亮分析器 Highlighter highlighter=new Highlighter(simpleHTMLFormatter,scorer); //提供静态方法,支持从数据源中获取TokenStream,进行token处理 TokenStream tokenStream=new CJKAnalyzer().tokenStream("title", new StringReader(context)); return highlighter.getBestFragment(tokenStream, context); } @Test public void searcherTest()throws Exception{ // Indexer(); IndexReader reader= DirectoryReader.open(getDirctory(indexDir)); IndexSearcher is=new IndexSearcher(reader); System.out.println("总的文档数:"+reader.numDocs()); QueryParser qp=new QueryParser("title",new CJKAnalyzer()); String q="中国"; Query query=qp.parse(q); TopDocs tDocs=is.search(query,11); System.out.println("查询-》"+q+"《-总共命中【"+tDocs.totalHits+"】条结果"); for (ScoreDoc scoredoc:tDocs.scoreDocs){ Document doc = is.doc(scoredoc.doc); String context=doc.get("title"); if(context!=null){ System.out.println(getHighlighterString(query,context)); } } } }</code></pre><p>Эффект запроса следующий: </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-d3c9d671.png"/><
2360223
None
Read more...
Lucene5.5 Обучение (9) – использование метода searchafter для реализации пейджингового запроса
<p> <strong>Предисловие</strong> </p><p> В любом случае, когда объем данных велик, при получении данных требуется обработка страниц. Например, когда мы используем Baidu, результаты часто содержат десятки миллионов результатов, а в настоящее время только несколько страниц контента Представлено. Это В сценариях подкачки Lucene также обеспечивает поддержку запросов подкачки</p><p> <strong>Познакомьтесь с поиском</strong> </p><p> С помощью метода searchafter IndexSearcher можно легко реализовать запросы по страницам, как показано ниже </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-2a263d9d.png"/><p> searchafter имеет несколько перегруженных методов, некоторые из которых больше не рекомендуются в Lucene. Чаще всего используется searchAfter(final ScoreDoc after, Query query, int numHits) </p><p> Он имеет три формальных параметра, а именно </p><p> после: последний документ ScoreDoc на предыдущей странице; </p><p> Query: объект класса реализации интерфейса запроса. Объект запроса может быть создан с помощью класса QueryParser или может быть конкретным классом реализации интерфейса нового интерфейса Query; </p><p> numHits: количество элементов, отображаемых на каждой странице </p><p> <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Flucene.apache.org%2Fcore%2F5_0_0%2Fcore%2Forg%2Fapache%2Flucene%2Fsearch%2FIndexSearcher .html%23searchAfter(org.apache.lucene.search.ScoreDoc%2C%2520org.apache.lucene.search.Query%2C%2520int)" rel="nofollow noopener" style="color:#0052D9" target="_blank ">searchafter官方文档说明地址</a> </p><p> <strong>Фокус внизу</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * Created by 小陈 on 2016/3/25. */ public class IndexerPaging { //测试数据,模拟数据库表结构 private static String[] ids={"1","2","3","4","5","6"}; //用户ID private static String [] names={"kl","kl","kl","kl","kl","fds"}; private static String [] describes={"shi yi ge mei nan zi","Don't know","Is an idiot\n","Is an idiot\n","Is an idiot\n","Is an idiot\n"}; //索引存储地址 private static String indexDir="E:\\javaEEworkspace\\LuceneDemo\\LuceneIndex"; /** * 获取操作索引实体,并添加测试数据 * @param indexDir 索引存储位置 * @return * @throws Exception */ public static void getIndexWriter(String indexDir)throws Exception{ IndexWriterConfig writerConfig=new IndexWriterConfig(getAnalyzer()); IndexWriter indexWriter=new IndexWriter(FSDirectory.open(Paths.get(indexDir)),writerConfig); Document document=new Document(); //Field.Store.YES或者NO(存储域选项) //设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原 //设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原(doc.get) for(int i=0;i1){ int pageIndexLast=(pageIndex-1)*pageSize-1; TopDocs hits=searcher.search(query,pageIndexLast); if(hits.totalHits>=pageIndexLast) return hits.scoreDocs[pageIndexLast]; } return null; } public static void searcher(String indexDir,String q,int pageIndex,int pageSize)throws Exception{ Directory directory= FSDirectory.open(Paths.get(indexDir)); IndexReader reader= DirectoryReader.open(directory); IndexSearcher indexSearcher=new IndexSearcher(reader); QueryParser queryParser=new QueryParser("names",new StandardAnalyzer()); Query query=queryParser.parse(q); //分页查询 TopDocs hits= indexSearcher.searchAfter(getPageLastScoreDoc(pageIndex,pageSize,query,indexSearcher),query,pageSize);//查询首次的30条 System.out.println("匹配 "+q+"查询到"+hits.totalHits+"个记录"); for (ScoreDoc scoreDoc:hits.scoreDocs){ Document doc=indexSearcher.doc(scoreDoc.doc); System.out.println(doc.get("describes"));//打印Document的fileName属性 } reader.close(); directory.close();//关闭连接 } /** * 得到默认分词器 * @return */ public static Analyzer getAnalyzer(){ return new StandardAnalyzer(); } @Test public void Test()throws Exception{ // getIndexWriter(indexDir); searcher(indexDir,"kl",1,10);//查询测试 } }</code></pre><
2360222
None
Read more...
Обучение Lucene5.5 (8) — QueryParser реализует расширенный запрос
<p> <strong>Предисловие</strong> </p><p> Для решения сложных бизнес-запросов Lucene предоставляет нам семантический анализатор запросов, полный набор синтаксических правил, которые могут удовлетворить большинство потребностей запросов, не заботясь о базовом классе реализации запроса, как и при написании того же самого sql. Lucene рекомендует использовать QueryParser вместо различных классов реализации запросов. Однако QueryParser не может удовлетворить все требования к запросам, например запросы на объединение нескольких документов в домене. Иногда вам все же необходимо использовать соответствующие классы реализации Query. Хорошо, давайте посмотрим, какую грамматику может анализировать QueryParser, какие проблемы он может решить, а также многодокументные доменные запросы </p><p> <strong>Загрузите код напрямую</strong> </p><p> Вы можете проверить каждую грамматику еще раз и просмотреть результаты, чтобы углубить свое понимание. Поскольку тестов здесь очень много, я не буду публиковать результаты тестов; </p><p> ps: Семантику каждого запроса можно использовать перекрестно, также используются некоторые из следующих кодов. Однако, поскольку это пример, чтобы лучше различать роль каждой семантики, было предпринято не так много попыток. </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * @author kl by 2016/3/20 * @boke www.kailing.pub */ public class QueryTest { //索引目录 String indexDir="E:\\LuceneIndex"; //测试数据目录 String dataDir="E:\\LuceneTestData"; /** * Lucence5.5返回IndexWriter实例 * @param directory * @return */ public IndexWriter getIndexWriter(Directory directory){ Analyzer analyzer=new StandardAnalyzer(); IndexWriterConfig writerConfig=new IndexWriterConfig(analyzer); IndexWriter writer=null; try { writer =new IndexWriter(directory,writerConfig); }catch (Exception e){ e.printStackTrace(); } return writer; } public Directory getDirctory(String indexDir){ Directory directory=null; try { directory= FSDirectory.open(Paths.get(indexDir)); }catch (IOException e){ e.printStackTrace(); } return directory; } @Test public void TestIndexer()throws Exception{ File[] files= new File(dataDir).listFiles(); IndexWriter writer=getIndexWriter(getDirctory(indexDir)); for(File file:files){ Document doc=new Document(); doc.add(new TextField("filePath",file.getCanonicalPath(), Field.Store.YES)); doc.add(new TextField("context",new FileReader(file))); writer.addDocument(doc); } System.out.println("总共添加了"+writer.numDocs()+"个文档"); writer.close(); } @Test public void testSearcher()throws Exception{ IndexReader reader= DirectoryReader.open(getDirctory(indexDir)); IndexSearcher searcher=new IndexSearcher(reader); QueryParser queryParser=new QueryParser("context",new StandardAnalyzer()); Query queryw=queryParser.parse("Licensor");//完整匹配分词查询 /** * 通配符 ?,*的使用 */ Query queryy=queryParser.parse("Lice?sor");//使用?匹配单个字符查询 Query queryx=queryParser.parse("L*r");//使用*匹配多个字符查询 /** * 布尔运算AND, OR,NOT,+,-的使用,注意:一定要是大写的AND和OR,NOT */ Query queryo=queryParser.parse("Licensor OR ce*");//使用OR联合多关键字查询,也可用空格代替OR Query queryoo=queryParser.parse(" Licensor ce*");//这个和使用OR一样的效果 Query queryjia=queryParser.parse("+Licensor Wildcard");//+代表必须的条件,搜索文档必须包含Licensor 可能有Wildcard Query querya=queryParser.parse("Licensor AND ce* AND Licenso?");//使用AND取多个关键字的并集查询 Query queryNot=queryParser.parse("'Lincensor Apache' NOT 'Apache Licensor'");//搜索Lincensor Apache而不是Apache Licensor Query queryjian=queryParser.parse("'Lincensor Apache' - 'Apache Licensor'");//"-"同NOT的效果一样 /** * 使用正则表达式查询 */ Query queryRegular=queryParser.parse("/[Lab]icensor/");//这个匹配Lincensor,aicensor,bicensor分词 Query queryRegularr=queryParser.parse("/[Lab]icenso[a-z]/");//根据需要可以更灵活的使用 /** * 使用~模糊匹配查询 * 这个要和*号的用法区分下,*号完整通配多个字符查询,而~不是简单的通配,这个模糊匹配和Lucene的评分有关 */ Query queryFuzzy=queryParser.parse("icensor~");//可以查到Licensor关键字,而queryParser.parse("icensor*")查不到 Query queryFuzzyparam=queryParser.parse("Licens~1");//~后面可加0-2的整数来制定模糊匹配度,默认不加为1 Query queryFuzzyParam=queryParser.parse("Licens cens ~0");//~还可以模糊匹配差异化N字符数的多个关键字 /** * 范围查询,多用于数字和时间的查询 */ Query queryRange =queryParser.parse("{abc TO Licens}");//{}abc与Licenszhi间的文件,不包含 Query queryRangex =queryParser.parse("[abc TO Licens]");//{}abc与Licenszhi间的文件,包含本身 /** * 关键字加权处理查询 */ //默认为1,可加权可降权,可通过加权处理给匹配的结果排序 Query queryBoosting =queryParser.parse("Licensor Wildcard^4 "); /** * Grouping组合查询 */ Query queryGrouping =queryParser.parse("(+Licensor +Wildcard) AND easier");//可使用()组合多个条件查询 //ps: 查询部分字符需要转义处理,如(+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /) /** * 使用MultiFieldQueryParser进行多个文档域查询 */ Map boost=new HashMap(); boost.put("filePath",1.5F);//设置文档域的权值 boost.put("context",2F); QueryParser multiField=new MultiFieldQueryParser(new String[]{"filePath","context"},new StandardAnalyzer(),boost); Query queryq=multiField.parse("lucenetestdata"); TopDocs topDocs= searcher.search(queryq,10); System.out.println("查询结果共有"+topDocs.totalHits+"条"); for(ScoreDoc scoreDoc:topDocs.scoreDocs){ Document document=searcher.doc(scoreDoc.doc); System.out.println(document.get("filePath")+"--评分:"+scoreDoc.score); } } } </code></pre><p>ps: В коде много комментариев, некоторые из которых могут быть не до конца понятны.Для более глубокого понимания обратитесь к официальной инструкции:</p><p> <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Flucene.apache.org%2Fcore%2F5_5_0%2Fqueryparser%2Forg%2Fapache%2Flucene%2Fqueryparser%2Fclassic %2Fpackage-summary.html%23Overview" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://lucene.apache.org/core/5_5_0/queryparser/org/apache/lucene /queryparser/classic/package-summary.html#Wildcard_Searches</a> </p><
2360221
None
Read more...
Lucene5.5 Обучение (7) - индексированное взвешивание домена документа
<p> <strong>Предисловие</strong> </p><p> Возьмем в качестве примера Baidu. Когда вы воспользуетесь поисковой системой Baidu, вы обнаружите, что, черт возьми, первые несколько результатов совсем не то, что мне нужно, все они представляют собой рекламный контент, и результаты Высокая степень соответствия все еще остается позади. Почему это дерьмо, перелопачивающее Baidu, ест! В этом нельзя винить Baidu: в конце концов, люди полагаются на продвижение, чтобы зарабатывать на жизнь, поэтому, естественно, вес результатов, за которые они платят, увеличивается! Это считается сценарием использования взвешивания домена документа </p><p> <strong>Описание</strong> </p><p> Так называемое «взвешивание» поля индекса означает присвоение разных весов разным значениям ключей или разным ключевым индексам в соответствии с разными потребностями, поскольку механизм оценки Lucene прямо пропорционален весу при запросе, поэтому содержимое с Большой вес с большей вероятностью будет искаться пользователями и иметь более высокий рейтинг. Обработка взвешивания домена в Lucene3. <p> ps: блоггер рассказал об этом в предыдущем сообщении блога<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.kailing.pub%2Farticle%2Findex %2Farcid% 2F76.html" rel="nofollow noopener" style="color:#0052D9" target="_blank">IKAnalyzer и paoding</a> Сегментация китайских слов. Сегодня мы используем сегментатор двоичных слов CJKAnalyzer, который можно используется в Китае, Японии и Южной Корее.</p><p> <strong>Прекратите общение, перейдите непосредственно к коду и посмотрите результаты</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">package com.kl.luceneDemo; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.cjk.CJKAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.StringField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.*; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.junit.Test; import java.io.IOException; import java.nio.file.Paths; /** * @author kl by 2016/3/19 * @boke www.kailing.pub */ public class FieldSetBoostTest { //索引目录 String indexDir="E:\\LuceneIndex"; //测试数据 String theme="中国"; String []title={"中国是一个伟大的国家","我爱你的的祖国,美丽的中国","是什么,中国令美日等国虎视眈眈"}; /** * Lucence5.5返回IndexWriter实例 * @param directory * @return */ public IndexWriter getIndexWriter(Directory directory){ Analyzer analyzer=new CJKAnalyzer();//中日韩二元分词 IndexWriterConfig writerConfig=new IndexWriterConfig(analyzer); IndexWriter writer=null; try { writer =new IndexWriter(directory,writerConfig); }catch (Exception e){ e.printStackTrace(); } return writer; } public Directory getDirctory(String indexDir){ Directory directory=null; try { directory=FSDirectory.open(Paths.get(indexDir)); }catch (IOException e){ e.printStackTrace(); } return directory; } /** * 创建索引不加权 * @throws Exception */ public void Indexer()throws Exception{ IndexWriter writer=getIndexWriter(getDirctory(indexDir)); Document doc=null; for(String str:title){ doc=new Document(); //Lucence5.5 Fileld有多个实现,StringFIeld不分词 TextField分词 doc.add(new StringField("theme",theme, Field.Store.YES)); Field field=new TextField("title",str, Field.Store.YES); doc.add(field); writer.addDocument(doc); } writer.close(); } /** * 创建索引,指定文档域加权 * @throws Exception */ public void IndexerSetBoot()throws Exception{ IndexWriter writer=getIndexWriter(getDirctory(indexDir)); Document doc=null; for(String str:title){ doc=new Document(); //Lucence5.5 Fileld有多个实现,StringFIeld不分词 TextField分词 doc.add(new StringField("theme",theme, Field.Store.YES)); Field field=new TextField("title",str, Field.Store.YES); if(str.indexOf("是什么")!=-1) field.setBoost(2);//提高权值 doc.add(field); writer.addDocument(doc); } writer.close(); } @Test public void searcherTest()throws Exception{ IndexerSetBoot(); // Indexer(); IndexReader reader= DirectoryReader.open(getDirctory(indexDir)); IndexSearcher is=new IndexSearcher(reader); System.out.println("总的文档数:"+reader.numDocs()); QueryParser qp=new QueryParser("title",new CJKAnalyzer()); Query query=qp.parse("中国"); TopDocs tDocs=is.search(query,11);//一次查询多少个结果 System.out.println("总共有【"+tDocs.totalHits+"】条结果"); for (ScoreDoc scoredoc:tDocs.scoreDocs){ Document doc = is.doc(scoredoc.doc); System.out.println(doc.getField("title").stringValue()); } } }</code></pre><p><strong>Взвешенные и невзвешенные результаты следующие:</strong></p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-a53d3b3f.png"/><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-cdc9a509.png"/><
2360220
None
Read more...
Обучение Lucene5.5 (6) — анализатор сегментации китайских слов IKAnalyzer и паодинг
<p> <strong>Предисловие</strong> </p><p> <strong>Что касается сегментации китайских слов, энциклопедия описывает ее следующим образом</strong>: </p><p> Сегментация китайских слов подразумевает разделение последовательности китайских иероглифов на отдельные слова. Сегментация слов — это процесс рекомбинации непрерывных последовательностей слов в последовательности слов в соответствии с определенными спецификациями. Мы знаем, что в английском письме в качестве естественных разделителей между словами используются пробелы, в то время как в китайском языке слова, предложения и абзацы могут быть просто разделены очевидными разделителями, но у слов нет формального разделителя. разделение фраз, но на уровне слов китайский гораздо сложнее и труднее английского. </p><p>Проще говоря, это разбиение предложения на несколько слов, а это ерунда, хаха</p><p> В предыдущих сообщениях блога автор использовал StandardAnalyzer в Lucene для обработки сегментации слов, хотя в более поздних версиях Lucene </p><p> <strong>Подготовка</strong> </p><p> Давайте сначала добавим эти два токенизатора в наш проект </p><p> <strong>IKAnalyzer</strong>: IKAnalyzer — это инструмент сегментации слов с открытым исходным кодом, разработанный китайцами. Адрес GItHub: <a class="" href="/developer/tools/blog-entry?target=https% 3A% 2F%2Fgithub.com%2Fwks%2Fik-analyzer" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/wks/ik-analyzer</a >. Рекомендуется загрузить исходный код на GitHub и упаковать его самостоятельно.Проект собирается с помощью maven, превращается в jar, а затем на него ссылаются в нашем проекте. </p><p> ps: не забудьте удалить тест при упаковке проекта </p><p> <strong>paoding</strong>: paoding также является проектом с открытым исходным кодом. Он загружается в виде сжатого файла, содержащего исходный код и упакованные файлы jar, которые можно использовать напрямую. </p><p> ps: при загрузке paoding посещайте иностранные веб-сайты.</p><p> <strong>Введите текст</strong> </p><p>У автора не все гладко было в процессе тестирования. Было много подводных камней. Давайте разберемся в этих подводных камнях </p><p> <strong>Вопрос IAnlyzer</strong>: </p><p> 1. Последний проект также основан на версии Lucene3.0.3, и автор всегда использовал последнюю версию Lucene5.5, поэтому, как только я ее протестировал, появилась следующая ошибка </p><p> Исключение в потоке "main" java.lang.VerifyError: класс org.wltea.analyzer.lucene.IKAnalyzer переопределяет конечный метод tokenStream.(Ljava/lang/String;Ljava/io/Reader;)Lorg/apache/lucene/ анализ/TokenStream; </p><p>Решение: Автор попытался перепаковать Lucene-версию проекта IKAnlyzer с 5.5, но обнаружил, что это не сработало.Изменений было слишком много, хотя проект IKAnlyzer не был большим и файлов было немного. Автор пока не дошёл до возможности переписать проект IKAnlyzer.Если будет время, могу изучить исходный код.В конце концов придётся понизить собственную версию Lucene.К счастью, доступен maven.Чтобы понизить версию, достаточно изменить pom.xml. </p><p> <strong>Проблема с заливкой</strong> </p><p> 1. Проект сначала будет опираться на Commons-logging Apache. Автор протестировал версию 1.1 и принял ее. </p><p> 2. Возникает следующая проблема. Фактически, аналогичные инструкции по этой проблеме есть в собственном документе использования paoding (Справочное руководство по сегментации китайских слов Paoding.htm). Этот документ включен в загруженный сжатый пакет</ р ><p> net.paoding.anaанализ.Exception.PaodingAnaанализException: установите системную среду PAODING_DIC_HOME или Config paoding.dic.home в paoding-dic-home.properties, указывающую на словари! </p><p> Решение: просто укажите каталог файла словаря для paoding. Этот файл находится в формате dic в загруженном сжатом пакете. </p><p> Три решения: </p><p> (1) Вы можете распаковать jar, затем указать каталог документов для paoding.dic.home в файле paoding-dic-home.properties, повторно сжать его и изменить суффикс на jar. </p><p> (2) Просто следуйте официальным инструкциям и добавьте каталог doc в переменную среды. </p><p> (3). Поместите документ в каталог проекта </p><p> 3. Еще одна проблема с paoding заключается в том, что Lucene 3.0.3 больше не совместима, поэтому автору пришлось понизить версию Lucene до 2.2.0 для тестирования </p><p> <strong>Наконец-то пришло время показать свои настоящие навыки в преодолении этих рвов и препятствий. Без лишних слов, давайте перейдем непосредственно к коду и картинке выше</strong> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">package com.kl.Lucene; import net.paoding.analysis.analyzer.PaodingAnalyzer; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Token; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.TermAttribute; import org.junit.Test; import org.wltea.analyzer.lucene.IKAnalyzer; import java.io.StringReader; /** * @author kl by 2016/3/14 * @boke www.kailing.pub */ public class AnalyzerTest { //测试数据 public static String testData="中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一" + "一个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。"; /** * 得到IKAnalyzer分词器 * @return */ public static Analyzer getIKAnalyzer(){ return new IKAnalyzer(); } /** * 得到Paoding分词器 * @return */ public static Analyzer getPaoding(){ return new PaodingAnalyzer(); } /** * 测试IKAnalyzer * @throws Exception */ @Test public void TestIKAnalyzer()throws Exception{ Analyzer analyzer =getIKAnalyzer(); TokenStream tokenStream = analyzer.tokenStream("", new StringReader(testData)); tokenStream.addAttribute(TermAttribute.class); System.out.println("分词数据:"+testData); System.out.println("=====IKAnalyzer的分词结果===="); while (tokenStream.incrementToken()) { TermAttribute termAttribute = tokenStream.getAttribute(TermAttribute.class); System.out.println(new String(termAttribute.term())); termAttribute.termLength(); } } /** * 测试Paoding * @throws Exception */ @Test public void TestPaoding()throws Exception{ Analyzer analyzer =getPaoding(); TokenStream ts = analyzer.tokenStream("", new StringReader(testData)); System.out.println("分词数据:"+testData); System.out.println("=====Paoding的分词结果===="); Token t; // while ((t = ts.next()) != null) { // System.out.println(t.termText()); // } } }</code></pre><p><strong>Тестовые данные:</strong> Сегментация китайских слов подразумевает разделение последовательности китайских иероглифов на отдельное слово. Сегментация слов — это процесс рекомбинации непрерывных последовательностей слов в последовательности слов в соответствии с определенными спецификациями. </p><p>Результаты теста следующие: </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-8c5f63eb.png"/><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-7ec18659.png"/><p> Судя по результатам, сегментация слов в IKAnalyzer и paoding почти одинакова. Сегментация слов в IKAnlyzer более детальная, чем в paoding. Вы можете проверить файлы словарей сегментации слов для анализа </p><p> Постскриптум: в дополнение к двум сегментациям слов, представленным выше, широко используемые сегментаторы двоичных слов для китайского, японского и корейского языков, CJKAnalyzer и SmartChineseAnalyzer от Lucene, основанные на сегментации слов Китайской академии наук, среди которых cjk находится в пакете jar пакета lucene-common, SmartChineseAnalyzer необходимо ввести отдельно. Следующие зависимости pom</p><p> <!--Общедоступный токенизатор, включая большинство языковых токенизаторов--></p><p> <зависимость></p><p> <зависимость></p><p> <groupId>org.apache.lucene</groupId></p><p> <groupId>org.apache.lucene</groupId></p><p> <artifactId>lucene-analyzers-common</artifactId></p><p> <версия>5.5.0</версия></p><p> <версия>5.5.0</версия></p><p> </зависимость></p><p> </зависимость></p><p> <!--Сегментация китайских слов на основе данных Китайской академии наук--></p><p> <artifactId>lucene-analyzers-smartcn</artifactId></p><
2360219
None
Read more...
Lucene5.5 Обучение (5) – [добавление, удаление, изменение и проверка] индекса Lucene
<p> <strong>Предисловие</strong> </p><p> От вводной демонстрации до понимания принципов, понимания структуры и последующего изучения инструментов — теперь мы можем использовать Lucene для выполнения простых операций добавления, удаления, изменения и запроса данных </p><p> <strong>Загрузите код напрямую</strong> </p><p>ps: Комментарии к коду относительно полные, из-за уровня автора некоторые вещи могут быть не понятны на месте. Для участия в тестировании рекомендуется использовать Luke. Чтобы узнать о Luke, обратитесь к моему предыдущему сообщению в блоге: <a class="" href="/developer/tools/blog-entry?target=http%3A%2F% 2Fwww.kailing.pub% 2Farticle%2Findex%2Farcid%2F74.html" rel="nofollow noopener" style="color:#0052D9" target="_blank">http://www.kailing.pub/article/index/ arcid/74.html</a> </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">package com.kl.Lucene; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.StringField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.*; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.*; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.junit.Test; import java.nio.file.Paths; /** * @author kl by 2016/3/14 * @boke www.kailing.pub */ public class IndexerCURD { //测试数据,模拟数据库表结构 private static String[] ids={"1","2","3"}; //用户ID private static String [] names={"kl","wn","sb"}; private static String [] describes={"shi yi ge mei nan zi","Don't know","Is an idiot\n"}; //索引存储地址 private static String indexDir="E:\\javaEEworkspace\\LuceneDemo\\LuceneIndex"; /** * 获取操作索引实体,并添加测试数据 * @param indexDir 索引存储位置 * @return * @throws Exception */ public static IndexWriter getIndexWriter(String indexDir)throws Exception{ IndexWriterConfig writerConfig=new IndexWriterConfig(getAnalyzer()); IndexWriter indexWriter=new IndexWriter(getDirectory(indexDir),writerConfig); Document document=new Document(); //Field.Store.YES或者NO(存储域选项) //设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原 //设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原(doc.get) for(int i=0;i"+doc.get("ids")); } reader.close(); } catch (Exception e) { e.printStackTrace(); } } }</code></pre><
2360218
None
Read more...
Обучение Lucene5.5 (4) — инструмент просмотра индекса Lucene, Люк
<p> <strong>Предисловие</strong> </p><p> Luke — это сторонний инструмент для поисковых систем Lucene, который упрощает разработку и диагностику. Он может получать доступ к существующим индексам Lucene и позволяет отображать и изменять их. Если мы сравним индекс Lucene с данными базы данных, то Люк — это клиент (СУБД), который управляет данными. Когда мы разрабатываем Lucene, мы можем использовать этот инструмент для повышения эффективности нашей разработки </p><p> <strong>Подготовка</strong> </p><p> Luke — это проект с открытым исходным кодом, размещенный на GitHub по адресу <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2FDmitryKey% 2Fluke" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/DmitryKey/luke</a>, выберите нашу ветку Люка и загрузите ее</p><p>ps: Lucene обновляется и выполняет итерации очень быстро, а изменения в каждой версии относительно велики, поэтому, когда мы выбираем версию Люка, мы также должны выбрать соответствующую версию в соответствующей ветке, иначе это будет gg. Lucene - это последняя версия 5.X, конечно, Люк тоже выбрал последнюю</p><p> Luke — это проект maven. После загрузки установите его, и он будет упакован в пакет jar. Просто дважды щелкните файл jar, чтобы запустить его. </p><p>ps: Последний Люк использует jdk1.8. Если вы не знаете о других версиях, вы можете проверить файл pom.xml </p><p>Интерфейс после запуска следующий: здесь я выбрал индексный каталог </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-15776f9a.png"/><p> <strong>Иллюстрация</strong> </p><p> Из информации в 1 вы можете увидеть, сколько полей имеет этот документ, а также количество сегментов слов, процентное соотношение и кодировку каждого поля </p><p> 2. Информация здесь представляет собой статистическую область, в которой указано количество документов, количество полей в документе и общее количество причастий </p><p> 3. Вы можете повторно открыть индекс (когда индекс изменится) и зафиксировать изменения </p><p> 4. Здесь представлена подробная информация об индексе. Вы можете увидеть частоту появления каждого сегмента слова и соответствующего поля </p><p> <strong>Использование Люка</strong> </p><p>На картинке выше вы можете увидеть функцию первой вкладки OverView.Далее давайте посмотрим на функции остальных вкладок</p><p> Вкладка «Документы» используется для управления и просмотра документов, например для удаления и добавления файлов. Для просмотра подробной информации о документе можно использовать следующий большой список. Очень ли он похож на данные таблицы представления СУБД? Выше есть два метода поиска документов: поиск по номеру документа и поиск по словам. По сути, это поиск. Подробности следующие</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-c684cca7.png"/><р> На мой взгляд, вкладка поиска является наиболее полезным интерфейсом, где мы можем выполнять тесты поиска по индексу, писать большинство операторов поиска Lucene, а затем просматривать дерево запросов после анализа оператора, чтобы мы могли знать, почему у нас есть некоторые запросы. не найдет нужную нам информацию, и тогда мы также можем выбрать сегментатор слов для поиска, поле по умолчанию и количество повторных поисков (среднее время процесса поиска можно получить с помощью нескольких поисков, что очень важно для запрос) Очень полезно для тестирования производительности), тогда в представлении списка ниже будут перечислены все сохраненные (сохраненные) значения полей искомого документа, и вы сможете увидеть время, затраченное на запрос ниже. Подробности показаны ниже </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-09fabb18.png"/><p> Вкладка «Коммиты» — это интерфейс, используемый для просмотра некоторых атрибутов каждого файла, связанного с индексом. В частности, вы можете использовать этот интерфейс для анализа размера индексного файла, необходимости его оптимизации или объединения и т. д. Подробности следующие</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-e051d4b9.png"/><p> На последней вкладке плагинов вы можете увидеть различные плагины, предоставленные Люком. Я думаю, что более полезным из них является инструмент сегментации слов, который предоставляет класс сегментации слов, а затем вводит фрагмент текста в текст. поле ниже, а затем вы можете использовать этот инструмент. Помогите вам сегментировать слова, вы можете увидеть подробную информацию о сегментации слов. Подробности показаны ниже </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-9645440e.png"/><
2360217
None
Read more...
Обучение Lucene5.5 (4) — инструмент просмотра индекса Lucene, Люк
<p> <strong>Предисловие</strong> </p><p> Luke — это сторонний инструмент для поисковых систем Lucene, который упрощает разработку и диагностику. Он может получать доступ к существующим индексам Lucene и позволяет отображать и изменять их. Если мы сравним индекс Lucene с данными базы данных, то Люк — это клиент (СУБД), который управляет данными. Когда мы разрабатываем Lucene, мы можем использовать этот инструмент для повышения эффективности нашей разработки </p><p> <strong>Подготовка</strong> </p><p> Luke — это проект с открытым исходным кодом, размещенный на GitHub по адресу <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2FDmitryKey% 2Fluke" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/DmitryKey/luke</a>, выберите нашу ветку Люка и загрузите ее</p><p>ps: Lucene обновляется и выполняет итерации очень быстро, а изменения в каждой версии относительно велики, поэтому, когда мы выбираем версию Люка, мы также должны выбрать соответствующую версию в соответствующей ветке, иначе это будет gg. Lucene - это последняя версия 5.X, конечно, Люк тоже выбрал последнюю</p><p> Luke — это проект maven. После загрузки установите его, и он будет упакован в пакет jar. Просто дважды щелкните файл jar, чтобы запустить его. </p><p>ps: Последний Люк использует jdk1.8. Если вы не знаете о других версиях, вы можете проверить файл pom.xml </p><p>Интерфейс после запуска следующий: здесь я выбрал индексный каталог </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-15776f9a.png"/><p> <strong>Иллюстрация</strong> </p><p> Из информации в 1 вы можете увидеть, сколько полей имеет этот документ, а также количество сегментов слов, процентное соотношение и кодировку каждого поля </p><p> 2. Информация здесь представляет собой статистическую область, в которой указано количество документов, количество полей в документе и общее количество причастий </p><p> 3. Вы можете повторно открыть индекс (когда индекс изменится) и зафиксировать изменения </p><p> 4. Здесь представлена подробная информация об индексе. Вы можете увидеть частоту появления каждого сегмента слова и соответствующего поля </p><p> <strong>Использование Люка</strong> </p><p>На картинке выше вы можете увидеть функцию первой вкладки OverView.Далее давайте посмотрим на функции остальных вкладок</p><p> Вкладка «Документы» используется для управления и просмотра документов, например для удаления и добавления файлов. Для просмотра подробной информации о документе можно использовать следующий большой список. Очень ли он похож на данные таблицы представления СУБД? Выше есть два метода поиска документов: поиск по номеру документа и поиск по словам. По сути, это поиск. Подробности следующие</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-c684cca7.png"/><р> На мой взгляд, вкладка поиска является наиболее полезным интерфейсом, где мы можем выполнять тесты поиска по индексу, писать большинство операторов поиска Lucene, а затем просматривать дерево запросов после анализа оператора, чтобы мы могли знать, почему у нас есть некоторые запросы. не найдет нужную нам информацию, и тогда мы также можем выбрать сегментатор слов для поиска, поле по умолчанию и количество повторных поисков (среднее время процесса поиска можно получить с помощью нескольких поисков, что очень важно для запрос) Очень полезно для тестирования производительности), тогда в представлении списка ниже будут перечислены все сохраненные (сохраненные) значения полей искомого документа, и вы сможете увидеть время, затраченное на запрос ниже. Подробности показаны ниже </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-09fabb18.png"/><p> Вкладка «Коммиты» — это интерфейс, используемый для просмотра некоторых атрибутов каждого файла, связанного с индексом. В частности, вы можете использовать этот интерфейс для анализа размера индексного файла, необходимости его оптимизации или объединения и т. д. Подробности следующие</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-e051d4b9.png"/><p> На последней вкладке плагинов вы можете увидеть различные плагины, предоставленные Люком. Я думаю, что более полезным из них является инструмент сегментации слов, который предоставляет класс сегментации слов, а затем вводит фрагмент текста в текст. поле ниже, а затем вы можете использовать этот инструмент. Помогите вам сегментировать слова, вы можете увидеть подробную информацию о сегментации слов. Подробности показаны ниже </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-9645440e.png"/><
2360216
None
Read more...
Обучение Lucene5.5 (3) — структура индексного файла Lucene
<p> <strong>Структура индекса Lucene является иерархической и в основном разделена на следующие уровни: </strong> </p><img src="https://developer.qcloudimg.com/http-save/yehe-1651485/e34b13850543739d72d94d6deed71400.png"/><li> Индекс: <ul class="ul-level-1"><li> В Lucene индекс помещается в папку. </li><li> Как показано выше, все файлы в одной папке составляют индекс Lucene. </li></ul></li><li> В Lucene индекс помещается в папку. </li><li> Как показано выше, все файлы в одной папке составляют индекс Lucene. </li><li> Сегмент: <ul class="ul-level-1"><li> Индекс может содержать несколько сегментов, каждый из которых независим. Добавление нового документа может создать новый сегмент. Различные сегменты можно объединять. </li><li>Как показано на рисунке выше, файлы с одинаковым префиксом принадлежат одному сегменту.На рисунке три сегмента «_0», «_1» и «_2». </li><li>egments.gen и сегменты_X — это файлы метаданных сегментов, то есть они сохраняют информацию об атрибутах сегментов. </li></ul></li><li> Индекс может содержать несколько сегментов, причем сегменты независимы. Добавление новых документов может привести к созданию новых сегментов, а разные сегменты могут быть объединены. </li><li> Как показано на рисунке выше, файлы с одинаковым префиксом принадлежат одному и тому же сегменту. На рисунке показаны три сегмента: «_0», «_1» и «_2». </li><li> slots.gen и сегменты_X — это файлы метаданных сегментов, то есть они сохраняют информацию об атрибутах сегментов. </li><li> Документ: <ul class="ul-level-1"><li> Документ — это основная единица построения индекса. Разные документы хранятся в разных сегментах. Один сегмент может содержать несколько статей. </li><li>Новый добавленный документ сохраняется отдельно в новом созданном сегменте.При объединении сегментов разные документы объединяются в один сегмент. </li></ul></li><li> Документы — это основная единица построения индексов. Разные документы хранятся в разных сегментах, и один сегмент может содержать несколько документов. </li><li>Новый добавленный документ сохраняется отдельно в новом созданном сегменте.При объединении сегментов разные документы объединяются в один сегмент. </li><li> Поле: <ul class="ul-level-1"><li> Документ содержит различные типы информации, которые можно индексировать отдельно, например название, время, текст, автор и т. д. сохраняться в разных доменах. </li><li>Методы индексации разных доменов могут быть разными, мы это подробно объясним, когда будем собственно анализировать хранилище домена. </li></ul></li><li> Документ содержит различные типы информации, которые могут индексироваться отдельно, например название, время, текст, автор и т. д., которые можно сохранять в разных полях. </li><li>Методы индексации разных доменов могут быть разными, мы объясним это подробно, когда будем собственно анализировать хранилище домена. </li><li> Термин: <ul class="ul-level-1"><li> Термин — это наименьшая единица индекса, представляющая собой строку после лексического анализа и языковой обработки. </li></ul></li><li>Слово — это наименьшая единица индекса, представляющая собой строку после лексического анализа и языковой обработки. </li><p> <strong> Дополнительные соответствующие суффиксы файлов</strong> </p><p>Имя</p><p>Расширение файла</p><p>Описание</p><p>Сегментировать файл</p><p>сегментов_N</p><p>Сохраняет количество сегментов, содержащихся в индексе, и количество документов, содержащихся в каждом сегменте. </p><p>Сегментировать метаданные</p><p>.if</p><p>Сохраняет метаданные сегмента индекса</p><p>Заблокировать файл</p><p>write.lock</p><p>Запретить одновременную запись нескольких IndexWriters в индексный файл. </p><p>Файл составного индекса</p><p>.cfs, .cfe</p><p>Сохраняйте всю индексную информацию в составных индексных файлах. </p><p>Информация о поле индексного сегмента</p><p>.fnm</p><p>Сохраните поля, содержащиеся в этом разделе, а также имя поля и тип индекса поля. </p><p>Информация о документе индексного сегмента</p><p>.fdx, .fdt</p><p>Сохраните документы, содержащиеся в этом разделе, поля, содержащиеся в каждом документе, и информацию о каждом поле. </p><p>Информация о терминах сегмента индекса</p><p>.team, .tip</p><p>Файл .tim хранит статистическую информацию Term в каждом домене и сохраняет указатели на индексные файлы .doc, .pos и .pay. Файл .tip сохраняет индексную информацию словаря терминов и поддерживает произвольный доступ. </p><p>Частота слов термина и информация о списке пропуска в документе</p><p>.doc</p><p>Сохраните информацию о частоте терминов, соответствующую каждому документу в этом абзаце. </p><p>Информация о местоположении термина в документе</p><p>.pos</p><p>Сохраните информацию о местонахождении термина, соответствующую каждому документу в этом абзаце. </p><p>Полезная нагрузка и частичная информация о местоположении документа</p><p>.он</p><p>Сохраните информацию о полезной нагрузке и позиции термина (смещениях) каждого документа в этом разделе. Часть информации о местоположении термина хранится в файле .pos. </p><p>Весовой коэффициент индексного поля</p><p>.nvd, .nvm</p>Файл <p>.nvm содержит метаданные весовых коэффициентов индексных полей. В файле .nvd сохраняются взвешенные данные индексного поля</p><p>Весовой коэффициент индексного документа</p><p>.dvd, .dvm</p>Файл <p>.dvm содержит метаданные для весовых коэффициентов индексированных документов. Файл .dvd содержит взвешенные данные проиндексированного документа</p><p>Индексные векторные данные</p><p>.tvx, .tvd, .tvf</p><p>.tvd хранит Срок, частоту использования, информацию о местоположении, полезную нагрузку и другую информацию этого документа. Индексный файл .tvx, используемый для загрузки определенных документов в память. .tvf сохраняет векторную информацию индексного поля. </p><p>Действительный документ</p><p>.life</p><p>Сохраните информацию индексного файла действительных документов</p><p> <strong>В структуре индекса Lucene сохраняется как прямая, так и обратная информация. </strong> </p><p>Так называемая положительная информация:</p><li> Отношения включения от индекса к слову хранятся иерархически: Индекс –> Сегмент –> Документ –> Поле –> Термин </li><li> То есть этот индекс содержит эти сегменты, каждый сегмент содержит эти документы, каждый документ содержит эти поля и каждое поле содержит эти слова. </li><li> Поскольку это иерархическая структура, каждый уровень хранит информацию этого уровня и метаинформацию следующего уровня, то есть атрибутивную информацию. Например, книга, знакомящая с китайской географией, должна сначала представить обзор китайской географии. и Сколько провинций состоит из Китая? В каждой провинции представлен общий обзор провинции и количества городов, входящих в нее. Каждый город представляет базовый обзор города и количества уездов, входящих в него. Каждый уезд представляет конкретную ситуацию в каждом уезде. . </li><li> Как показано выше, файлы, содержащие предварительную информацию: <ul class="ul-level-1"><li>egments_N сохраняет количество сегментов, содержащихся в этом индексе, и количество документов, содержащихся в каждом сегменте. </li><li> XXX.fnm сохраняет количество доменов, содержащихся в этом сегменте, имя и метод индексации каждого домена. </li><li> XXX.fdx, XXX.fdt сохраняет все документы, содержащиеся в этом разделе, сколько полей содержит каждый документ и какая информация сохраняется в каждом поле. </li><li> XXX.tvx и другая информация. </li></ul></li><li> сегменты_N сохраняет количество сегментов, содержащихся в этом индексе, и количество документов, содержащихся в каждом сегменте. </li><li> XXX.fnm сохраняет количество доменов, содержащихся в этом сегменте, имя и метод индексации каждого домена. </li><li> XXX.fdx, XXX.fdt сохраняет все документы, содержащиеся в этом разделе, сколько полей содержит каждый документ и какая информация сохраняется в каждом поле. </li><li>XXX.tvx, </li><p> Так называемая обратная информация: </p><li> Сохраняет сопоставление из словаря в инвертированный список: Термин -> Документ </li><li> Как показано выше, файлы, содержащие обратную информацию: <ul class="ul-level-1"><li> XXX.tis, XXX.tii сохраняет словарь (Term Dictionary), который и содержит этот абзац. Все слова отсортированы лексикографически. </li><li> XXX.frq сохраняет инвертированный список, то есть список идентификаторов документов, содержащий каждое слово. </li><li> XXX.prx сохраняет позицию каждого слова в инвертированном списке в документе, содержащем это слово. </li></ul></li><li> XXX.tis, XXX.tii сохраняют словарь (Term Dictionary), то есть все слова, содержащиеся в этом абзаце, сортируются в словарном порядке. </li><li> XXX.frq сохраняет инвертированный список, который представляет собой список идентификаторов документов, содержащий каждое слово. </li><li> XXX.prx сохраняет позицию каждого слова в списке инверсий в документе, содержащем это слово. </li><p> Прежде чем разобраться в подробной структуре индекса Lucene, давайте взглянем на основные типы данных в индексе Lucene. </p><p> В индексных файлах Lucene для хранения информации используются следующие основные типы: </p><li> Байт: это самый простой тип, длиной 8 бит. </li><li> UInt32: состоит из 4 байтов. </li><li> UInt64: состоит из 8 байт. </li><li> VInt: <ul class="ul-level-1"><li> Целочисленный тип переменной длины, который может содержать несколько байтов. Для каждого 8-битного байта последние 7 бит представляют числовое значение, до 1 Бит указывает, есть ли еще один Байт, 0 означает отсутствие, 1 означает, что есть. </li><li> Байт спереди представляет младшую цифру значения, а байт сзади представляет старший байт значения. </li><li>Например, 130 преобразуется в двоичное число как 1000, 0010, что требует всего 8 бит. Один байт не может его представить, поэтому для его представления необходимы два байта. Первый байт представляет последние 7 цифры, а самая высокая позиция равна 1. Это означает, что позади еще один байт, поэтому это (1) 0000010. Второй байт означает 8-й бит, а самая высокая позиция равна 0, что указывает на то, что позади нет другого байта, так что это (0) 0000001. </li></ul></li><li> Целочисленный тип переменной длины, который может содержать несколько байтов. Для 8 бит каждого байта последние 7 бит представляют числовое значение, а старший 1 бит указывает, есть ли еще один байт. 0 означает нет, 1 означает есть. </li><li> Первый байт представляет младшую цифру значения, а последующий байт представляет старший байт значения. </li><li> Например, 130 преобразуется в двоичное число как 1000, 0010, что требует всего 8 бит. Один байт не может его представить, поэтому для его представления необходимы два байта. Первый байт представляет последние 7 цифр, а второй Самая высокая позиция 1 представляет следующее: Один байт, то есть (1) 0000010, второй байт представляет 8-й бит, а самая высокая позиция равна 0, что указывает на то, что позади нет другого байта, поэтому это (0) 0000001. </li><img src="https://developer.qcloudimg.com/http-save/yehe-1651485/328d3f5d7d20db2e7fc0223d01254ecb.jpg"/><li> Символы: это последовательность байтов, закодированных в UTF-8. </li><li> Строка: строка сначала представляет собой VInt, представляющий количество символов, содержащихся в строке, за которым следует последовательность символов в кодировке UTF-8 Chars. </li><p> Lucene применила некоторые специальные методы, чтобы хранилище информации занимало меньше места и обеспечивало более быстрый доступ к ней. Однако при взгляде на формат файла Lucene эти методы могут легко нас сбить с толку, поэтому необходимо использовать эти специальные методы. технические правила извлекаются и вводятся. </p><p> Извините, я случайно дал этим правилам несколько названий, чтобы их было легче применять в дальнейшем. Простите меня за неудобства. </p><p>Lucene необходимо сохранить информацию словаря (Term Dictionary) в обратном индексе. Все слова (Terms) в словаре расположены в словарном порядке. Однако словарь содержит почти все слова в документе. И некоторые слова очень длинные, поэтому индексный файл будет очень большим.Так называемое правило префиксов и суффиксов означает, что, когда слово имеет общий префикс с предыдущим словом, следующее слово сохраняет в слове только префикс.Сдвиг (смещение ) и строки, отличные от префиксов (называемые суффиксами). </p><img alt="[图]前缀后缀规则" src="https://developer.qcloudimg.com/http-save/yehe-1651485/b7d22f80205e7641b7ea851cfd122647.jpg"/><p> Например, вы хотите сохранить следующие слова: term, termagancy, termagant, терминал, </p><p> При обычном хранении требуемое пространство будет следующим: </p><p> При обычном хранении требуемое пространство будет следующим: </p><p> [VInt = 4] [t][e][r][m],[VInt = 10][t][e][r][m][a][g][a][n] [c][y],[VInt = 9][t][e][r][m][a][g][a][n][t],[VInt = 8][t][e ][r][m][i][n][a][l] </p><p> Всего требуется 35 байт. </p><p> Если применяются правила префиксов и суффиксов, необходимое пространство следующее: </p><p> [VInt = 4] [t][e][r][m],[VInt = 4 (смещение)][VInt = 6][a][g][a][n][c][ y],[VInt = 8 (смещение)][VInt = 1][t],[VInt = 4(смещение)][VInt = 4][i][n][a][l] </p><p> Всего требуется 22 байта. </p><p>Значительно сокращается пространство для хранения, особенно в случае сортировки по словарю, значительно повышается уровень совпадения префиксов. </p><p> В обратном индексе Lucene необходимо сохранить много целочисленной информации, например идентификационный номер документа, положение слова (терм) в документе и т. д. </p><p> Из приведенного выше введения мы знаем, что целые числа хранятся в формате VInt. По мере увеличения значения количество байтов, занимаемых каждым числом, также постепенно увеличивается. Так называемое правило разницы (дельта) означает, что когда два целых числа сохраняются одно за другим, последнее целое число сохраняет только разницу с предыдущим целым числом. </p><img alt="[图]差值规则" src="https://developer.qcloudimg.com/http-save/yehe-1651485/d047706f1a6dfbafac782cb8ee4fdee0.jpg"/><p> Например, вы хотите сохранить следующие целые числа: 16386, 16387, 16388, 16389 </p><p> [(1) 000, 0010][(1) 000, 0000][(0) 000, 0001],[(1) 000, 0011][(1) 000, 0000][(0) 000, 0001],[(1) 000, 0100][(1) 000, 0000][(0) 000, 0001],[(1) 000, 0101][(1) 000, 0000][(0) 000, 0001] </p><p> Спрос и предложение составляют 12 байт. </p><p> Если для хранения используются правила различия, необходимое пространство следующее: </p><p> [(1) 000, 0010][(1) 000, 0000][(0) 000, 0001],[(0) 000, 0001],[(0) 000, 0001],[(0) 000, 0001] </p><p> Всего требуется 6 байт. </p><p> Пространство для хранения значительно сокращается, а идентификатор документа и положение слова в документе постепенно увеличиваются от меньшего к большему. </p><p> В структуре индекса Lucene существует такая ситуация: определенное значение B может существовать, а может и не существовать после определенного значения A. Для указания того, следует ли B, необходим флаг. </p><p> Обычно байт помещается после A. Если он равен 0, после него нет B. Если он равен 1, после него идет B. Или, если он равен 0, после него идет B. Если это 1, после него нет буквы B. </p><p> Но это приведет к потере одного байта пространства. На самом деле одного бита достаточно. </p><p> В Lucene принят следующий метод: значение A сдвигается на один бит влево, а последний бит освобождается как бит флага, указывающий, следует ли B, поэтому в этом случае A/2 вещественное Исходное значение А. </p><img src="https://developer.qcloudimg.com/http-save/yehe-1651485/6fcd30ee54592895712ec002f4525645.jpg"/><p> Если вы прочтете статью Apache Lucene — форматы индексных файлов, вы найдете множество таких, которые соответствуют этому правилу: </p><li> DocDelta[, Freq?], DocSkip, PayloadLength? </li> в файле .frq<li> PositionDelta, полезные данные в файле .prx? (Но не полностью, как показано в следующей таблице) </li><p> Конечно, есть некоторые символы с ?, которые не подпадают под это правило: </p><li> SkipChildLevelPointer? в файле .frq — это указатель на таблицу следующего уровня в многоуровневой таблице пропуска. Конечно, если это последний уровень, это значение не существует и флаг не требуется. </li><li> Позиции?, Смещения? в файле .tvf. <ul class="ul-level-1"><li> В таких случаях наличие или отсутствие значения с ? не зависит от последней цифры предыдущего значения. </li><li>Скорее это зависит от определенной конфигурации Lucene.Конечно, эти конфигурации также сохраняются в индексном файле Lucene. </li><li> Сохранение позиции и смещения зависит от конфигурации каждого домена в файле .fnm (TermVector.WITH_POSITIONS и TermVector.WITH_OFFSETS) </li></ul></li><li> В таких случаях наличие или отсутствие значения с ? не зависит от последней цифры предыдущего значения. </li><li> Скорее, это зависит от определенной конфигурации Lucene. Разумеется, эти конфигурации также сохраняются в индексном файле Lucene. </li><li> Сохранение позиции и смещения зависит от конфигурации каждого домена в файле .fnm (TermVector.WITH_POSITIONS и TermVector.WITH_OFFSETS) </li><p> На самом деле понятно, почему существуют две вышеуказанные ситуации: </p><li> Для тех, кто соблюдает правила следования вероятности, это потому, что для каждого A существует разное существование B. Когда такая ситуация существует в больших количествах, 8-кратная экономия пространства от одного байта к одному биту все равно того стоит. . </li><li> Для тех, кто не соблюдает условные следующие правила, конфигурация того, существует или нет определенное значение, действительна для всего поля (Поля) или даже для всего индекса, а не каждый раз разная, поэтому она может храниться единообразно.знак. </li><p> Описание следующего формата в статье сбивает с толку: Позиции -> Частота Полезная нагрузка --> Применяют ли PositionDelta и Payload правила условных подписчиков? Как определить, существует ли PayloadLength? Фактически, PositionDelta и Payload не соответствуют следующим условным правилам.Существование полезных данных определяется конфигурацией полезных данных в конфигурации каждого домена в файле .fnm (FieldOption.STORES_PAYLOADS). Когда полезная нагрузка не существует, сама PayloadDelta не следует принципу вероятности. Если полезная нагрузка существует, формат должен стать следующим: Позиции -> Частота. Таким образом, PositionDelta и PayloadLength применяются или следуют правилам вместе. </p><p> Чтобы улучшить производительность поиска, Lucene во многих местах использует структуру данных таблицы переходов. </p><p> Пропускной список — это структура данных, показанная на рисунке, которая имеет следующие основные характеристики: </p><li> Элементы располагаются в Lucene либо в порядке словаря, либо в порядке возрастания. </li><li>Прыжки имеют интервалы (Interval), то есть количество элементов для каждого перехода.Интервалы настраиваются заранее, как показано на рисунке, интервал таблицы переходов равен 3. </li><li>Список переходов состоит из уровней.Элементы каждого уровня через определенные интервалы составляют предыдущий уровень.Как показано на рисунке, список переходов имеет 2 уровня. </li><img src="https://developer.qcloudimg.com/http-save/yehe-1651485/0947577f2e2fe4e22a73eb9124d751a8.jpg"/><p>Следует отметить, что таблицы переходов описаны во многих книгах по структурам данных и алгоритмам. Принципы примерно одинаковы, но определения немного отличаются: </p><li> Определение интервала: как показано на рисунке, некоторые считают, что интервал равен 2, то есть количеству элементов между двумя элементами верхнего уровня, исключая два элемента верхнего уровня; некоторые думают, что это 3, то есть два элемента верхнего уровня Разница между элементами включает верхний элемент сзади, исключая верхний элемент спереди; некоторые думают, что это 4, то есть, за исключением элементов между двумя верхними элементами, оно включает как верхний элемент спереди, так и верхний элемент сзади. Lucene – второе принятое определение. </li><li> Определение уровня: Как показано на рисунке, некоторые люди считают, что исходный поверхностный слой цепи должен быть включен, и, считая с 1, общий уровень равен 3, то есть уровням 1, 2 и 3; некоторые люди считают, что исходный уровень цепочки должен быть включен. Слой связанного списка, считая с 0, является слоем 0, 1 и 2; некоторые думают, что исходный уровень связанного списка не должен быть включен, и, считая с 1, тогда это уровень 1, 2; некоторые считают, что слой связанного списка не следует включать, и начиная с 1. Начиная отсчет с 0, это уровень 0,1. Lucene принимает последнее определение. </li><p>По сравнению с последовательным поиском таблица переходов значительно повышает скорость поиска. Например, если вы хотите найти элемент 72, вам необходимо получить доступ в общей сложности к 10 элементам 2, 3, 7, 12, 23, 37, 39. , 44, 50 и 72. Используйте таблицу переходов. Наконец, пока мы сначала обращаемся к 50 на первом уровне и обнаруживаем, что 72 больше 50, но на первом уровне нет следующего узла, тогда получаем доступ к 94 на первом уровне. второй уровень и обнаружите, что 94 больше, чем 72, а затем получите доступ к 72 исходного связанного списка, чтобы найти элемент, в общей сложности просто получите доступ к 3 элементам. </p><p> Однако конкретная реализация Lucene отличается от теории. Конкретный формат будет объяснен подробно. </p><p> Для получения дополнительной информации обратитесь к официальной документации: <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Flucene.apache.org%2Fcore%2F2_9_4% 2Ffileformats.html " rel="nofollow noopener" style="color:#0052D9" target="_blank">http://lucene.apache.org/core/2_9_4/fileformats.html</a> </p><
2360215
None
Read more...
Обучение Lucene5.5 (2) — основные принципы полнотекстового поиска Lucene
<p> <strong>Предисловие</strong> </p><p> В последнем сообщении блога автор в основном понял, что делает Lucene, а затем написал hello world, чтобы улучшить свое понимание Lucene. Лично я считаю, что при изучении чего-то нового, начиная с демо-версии, вы можете повысить свой интерес к технологии, а затем постепенно проникнуть в ее принципы, и у вас возникнет ощущение, что темные тучи раздвигаются, и вы видите яркую луну. Конечно, некоторым людям нравится начинать с принципов, и это вопрос мнения. Подводя итог, с чего бы вы ни начали, вам всегда нужно знать все о новой технологии </p><p> <strong>Текст</strong> </p><p> <strong>Lucene — это эффективная библиотека полнотекстового поиска на основе Java. </strong> </p><p> Итак, прежде чем разобраться в Lucene, вам нужно потратить некоторое время на понимание полнотекстового поиска. </p><p> Так что же такое полнотекстовый поиск? Это начинается с данных в нашей жизни. </p><p> Данные в нашей жизни обычно делятся на два типа: <strong>Структурированные данные</strong> и <strong>Неструктурированные данные</strong>. </p><li> <strong>Структурированные данные:</strong> относятся к данным фиксированного формата или ограниченной длины, например базам данных, метаданным и т. д. </li><li> <strong>Неструктурированные данные:</strong> относятся к данным переменной длины или без фиксированного формата, например электронные письма, документы Word и т. д. </li><p> Конечно, в некоторых местах упоминается третий тип: полуструктурированные данные, такие как XML, HTML и т. д., которые при необходимости можно обрабатывать как структурированные данные, или же простой текст можно извлекать и обрабатывать как неструктурированные данные. . . </p><p> <strong>Неструктурированные данные также называются полнотекстовыми данными. </strong> </p><p>По классификации данных поиск также делится на два типа: </p><li> <strong>Поиск структурированных данных</strong>. Например, для поиска в базе данных используйте инструкции SQL. Другим примером является поиск метаданных, например использование поиска Windows для поиска имени файла, типа, времени изменения и т. д. </li><li> <strong>Поиск неструктурированных данных</strong>. Например, вы можете использовать поиск Windows для поиска содержимого файлов, команду grep в Linux, а также Google и Baidu для поиска больших объемов данных контента. </li><p> Существует два основных метода поиска неструктурированных данных, то есть полнотекстовых данных: </p><p> Одним из них является <strong>Метод последовательного сканирования:</strong> Так называемое последовательное сканирование. Например, если вы хотите найти файлы, содержащие определенную строку содержимого, вы будете просматривать каждый документ один за другим. Для каждого документа, просматривая от начала до конца, если этот документ содержит эту строку, то этот документ является файлом, который мы ищем, а затем просматриваем следующий файл, пока все файлы не будут проверены. Например, вы также можете искать содержимое файла с помощью поиска Windows, но это довольно медленно. Если у вас есть жесткий диск емкостью 80 ГБ и вы хотите найти на нем файл, содержащий определенную строку, возможно, вам не удастся сделать это, потратив несколько часов. Команда grep в Linux также работает таким же образом. Вам может показаться этот метод примитивным, но для файлов с небольшими объемами данных этот метод все же является наиболее прямым и удобным. Но для большого количества файлов этот метод очень медленный. </p><p> Некоторые люди могут сказать, что последовательное сканирование неструктурированных данных очень медленное, но поиск структурированных данных происходит относительно быстро (поскольку структурированные данные имеют определенную структуру и для его ускорения можно использовать определенные алгоритмы поиска), тогда давайте Разве недостаточно найти способ придать неструктурированным данным определенную структуру? </p><p>Эта идея очень естественна, но она составляет основную идею полнотекстового поиска, которая заключается в извлечении части информации из неструктурированных данных, реорганизации ее, придании ей определенной структуры, а затем определенная структура поиска данных, благодаря чему поиск происходит относительно быстро. </p><p> Эта часть информации, извлеченная из неструктурированных данных и затем реорганизованная, называется <strong>индексом</strong>. </p><p> Это утверждение относительно абстрактно. Его легко понять, приведя несколько примеров. Например, в словаре таблица пиньинь и таблица поиска радикальных слов словаря эквивалентны индексу словаря. Объяснение каждое слово неструктурировано.Если в словаре нет таблицы слогов или таблицы поиска радикальных слов.Чтобы найти слово в обширном словаре, можно только просмотреть его последовательно. Однако некоторая информация слова может быть извлечена для структурированной обработки.Например, произношение относительно структурировано, разделено на начальные согласные и конечные.Есть только несколько типов каждого, которые можно перечислить один за другим, поэтому берется произношение и расположены в определенном порядке.Каждый элемент Произношения указывают на страницу, где слово объяснено подробно. При поиске мы ищем произношение по структурированному пиньинь, а затем по номеру страницы, на который он указывает, мы можем найти наши неструктурированные данные — то есть объяснение слова. </p><p> <strong>Этот процесс сначала создания индекса, а затем поиска в нем называется полнотекстовым поиском. </strong> </p><p> Изображение ниже взято из «Lucene в действии», но оно не только описывает процесс поиска Lucene, но также описывает общий процесс полнотекстового поиска. </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/f61d618d35e6ce1e08f178d3290824d3.png"/><p> Полнотекстовый поиск обычно делится на два процесса: <strong>Индексирование</strong> и <strong>Поиск</strong>. </p><li> Создание индекса: процесс извлечения информации из всех структурированных и неструктурированных данных в реальном мире и создания индекса. </li><li> Индекс поиска: это процесс получения запроса пользователя, поиска по созданному индексу и последующего возврата результатов. </li><p> Итак, при полнотекстовом извлечении возникают три важные проблемы: </p><p> <strong>1. Что именно хранится в индексе? (Индекс)</strong> </p><p> <strong>2. Как создать индекс? (Индексирование)</strong> </p><p> <strong>3. Как искать по индексу? (Поиск)</strong> </p><p>Ниже мы последовательно изучим каждый вопрос. </p><p>Что именно нужно хранить в индексе? </p><p>Во-первых, давайте посмотрим, почему последовательное сканирование медленное: </p><p> На самом деле это вызвано несоответствием информации, которую мы хотим найти, и информации, хранящейся в неструктурированных данных. </p><p> Информация, хранящаяся в неструктурированных данных, заключается в том, какие строки содержит каждый файл, то есть известные файлы. Получить строки, то есть сопоставление файлов со строками, относительно легко. Информация, которую мы хотим найти, — это то, какие файлы содержат эту строку, то есть известную строку, и желаемый файл, который представляет собой сопоставление строки с файлом. Эти двое совершенно противоположны. Поэтому, если индекс всегда сможет сохранить сопоставление строк с файлами, скорость поиска значительно улучшится. </p><p> Поскольку преобразование строки в файл представляет собой обратный процесс преобразования файла в строку, индекс, в котором сохраняется эта информация, называется <strong>обратным индексом</strong>. </p><p> Информация, хранящаяся в обратном индексе, обычно следующая: </p><p>Предположим, в моей коллекции документов 100 документов. Для удобства пронумеруем документы от 1 до 100 и получим следующую структуру </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/947b6d01de63f27037ff492fc504aaab.jpg"/><p> Слева сохранена серия строк под названием <strong>словарь</strong>. </p><p> Каждая строка указывает на связанный список документов, содержащий эту строку. Этот связанный список документов называется <strong>инвертированным списком</strong> (списком проводок). </p><p> Благодаря индексу сохраненная информация согласуется с информацией, подлежащей поиску, что может значительно ускорить поиск. </p><p> Например, если мы хотим найти документы, содержащие как строку «lucene», так и строку «solr», нам нужно выполнить всего лишь следующие шаги: </p><p> 1. Получите список документов, содержащий строку «lucene». </p><p> 2. Получите список документов, содержащий строку «solr». </p><p> 3. Найдите файлы, содержащие «lucene» и «solr», объединив связанные списки. </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/8b529a3b29e5946fa3c1896903d9861a.jpg"/><p> Видя это, некоторые люди могут сказать, что полнотекстовый поиск действительно ускоряет поиск, но с добавлением процесса индексирования сумма этих двух показателей не обязательно будет намного быстрее, чем последовательное сканирование. Действительно, в процессе индексирования полнотекстовое извлечение не обязательно происходит быстрее, чем последовательное сканирование, особенно когда объем данных невелик. Создание индекса для большого объема данных также является очень медленным процессом. </p><p> Однако разница между ними все же есть. Последовательное сканирование требует сканирования каждый раз, а процесс создания индекса нужен только один раз, и он будет выполнен раз и навсегда. Каждый раз, когда вы выполняете поиск, вы не делаете этого. Не нужно проходить процесс создания индекса. Вам нужно только искать и создавать. Хороший индекс подойдет. </p><p> <strong>Это также одно из преимуществ полнотекстового поиска перед последовательным сканированием: индексируйте один раз, используйте много раз. </strong> </p><p> Процесс создания индекса для полнотекстового поиска обычно состоит из следующих этапов: </p><p> Чтобы облегчить объяснение процесса создания индекса, в качестве примеров используются два файла: </p><p> 文件一: Студентам должно быть разрешено гулять с друзьями, но не разрешено пить пиво. </p><p> Описание: Мой друг Джерри пошел в школу, чтобы навестить своих учеников, но нашел их пьяными, что запрещено. </p><p> <strong>Компонент сегментации слов (Tokenizer) будет выполнять следующие действия (этот процесс называется Tokenize): </strong> </p><p> <strong>1. Разделите документ на отдельные слова. </strong> </p><p> <strong>2. Удалите знаки препинания. </strong> </p><p> <strong>3. Удалите стоп-слова. </strong> </p><p>Так называемые стоп-слова являются одними из наиболее распространенных слов в языке. Поскольку они не имеют специального значения, в большинстве случаев их нельзя использовать в качестве ключевых слов для поиска. Поэтому такие слова будут удалены при создании индекса. И уменьшите размер индекса. </p><p> Стоп-слова на английском языке, такие как: «the», «a», «this» и т. д. </p><p> Для каждого компонента сегментации слов (Tokenizer) каждого языка существует набор стоп-слов. </p><p> <strong>Результат, полученный после Tokenizer, называется Token. </strong> </p><p> В нашем примере мы получаем следующие токены: </p><p> «Студенты», «разрешено», «кому», «своим», «друзьям», «разрешено», «пить», </p><p> «пиво», «мой», «друг», «Джерри», «ходил», «школа», «видеть», «его», «</p><p>студенты», «найдены», «их», «пьяны», «разрешено»。 </p><p> Компонент языковой обработки (лингвистический процессор) в основном выполняет некоторую языковую обработку полученных токенов. </p><p> <strong>Для английского языка компонент языковой обработки (лингвистический процессор) обычно выполняет следующие действия:</strong> </p><p> <strong>1. Перевести в нижний регистр (Lowercase). </strong> </p><p> <strong>2. Сократите слово до его корневой формы, например «автомобили» до «автомобиль» и т. д. Эта операция называется стеммингом. </strong> </p><p> <strong>3. Преобразуйте слова в корневые формы, например «ехал» в «ехать» и т. д. Эта операция называется: лемматизация. </strong> </p><p> <strong>Сходства и различия между стеммингом и лемматизацией:</strong> </p><li> Сходства: Стемминг и лемматизация преобразуют слова в корневые формы. </li><li> Эти два метода различны: <ul class="ul-level-1"><li> Стемминг использует метод «сокращения»: «автомобили» на «автомобиль», «вождение» на «вождение». </li><li>Лемматизация принимает метод «преобразования»: «ехал» в «ехал», «ехал» в «ехал». </li></ul></li><li> Стемминг использует метод «сокращения»: «автомобили» на «автомобиль», «вождение» на «водить машину». </li><li>Лемматизация принимает прием «преобразования»: «ехал» в «возил», «ехал» в «гонял». </li><li> Алгоритмы этих двух методов различны: <ul class="ul-level-1"><li> Стемминг в основном использует фиксированный алгоритм для такого сокращения, например удаление "s", удаление "ing" и добавление. «е», замените «ational» на «ate», замените «tional» на «tion». </li><li>Лемматизация в основном использует метод сохранения словаря для выполнения этого преобразования. Например, в словаре есть сопоставления «вождение» с «езда», «ехал» с «водить» и «есть, есть, есть» с «быть». При внесении изменений вам нужно только просмотреть словарь. </li></ul></li><li> Стемминг в основном использует фиксированный алгоритм для выполнения этого сокращения, например удаление «s», удаление «ing» и добавление «e», замену «ational» на «ate» и замену «tional» на «tion». </li><li> Лемматизация в основном использует метод сохранения некоторого словаря для выполнения этого преобразования. Например, в словаре есть сопоставления «вождение» с «езда», «ехал» с «водить» и «есть, есть, есть» с «быть». При внесении изменений вам нужно только просмотреть словарь. </li><li> Стеммирование и лемматизация не исключают друг друга, а пересекаются. Некоторые слова могут быть преобразованы одинаково, используя оба метода. </li><p> <strong>Результат лингвистического процессора называется термином. </strong> </p><p> В нашем примере после языковой обработки результирующие слова (Term) выглядят следующим образом: </p><p> «ученик», «разрешить», «идти», «их», «друг», «разрешить», «пить», </p><p> «пиво», «мой», «друг», «джерри», «иди», «школа», «видишь», «его», </p><p> «ученик», «найти», «их», «выпить», «разрешить».。 </p><p> Именно благодаря этапам обработки языка можно осуществлять поиск по диску, а также по диску. </p><p> <strong>Компонент индекса (индексатор) в основном выполняет следующие функции: </strong> </p><p> <strong>1. Создайте словарь, используя полученные слова (Term). </strong> </p><p> В нашем примере словарь выглядит так: </p><p>Срок</p><p>Срок</p><p>Идентификатор документа</p><p>Идентификатор документа</p><p>студент</p><p>студент</p><p>студент</p><p>студент</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>1</p><p>разрешить</p><p>разрешить</p><p>разрешить</p><p>разрешить</p><p>разрешить</p><p>разрешить</p><p>иди</p><p>иди</p><p>иди</p><p>иди</p><p>их</p><p>их</p><p>друг</p><p>друг</p><p>друг</p><p>друг</p><p>пей</p><p>пей</p><p>пей</p><p>пей</p><p>пиво</p><p>пиво</p><p>мой</p><p>мой</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>2</p><p>Джерри</p><p>Джерри</p><p>школа</p><p>школа</p><p>см.</p><p>см.</p><p>его</p><p>его</p><p>найти</p><p>найти</p><p>они</p><p>они</p><p> <strong>2. Отсортируйте словарь по алфавиту. </strong> </p><p> <strong>3. Объедините одинаковые термины в список публикации документов. </strong> </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/15d2699360ab61cb2014eeb142d13728.jpg"/><p> В этой таблице есть несколько определений: </p><li> Частота документа — это частота появления документа, указывающая, сколько документов всего содержит это слово (термин). </li><li> Частота — это частота слов, которая означает, сколько слов (Term) содержится в этом файле. </li><p> Итак, для слова (Term) «разрешить» существует всего два документа, содержащих это слово (Term), поэтому список документов после слова (Term) состоит всего из двух элементов, первый элемент представляет собой документ, содержащий «разрешить» Первый документ — это документ № 1. В этом документе «разрешить» встречается дважды. Второй элемент представляет второй документ, содержащий «разрешить», то есть документ № 2. В этом документе «разрешить» появляется 1 раз. </p><p> На данный момент индекс создан, и с помощью него мы можем быстро найти нужные документы. </p><p> И в процессе мы были удивлены, обнаружив, что поиск по словам «вождение», «вождение», «ехал» и «вождение» также можно выполнять. Потому что в нашем индексе слова "вождение", "ехал" и "вождение" пройдут языковую обработку и станут словом "вождение". Если при поиске вы введете "вождение", введенный оператор запроса также пройдет через нашу обработку. Перейти на третьем шаге изменить запрос «диск», чтобы можно было найти нужный документ. </p><p> На этом этапе кажется, что мы можем заявить: «Мы нашли документ, который искали». </p><p> Однако на этом дело еще не закончилось: поиск — это лишь один из аспектов полнотекстового поиска. Не так ли? Если только один или десять документов содержат нашу строку запроса, мы действительно ее нашли. Но что, если результатов тысяча или даже тысячи? Какой файл вам нужен больше всего? </p><p> Откройте Google, например, вы хотите найти работу в Microsoft, поэтому вы вводите «Вакансия Microsoft», но обнаруживаете, что в общей сложности возвращается 22 600 000 результатов. Это такое большое число. Внезапно неспособность найти его становится проблемой, и найти слишком много тоже становится проблемой. Как при таком большом количестве результатов поставить наиболее релевантные на первое место? </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/4d56a757187f7bbb423f4d055d8a48b7.jpg"/><p>Конечно, Google отлично справляется со своей задачей, вы можете сразу найти работу в Microsoft. Представьте себе, как было бы ужасно, если бы первые несколько слов были такими: «Microsoft хорошо работает в индустрии программного обеспечения…». </p><p> Как найти наиболее релевантный запрос среди тысяч результатов поиска, таких как Google? </p><p>Как определить релевантность искомых документов и формулировок запроса? </p><p> Возвращаемся к нашему третьему вопросу: как осуществлять поиск по индексу? </p><p> Поиск в основном разделен на следующие этапы: </p><p> Операторы запроса, как и наши обычные языки, также имеют определенный синтаксис. </p><p> Разные операторы запроса имеют разный синтаксис. Например, операторы SQL имеют определенный синтаксис. </p><p> Синтаксис оператора запроса зависит от реализации системы полнотекстового поиска. Самые основные из них: И, ИЛИ, НЕ и т.д. </p><p> Например, пользователь вводит оператор: lucene И узнал НЕ Hadoop. </p><p> Указывает, что пользователь ищет документ, который включает Lucene и Learned, но не включает Hadoop. </p><p> Поскольку операторы запроса содержат грамматику, также требуются синтаксический анализ, синтаксический анализ и языковая обработка. </p><p> <strong>1. Лексический анализ в основном используется для идентификации слов и ключевых слов. </strong> </p><p> Как и в приведенном выше примере, после лексического анализа слова включают Lucene, Learne и Hadoop, а ключевые слова включают AND и NOT. </p><p> Если при лексическом анализе будет обнаружено недопустимое ключевое слово, произойдет ошибка. Например, при изучении lucene AMD, в котором AND написано с ошибкой, AMD участвует в запросе как обычное слово. </p><p> <strong>2. Синтаксический анализ в основном формирует синтаксическое дерево на основе правил синтаксиса оператора запроса. </strong> </p><p> Если будет обнаружено, что оператор запроса не соответствует правилам синтаксиса, будет сообщено об ошибке. Если lucene НЕ И узнал, произойдет ошибка. </p><p> Как и в приведенном выше примере, синтаксическое дерево, сформированное lucene И изученным NOT Hadoop, выглядит следующим образом: </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/ec17b18703392b7911c6036ec157549d.jpg"/><p> <strong>3. Языковая обработка практически такая же, как и в процессе индексирования. </strong> </p><p> Например, выученное становится выученным и т. д. </p><p> После второго шага мы получаем синтаксическое дерево, обработанное языком. </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/11ebaa4f2b753774b0d2f42cbe98a648.jpg"/><p> Этот шаг разделен на несколько небольших шагов: </p><li> Сначала в таблице обратного индекса найдите связанные списки документов, содержащие lucene, Learn и Hadoop. </li><li> Во-вторых, объедините связанные списки, содержащие lucene, и научитесь получать связанный список документов, содержащий как lucene, так и Learn. </li><li> Затем выполните операцию различия между этим связанным списком и связанным списком документов Hadoop, чтобы удалить документы, содержащие Hadoop, тем самым получив связанный список документов, который содержит как Lucene, так и Learn, но не содержит Hadoop. </li><li> Этот список документов — это тот документ, который мы ищем. </li><p> Хотя на предыдущем шаге мы получили нужный документ, результаты запроса следует отсортировать в соответствии с их релевантностью оператору запроса, при этом более релевантные будут располагаться выше. </p><p> Как рассчитать корреляцию между документами и операторами запроса? </p><p> Лучше рассматривать оператор запроса как короткий документ и оценивать релевантность (релевантность) между документами. Те, у кого высокие баллы и хорошая корреляция, должны быть ранжированы первыми. </p><p> Так как же оценить связь между документами? </p><p> <strong>Это непростая задача. Во-первых, давайте взглянем на оценку отношений между людьми. </strong> </p><p> <strong>Прежде всего</strong> При взгляде на человека часто учитывается множество <strong>элементов</strong>, таких как личность, убеждения, хобби, одежда, рост, упитанность и т. д. </p><p> <strong>Во-вторых</strong> Что касается взаимоотношений между людьми, то <strong>разные элементы имеют разное значение</strong>. Личность, убеждения и хобби могут иметь большее значение. Одежда, рост, полнота и худоба могут иметь большее значение. Это не так важно, поэтому люди с одинаковыми или похожими характерами, убеждениями и хобби с большей вероятностью станут хорошими друзьями. Однако люди с разной одеждой, ростом, весом и худобой также могут стать хорошими друзьями. </p><p> Поэтому, чтобы судить об отношениях между людьми, <strong>прежде всего, мы должны выяснить, какие элементы наиболее важны для отношений между людьми</strong>, такие как личность, убеждения и хобби. <strong>Во-вторых, нам нужно оценить взаимоотношения между этими элементами двух людей</strong>, например, у одного человека жизнерадостный характер, а у другого экстраверт, один человек верит в буддизм, а другой верит в Бога, один любит играть в баскетбол, а другой любит играть в футбол. Мы обнаружили, что эти два человека очень позитивны с точки зрения личности, оба добры с точки зрения убеждений и оба любят спорт с точки зрения хобби, поэтому отношения между двумя людьми должны быть очень хорошими. </p><p> <strong>Давайте еще раз посмотрим на отношения между компаниями. </strong> </p><p> <strong>Прежде всего</strong>Посмотрите на компанию. Она состоит из множества людей, таких как генеральный директор, менеджер, технический директор, рядовые сотрудники, охранники, швейцары и т. д. </p><p> <strong>Во-вторых, что касается отношений между компаниями, разные люди имеют разное значение</strong>. Генеральные менеджеры, менеджеры и технические директора могут быть более важными, а рядовые сотрудники, охранники и швейцары - менее важными. важно немного. Следовательно, если отношения между генеральными менеджерами, менеджерами и техническими директорами двух компаний относительно хорошие, у этих двух компаний, скорее всего, будут относительно хорошие отношения. Однако даже если у рядового сотрудника возникает кровная месть с рядовым сотрудником другой компании, это может не повлиять на отношения между двумя компаниями. </p><p> Поэтому, чтобы оценить отношения между компаниями, <strong>в первую очередь выясните, кто наиболее важен для отношений между компаниями</strong>, например генеральные менеджеры, менеджеры и технические директора. <strong>Во-вторых, чтобы судить об отношениях между этими людьми</strong>, лучше учитывать, что генеральные менеджеры двух компаний когда-то были одноклассниками, менеджеры – односельчанами, а технологи – когда-то партнёрами по предпринимательству. Мы обнаружили, что между генеральными менеджерами, менеджерами и техническими директорами двух компаний очень хорошие отношения, поэтому отношения между двумя компаниями должны быть очень хорошими. </p><p> Проанализировав две связи, давайте посмотрим, <strong>как определить связь между документами</strong>. </p><p> <strong>Прежде всего, документ состоит из множества слов (терминов)</strong>, таких как поиск, lucene, полнотекстовый, это, а, что и т. д. </p><p> <strong>Во-вторых, что касается взаимоотношений между документами, разные термины имеют разное значение</strong>. Например, для этого документа относительно важны поиск, Lucene и полнотекстовый режим, а this, a и What может быть относительно важным.Менее важным. Таким образом, если два документа содержат поиск, Lucene и полнотекстовый режим, корреляция между двумя документами лучше. Однако, даже если один документ содержит это, а, что, а другой документ не содержит это, а, что, он будет не влияет на корреляцию между двумя документами. </p><p> Поэтому, чтобы определить связь между документами, сначала выясните, какие слова (Term) наиболее важны для связи между документами, например, поиск, Lucene, полнотекстовый. Затем определите связь между этими словами (Термин). </p><p> <strong>Процесс определения важности термина для документа называется процессом расчета веса термина. </strong> </p><p> Существует два параметра для расчета веса термина: первый — это термин, а второй — документ. </p><p>Вес термина (Term Weight) указывает на важность этого термина (Term) в данном документе. Чем важнее термин (Term), тем больше вес (Term Weight), поэтому рассчитывается корреляция между документами. Генерал-лейтенант будет играть большую роль. </p><p> <strong>В процессе определения взаимосвязи между терминами для получения релевантности документа применяется алгоритм, называемый векторной пространственной моделью. </strong> </p><p> Давайте подробно разберем эти два процесса: </p><p> На важность термина в документе влияют два основных фактора: </p><li> Частота термина (tf): сколько раз этот термин встречается в этом документе. Чем больше tf, тем это важнее. </li><li> Частота документов (df): то есть, сколько документов содержат раз Term. Чем больше df, тем менее это важно. </li><p> Легко ли это понять? Чем больше раз термин встречается в документе, тем важнее он для документа. Например, если слово «поиск» встречается в этом документе много раз, это означает, что этот документ в основном посвящен этому аспекту. Да. Однако, если в английском документе это встречается больше раз, означает ли это, что это более важно? Нет, это корректируется вторым фактором.Второй фактор показывает, что чем больше документов, содержащих это слово (Термин), то это означает, что это слово (Термин) слишком распространено, чтобы различать эти документы, и, следовательно, тем оно важнее. Низкий. </p><p>Это тоже технология, которую изучают наши программисты.Для самих программистов, чем глубже они владеют этой технологией, тем лучше (чем глубже освоение, тем больше времени тратится на просмотр, тем больше tf), и тем легче это найти работу, конкурентоспособную. Однако для всех программистов, чем меньше людей знают эту технологию, тем лучше (чем меньше людей ее знают, тем меньше df) и тем более конкурентоспособными они будут при поиске работы. Вот почему ценность человека заключается в его незаменимости. </p><p> Теперь, когда истина ясна, давайте взглянем на формулу: </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/11b352f81a11a9c0e131396f258fc594.png"/><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/bc7d7b4201a5c0a81f9e401d432b1bad.png"/><p> Это просто типичная реализация формулы расчета веса термина. Люди, реализующие системы полнотекстового поиска, будут иметь свои собственные реализации, и Lucene немного отличается от них. </p><p>Мы рассматриваем документ как серию слов (Термин). Каждое слово (Термин) имеет вес (Термин вес). Различные слова (Термин) влияют на оценку релевантности документа в соответствии с их весом в документе. Вычислить. </p><p> Поэтому мы рассматриваем вес всех терминов в этом документе как вектор. </p><p> Документ = {term1, term2, …… ,term N} </p><p> Вектор документа = {вес1, вес2, ……, вес N} </p><p> Аналогично, мы рассматриваем оператор запроса как простой документ, также представленный вектором. </p><p> Запрос = {терм1, термин 2, …… , термин N} </p><p> Вектор запроса = {вес1, вес2, …… , вес N} </p><p> Мы помещаем все искомые векторы документов и векторы запросов в N-мерное пространство, и каждое слово (термин) имеет одно измерение. </p><p>Как показано на рисунке: </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/b3f307ade94439313d7e9a817f9bd892.jpg"/><p>Мы считаем, что чем меньше угол между двумя векторами, тем больше корреляция. </p><p> Таким образом, мы вычисляем значение косинуса включенного угла как показатель корреляции. Чем меньше включенный угол, тем больше значение косинуса. Чем выше показатель, тем выше корреляция. </p><p> Некоторые люди могут спросить, что операторы запроса обычно очень короткие и содержат мало терминов (Term), поэтому размерность вектора запроса очень мала, в то время как документ очень длинный и содержит много терминов (Term), а документ вектор Число измерений велико. Почему размеры обоих измерений на вашем изображении оба N? </p><p> Здесь, поскольку оно должно быть помещено в одно и то же векторное пространство, естественные размеры одинаковы. Если они разные, берется объединение двух. Если определенное слово (термин) не включено, вес (Вес термина) равен 0. </p><p> Формула оценки релевантности следующая: </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/be683027f390e94be80ea31f0b9ee5ac.png"/><p> Например, оператор запроса содержит 11 терминов, и всего выполняется поиск в трех документах. Их соответствующие веса (вес термина) показаны в таблице ниже. </p><p></p><p>t1</p><p>t2</p><p>t3</p><p>t4</p><p>t5</p><p>t6</p><p>t7</p><p>t8</p><p>t9</p><p>t10</p><p>t11</p><p>Д1</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>0</p><p>.477</p><p>.477</p><p>.477</p><p>.477</p><p>.176</p><p>.176</p><p>.176</p><p>.176</p><p>.176</p><p>.176</p><p>.176</p><p>.176</p><p>.176</p><p>.176</p><p>Д2</p><p>.954</p><p>D3</p><p>Вопрос</p><p> Таким образом рассчитываются оценки корреляции трех документов и оператора запроса: </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/19a3d96901b68ebc5cf1e70e0857fe10.png"/><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/176f9f87424f7857e2f345cc71e702ff.png"/><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/00c70e66b3daa56ee6a4e795d2ccdf5d.png"/><p> Таким образом, второй документ имеет самую высокую корреляцию и возвращается первым, за ним следует первый документ и, наконец, третий документ. </p><p> На этом этапе мы можем найти документ, который нам больше всего нужен. </p><p> Сказав это, мы на самом деле не вошли в Lucene, а только в базовую теорию технологии информационного поиска (Информационный поиск). Однако, когда мы посмотрим на Lucene, мы обнаружим, что Lucene представляет собой введение в эту базовую теорию. a основная практика. Поэтому в будущих статьях, анализирующих Lucene, вы часто увидите применение вышеизложенной теории в Lucene. </p><p> Прежде чем войти в Lucene, вот краткое изложение описанного выше процесса создания индекса и поиска, как показано на рисунке: </p><p> Это изображение относится к <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.lucene.com.cn%2Fabout.htm" rel="nofollow noopener " style="color:#0052D9" target="_blank">http://www.lucene.com.cn/about.htm</a> статья "Поисковая система полнотекстового поиска Lucene с открытым исходным кодом" </p><img alt="Lucene全文检索的基本原理" src="https://developer.qcloudimg.com/http-save/yehe-1651485/2ca09dcf2cc4c52364aa20e3815c3623.jpg"/><p> <strong>1. Процесс индексирования: </strong> </p><p> <strong>1) Имеется ряд проиндексированных документов</strong> </p><p> <strong>2) Индексированные файлы подвергаются грамматическому анализу и языковой обработке для формирования ряда слов (Term). </strong> </p><p> <strong>3) Создайте словарь и таблицу обратного индекса посредством создания индекса. </strong> </p><p> <strong>4) Запишите индекс на жесткий диск через хранилище индексов. </strong> </p><p> <strong>2. Процесс поиска: </strong> </p><p> <strong>a) Пользователь вводит оператор запроса. </strong> </p><p> <strong>b) После грамматического анализа и языкового анализа оператора запроса получается серия слов (Термин). </strong> </p><p> <strong>c) Получите дерево запроса посредством синтаксического анализа. </strong> </p><p> <strong>d) Считайте индекс в память через хранилище индексов. </strong> </p><p> <strong>e) Используйте дерево запросов для поиска по индексу, чтобы получить связанный список документов для каждого слова (термина), выполнить пересечение и различие в связанном списке документов и получить результирующий документ. </strong> </p><p> <strong>f) Отсортируйте документы результатов поиска в соответствии с их релевантностью запросу. </strong> </p><p> <strong>g) Возврат результатов запроса пользователю. </strong> </p><p> Цитирование: <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.open-open.com%2Flib%2Fview%2Fopen1348219378948.html%23_label3" rel ="nofollow noopener" style="color:#0052D9" target="_blank">Основные принципы полнотекстового поиска Lucene</a> </p><p> Чтобы узнать больше о принципах, перейдите по адресу: <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.open-open.com%2Flib% 2Fview%2Fopen1410492056742 .html" rel="nofollow noopener" style="color:#0052D9" target="_blank">http://www.open-open.com/lib/view/open1410492056742.html</a> < /п><
2360214
None
Read more...
Обучение Lucene5.5 (1) – первое знакомство с полнотекстовой поисковой системой Lucene
<p> <strong>Познакомьтесь с Lucene</strong> </p><p> Ниже приводится описание Lucene в энциклопедии: </p><p> Lucene — это подпроект команды проекта Apache Software Foundation 4 в Джакарте. Это набор инструментов для полнотекстовой поисковой системы с открытым исходным кодом, но это не полнотекстовая поисковая система, а полнотекстовая поисковая система. Архитектура, которая обеспечивает. Он имеет полный механизм запросов и индексирования, а также часть механизма анализа текста (два западных языка, английский и немецкий). Цель Lucene — предоставить разработчикам программного обеспечения простой и удобный в использовании набор инструментов, позволяющий легко реализовать функцию полнотекстового поиска в целевой системе или построить на ее основе полноценную систему полнотекстового поиска. Lucene — это набор библиотек с открытым исходным кодом для полнотекстового поиска и поиска, поддерживаемый и предоставляемый Apache Software Foundation. Lucene предоставляет простой, но мощный интерфейс прикладного программирования, который может выполнять полнотекстовое индексирование и поиск. Lucene — это зрелый бесплатный инструмент с открытым исходным кодом в среде разработки Java. Сама по себе Lucene в настоящее время и в последние годы является самой популярной бесплатной библиотекой поиска информации Java. Часто упоминаются библиотеки информационного поиска, и хотя они связаны с поисковыми системами, их не следует путать с поисковыми системами. </p><p> <strong>Выдающиеся преимущества Lucene</strong> </p><p> Как система полнотекстового поиска Lucene имеет следующие выдающиеся преимущества: (1) Формат индексного файла не зависит от платформы приложения. Lucene определяет набор форматов 8-битных индексных файлов, чтобы совместимые системы или приложения на разных платформах могли совместно использовать созданные индексные файлы. (2) На основе инвертированного индекса традиционных полнотекстовых поисковых систем реализовано блочное индексирование, которое позволяет создавать небольшие файловые индексы для новых файлов и повышать скорость индексирования. Тогда за счет слияния с исходным индексом достигается цель оптимизации. (3) Превосходная объектно-ориентированная архитектура системы облегчает изучение расширений Lucene и облегчает расширение новых функций. (4) Разработан интерфейс анализа текста, который не зависит от языка и формата файла. Индексатор завершает создание индексных файлов, принимая поток токенов. Пользователям необходимо только реализовать интерфейс анализа текста для расширения новых языков и форматов файлов. . (5) По умолчанию реализован набор мощных механизмов запросов. Пользователям не нужно самостоятельно писать код, чтобы система могла получить мощные возможности запросов. Реализация запросов Lucene реализует логические операции и нечеткие запросы (нечеткий поиск [11]) с помощью default., групповой запрос и т. д. По сравнению с существующими коммерческими системами полнотекстового поиска Lucene также имеет значительные преимущества. Прежде всего, метод распространения исходного кода разработки (соответствующий лицензии на программное обеспечение Apache [12]), на основе которого программисты могут не только в полной мере использовать мощные функции, предоставляемые Lucene, но и изучить систему полнотекстового поиска. Технология производства подробно и подробно И практика объектно-ориентированного программирования, а затем на основе этой основы мы можем написать лучшую систему полнотекстового поиска, которая больше подходит для текущих приложений в соответствии с реальной ситуацией в приложении. На данный момент коммерческое программное обеспечение гораздо менее гибкое, чем Lucene. Во-вторых, Lucene унаследовала преимущества последовательной превосходной архитектуры с открытым исходным кодом и разработала разумную и хорошо масштабируемую объектно-ориентированную архитектуру.Программисты могут расширять различные функции на основе Lucene, такие как расширение возможностей обработки на китайском языке, расширение для обработки текстовых форматов. таких как HTML, PDF [13] и т. д., написание этих расширенных функций не только несложно, но и поскольку Lucene соответствующим образом и разумно абстрагирует системное оборудование программно, расширенные функции также можно легко расширить за счет возможностей платформы. Наконец, после перехода в Apache Software Foundation с помощью сетевой платформы Apache Software Foundation программисты могут легко общаться с разработчиками и другими программистами, способствовать совместному использованию ресурсов и даже напрямую получать полностью написанные расширенные функции. Наконец, хотя Lucene написан на языке Java, программисты из сообщества открытого исходного кода неустанно работают над его реализацией с использованием различных традиционных языков (таких как .net framework [14]). , Lucene. Он может работать на различных платформах, и системные администраторы могут сделать разумный выбор в зависимости от языка, подходящего для текущей платформы. <strong>Подготовка перед началом работы</strong> </p><p> Понимание некоторых понятий ключевых слов: </p><p> <strong>Документ</strong> ?? Документ используется для описания документа. Документ здесь может относиться к HTML-странице, электронному письму или текстовому файлу. Объект Document состоит из нескольких объектов Field. Вы можете рассматривать объект «Документ» как запись в базе данных, а каждый объект «Поле» — это поле записи. ? <strong>Поле </strong>? Объекты Field используются для описания определенного атрибута документа. Например, заголовок и содержимое электронного письма можно описать с помощью двух объектов Field. ? <strong>Анализатор ??</strong> Прежде чем документ будет проиндексирован, его содержимое сначала необходимо сегментировать, и эту часть работы выполняет анализатор. Класс Анализатор — это абстрактный класс, имеющий несколько реализаций. Выберите подходящий анализатор для разных языков и потребностей приложений. Анализатор передает сегментированное по словам содержимое в IndexWriter для построения индекса. ? <strong>IndexWriter ?</strong>? IndexWriter — это базовый класс, используемый Lucene для создания индексов. Его функция — добавлять объекты Document в индекс один за другим. ? <strong>Каталог ??</strong> Этот класс представляет место хранения индекса Lucene. Это абстрактный класс, который в настоящее время имеет две реализации. Первая — FSDirectory, которая представляет местоположение индекса, хранящегося в файловой системе. Второй — RAMDirectory, который представляет расположение индекса, хранящегося в памяти. ? <strong>Запрос?</strong> Это абстрактный класс, который имеет несколько реализаций, таких как TermQuery, BooleanQuery и PrefixQuery.Цель этого класса — инкапсулировать строку запроса, введенную пользователем, в запрос, который может распознать Lucene. ? <strong>IndexSearcher ??</strong> IndexSearcher используется для поиска по установленному индексу. Он может открывать индекс только в режиме только для чтения, поэтому с индексом могут работать несколько экземпляров IndexSearcher. <strong>Хиты?</strong> Обращения используются для сохранения результатов поиска. ?? ? </p><p> <strong>Мое простое понимание</strong> Использование Lucene разделено на несколько этапов, каждый из которых сосредоточен на индексировании: 1. Напишите индекс IndexWriter 2. Чтение индекса IndexReader 3. Поиск по индексу IndexSearcher 4. Инкапсулируйте условия запроса, подумайте о sql для написания базы данных? QueryParser 5. Запросите найденный индекс, чтобы получить набор результатов TopDocs. Можете ли вы получить коллекцию документов? ? ??? ??? </p><р> ? ? ? ? ? ? </p><p> <strong>Официальное введение, непосредственное начало кода????????????????????????????????????</strong> </п ><p> Индекс записи: </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">package com.kl.luceneDemo; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.store.RAMDirectory; import java.io.File; import java.io.FileReader; import java.nio.file.Paths; /** * @author kl by 2016/3/14 * @boke www.kailing.pub */ public class Indexer { public IndexWriter writer; /** * 实例化写索引 */ public Indexer(String indexDir)throws Exception{ Analyzer analyzer=new StandardAnalyzer();//分词器 IndexWriterConfig writerConfig=new IndexWriterConfig(analyzer);//写索引配置 //Directory ramDirectory= new RAMDirectory();//索引写的内存 Directory directory= FSDirectory.open(Paths.get(indexDir));//索引存储磁盘位置 writer=new IndexWriter(directory,writerConfig);//实例化一个写索引 } /** * 关闭写索引 * @throws Exception */ public void close()throws Exception{ writer.close(); } /** * 添加指定目录的所有文件的索引 * @param dataDir * @return * @throws Exception */ public int index(String dataDir)throws Exception{ File[] files=new File(dataDir).listFiles();//得到指定目录的文档数组 for(File file:files){ indexFile(file); } return writer.numDocs(); } public void indexFile(File file)throws Exception{ System.out.println("索引文件:"+file.getCanonicalPath());//打印索引到的文件路径信息 Document document=getDocument(file);//得到一个文档信息,相对一个表记录 writer.addDocument(document);//写入到索引,相当于插入一个表记录 } /** * 返回一个文档记录 * @param file * @return * @throws Exception */ public Document getDocument(File file)throws Exception{ Document document=new Document();//实例化一个文档 document.add(new TextField("context",new FileReader(file)));//添加一个文档信息,相当于一个数据库表字段 document.add(new TextField("fileName",file.getName(), Field.Store.YES));//添加文档的名字属性 document.add(new TextField("filePath",file.getCanonicalPath(),Field.Store.YES));//添加文档的路径属性 return document; } public static void main(String []ages){ String indexDir="E:\\LuceneIndex"; String dataDir="E:\\LuceneTestData"; Indexer indexer=null; int indexSum=0; try { indexer=new Indexer(indexDir); indexSum= indexer.index(dataDir); System.out.printf("完成"+indexSum+"个文件的索引"); }catch (Exception e){ e.printStackTrace(); }finally { try { indexer.close(); }catch (Exception e){ e.printStackTrace(); } } } }</code></pre><p>Читать индекс </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">package com.kl.luceneDemo; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import java.nio.file.Paths; /** * @author kl by 2016/3/14 * @boke www.kailing.pub */ public class Searcher { public static void search(String indexDir,String q)throws Exception{ Directory dir= FSDirectory.open(Paths.get(indexDir));//索引地址 IndexReader reader= DirectoryReader.open(dir);//读索引 IndexSearcher is=new IndexSearcher(reader); Analyzer analyzer=new StandardAnalyzer(); // 标准分词器 QueryParser parser=new QueryParser("context", analyzer);//指定查询Document的某个属性 Query query=parser.parse(q);//指定查询索引内容,对应某个分词 TopDocs hits=is.search(query, 10);//执行搜索 System.out.println("匹配 "+q+"查询到"+hits.totalHits+"个记录"); for(ScoreDoc scoreDoc:hits.scoreDocs){ Document doc=is.doc(scoreDoc.doc); System.out.println(doc.get("fileName"));//打印Document的fileName属性 } reader.close(); } public static void main(String[] args) { String indexDir="E:\\LuceneIndex"; String q="Muir"; try { search(indexDir,q); } catch (Exception e) { e.printStackTrace(); } } }</code></pre><p> Следующие изображения представляют собой мой файловый каталог и индексный файл, созданный Lucene </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-060a8201.png"/><p> <strong>ps: блоггер использует последнюю версию Lucene 5.5.0. Методы создания экземпляров связанных объектов могут отличаться в каждой версии. Подробную информацию можно найти в официальных инструкциях</strong></p ><
2360213
None
Read more...
Развертывание платформы управления сервисами Dubbo
<p><strong>Подготовка</strong></p><p>Сначала загрузите код даббо, адрес кода: <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Falibaba%2Fdubbo" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/<em style="font-style:italic">alibaba</em>/dubbo</a></p ><p>Затем проверьте, нужно ли изменить информацию о конфигурации. Файл конфигурации находится в папке <em style="font-style:italic">WEB</em>-INF в модуле dubbo-admin проекта. , как показано ниже</ p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-e9c8085e.png"/><p><strong>Упаковка</strong></p><p>Как показано ниже, пропустите тестовые примеры при упаковке, а затем упакуйте родительский pom, ps: я использую IDEA</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-7674a038.png"/><p>После завершения упаковки вы сможете найти упакованный военный пакет в разделе dubbo-admin\target проекта</p><p><strong>Развертывание</strong></p><p>Бросьте пакет war в контейнер сервлетов (tomcat) и запустите проект. Если при доступе вы видите следующую страницу входа, это означает, что развертывание прошло успешно</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-4eaa7fb9.png"/><p>После входа в систему с использованием root по умолчанию: root появится следующий интерфейс</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-7c993d32.png"/><p>Поздравляем с успехом</p><
2360212
None
Read more...
Используйте атрибут userAgent, чтобы определить, является ли терминал доступа ПК или мобильным терминалом
<p> <strong>Описание (понять требования)</strong> </p><p> Требование состоит в том, чтобы div не отображался на стороне ПК, но отображался на стороне мобильного устройства. Идея состоит в том, чтобы определить терминал доступа </p><p> ps: автор использовал здесь<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fangularjs.cn%2F" rel="nofollow noopener" style=" color:#0052D9" target="_blank">angular.js</a>, но это не важно, просто небольшая реклама</p><p> <strong>Знакомьтесь с userAgent</strong> </p><p> Атрибут userAgent используется здесь для удовлетворения наших потребностей. Сначала давайте познакомимся с атрибутом userAgent: </p><p> Атрибут userAgent — это строка, доступная только для чтения, которая объявляет значение заголовка User-Agent, который браузер использует для HTTP-запросов. Вообще говоря, он формируется путем добавления косой черты и значения navigator.appVersion после значения navigator.appCodeName. Например: Mozilla/4.0 (совместимый; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322). Дополнительную информацию об агенте пользователя браузера можно найти по адресу <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fmy.oschina.net%2Fsub%2Fblog%2F203139" rel= "nofollow noopener" style="color:#0052D9" target="_blank">http://my.oschina.net/sub/blog/203139</a> </p><p> <strong>Реализация</strong> </p><p>Зная приведенную выше информацию, мы можем определить наш терминал доступа.Код реализован следующим образом</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">angular.module('webappApp').controller('MainCtrl', function ($scope) { var browser={ versions:function(){ var u = navigator.userAgent; console.log(navigator);//打印navigator对象,可以看到更多浏览器的信息 return {//移动终端浏览器版本信息 trident: u.indexOf('Trident') > -1, //IE内核 presto: u.indexOf('Presto') > -1, //opera内核 webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核 mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器 iPad: u.indexOf('iPad') > -1, //是否iPad webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 }; }(), } if(browser.versions.mobile || browser.versions.ios || browser.versions.android || browser.versions.iPhone || browser.versions.iPad){ alert(123);//这里写你的具体业务逻辑 } });</code></pre><
2360211
None
Read more...
Использование клиента службы Disconf
<p> <strong>ps:Поскольку я редактировал его один раз позже, большая часть данных была потеряна из-за редактора, поэтому следующее очень запутано.Есть ли какая-либо информация, но это не имеет значения.Я настроил сервис difconf и использованные примеры. Он был загружен в кодирование. Вы можете скачать его и использовать напрямую (включая difconf, redis, Zookeeper-3.3.6, nginx-1.9.12, apache-tomcat-7.0.68) и другие среды и демонстрации</strong> </strong> p><p> <strong>地址:</strong><a class="" href="https://coding.net/u/kailingchen/p/disconfDemo/git?from_column=20421&from=20421" style="color: #0052D9" target="_blank"><strong>https://coding.net/u/kailingchen/p/disconfDemo/git</strong></a> </p><p> <strong>Описание</strong> </p><p>Сервис disconf разработан на основе Spring.Предполагается, что ваш проект использует среду Spring и собран с использованием maven</p><p> <strong>Подготовка</strong> </p><p> Добавьте следующие зависимости в файл pom.xml вашего проекта </p><p> <strong>Конфигурация</strong> </p><p> 1. Во-первых, вам необходимо настроить bean-компонент disconfClient, в основном для настройки пути сканирования аннотаций Spring. Наконец, не забудьте загрузить файл конфигурации bean-компонента </p><р> 2. Настройте disconf.properties </p><p> # Использовать ли файлы удаленной конфигурации # true (по умолчанию) получит конфигурацию с удаленного устройства, false получит локальную конфигурацию напрямую. disconf.enable.remote.conf=истина # Настраиваем HOST сервера через запятую 127.0.0.1:8000, это обязательно, остальные по желанию disconf.conf_server_host=localhost:8081 # Версия, используйте формат X_X_X_X disconf.version=1_0_0_0 # Приложение, пожалуйста, используйте формат названия продукта_линии_услуги. disconf.app=disconf_demo # среда disconf.env=rd #отлаживать #debug=истина # Игнорировать, какие распределенные конфигурации разделены запятыми игнорировать= # Получить время повтора удаленной настройки, по умолчанию — 3 раза disconf.conf_server_url_retry_times=1 # Получите время сна удаленной конфигурации при повторной попытке, значение по умолчанию — 5 секунд disconf.conf_server_url_retry_sleep_секунды=1 disconf.user_define_download_dir=./ 3. Настройте свою конфигурацию </p><p>@Service @Scope("Одиночка") @DisconfFile(filename = "myTestConifg.properties")//Это имя файла вашего удаленного сервера. общественный класс MyConfig { частная статическая строка imageCdn; @DisconfFileItem(name="IMAGECDN")//Это имя является значением ключа, которое вы настроили. общественная статическая строка getImageCdn() { вернуть изображениеCdn; } public static void setImageCdn(String imageCdn) { MyConfig.imageCdn = imageCdn; } } </p><p> <strong>Использовать</strong> </p><p> @Autowired</p><p> Private MyConfig myConfig; </p><
2360210
None
Read more...
В конечном итоге согласованные распределенные транзакции, стратегии обработки и решения для нештатных ситуаций и сценариев с высоким параллелизмом
<p>Рекомендуется подписаться, поставить лайк и собрать перед прочтением. </p><img src="https://developer.qcloudimg.com/http-save/yehe-admin/f0070e113736ed4588e4496819bd0619.png"/><li><strong>Попробуйте еще раз:</strong> При возникновении проблемы с участником транзакции вы можете повторно выполнить транзакцию или повторить шаг. Повторная попытка может помочь решить некоторые временные проблемы, например сбой сети или временную недоступность ресурсов. Повторные попытки могут выполняться внутри самих участников транзакции или инициироваться повторными операциями через координатора. </li><li><strong>Механизм компенсации:</strong> При сбое выполнения участника транзакции или возникновении исключения уже выполненные шаги можно откатить, выполнив ряд компенсационных операций. Механизмы компенсации могут запускаться автоматически или вручную для обеспечения согласованного состояния системы. Операции компенсации следует выполнять в обратном порядке, чтобы обеспечить откат данных до правильного состояния. </li><li><strong>Механизм тайм-аута:</strong> Система может установить разумный период ожидания: если участник транзакции не завершает операцию в течение указанного времени, участник может считаться невыполнившим операцию. Механизм тайм-аута может быть реализован с помощью запланированных задач или механизмов тактового сигнала. После истечения тайм-аута система может выбрать повторную попытку, компенсировать или отказаться от операции участника в зависимости от конкретной ситуации. </li><li><strong>Запись и воспроизведение:</strong> Действия, выполняемые каждым участником, могут фиксироваться в журнале. При возникновении исключения операцию можно выполнить повторно на основе механизма воспроизведения журнала. Ведение журнала и воспроизведение обеспечивают согласованность работы системы в аномальных условиях и могут использоваться для устранения неполадок и восстановления. </li><li><strong>Уведомление об исключениях и мониторинг:</strong> Система должна своевременно ловить и обрабатывать исключения. О ненормальных транзакциях соответствующий персонал или системные администраторы могут быть уведомлены посредством уведомлений о сообщениях, записей журнала, мониторинга сигналов тревоги и т. д. Система мониторинга может принимать соответствующие меры в зависимости от нештатных ситуаций, например перезапуск отказавших участников, корректировку распределения ресурсов и т. д. </li><p>Подводя итог, обработка исключений в конечном итоге согласованных распределенных транзакциях может обеспечить согласованность и надежность системы посредством повторных попыток, механизма компенсации, механизма тайм-аута, регистрации и воспроизведения, уведомления об исключениях и мониторинга и т. д. Конкретная стратегия обработки зависит от фактической ситуации и потребностей системы. </p><li><strong>Асинхронные сообщения:</strong> Обрабатывайте различные операции транзакции асинхронно через очередь сообщений, чтобы избежать прямых синхронных вызовов, чтобы повысить производительность системы и возможности параллельной обработки. Использование очередей сообщений может обеспечить порядок операций, а механизм повторных попыток можно настроить по мере необходимости для обеспечения согласованности данных. </li><li><strong>Распределенная блокировка:</strong> Используйте распределенные блокировки для операций с ключами, которые должны обеспечить согласованность данных. Например, используйте распределенные блокировки Redis, чтобы гарантировать, что только один поток может выполнить определенную операцию с ключом. Это позволяет избежать проблемы несогласованности данных, вызванной параллельными операциями. </li><li><strong>Бессильный дизайн:</strong> Создавайте интерфейсы и методы, которые являются идемпотентными, чтобы обеспечить согласованные результаты даже при многократном вызове. Идемпотентность интерфейса может быть идентифицирована путем создания уникального идентификатора запроса, а оценка идемпотентности может быть сделана на основе идентификатора запроса при повторных запросах. </li><li><strong>Структура распределенных транзакций:</strong> Используйте зрелые платформы распределенных транзакций, такие как Seata от Alibaba или TCC-Transaction с открытым исходным кодом, чтобы упростить управление и обработку распределенных транзакций. Эти платформы предоставляют согласованные решения и менее навязчивы к бизнес-логике. </li><li><strong>Синхронизация и избыточность данных:</strong> В сценариях с высоким уровнем параллелизма можно рассмотреть возможность синхронизации и избыточности данных для некоторых очень важных операций. Например, ключевые данные могут храниться в базах данных в нескольких географических точках, а данные могут синхронизироваться асинхронно или синхронно, чтобы избежать единых точек сбоя и несогласованности данных. </li><li><strong>Ограничение тока и деградация автоматического выключателя:</strong> В сценариях с высокой степенью параллелизма можно использовать стратегии ограничения тока и снижения эффективности автоматического выключателя для обеспечения высокой доступности и оперативности системы. Вы можете установить максимальное количество одновременных запросов. При достижении максимального количества одновременных запросов новые запросы будут отклонены или будет выполнен автоматический выключатель и обработка перехода на более раннюю версию, чтобы избежать сбоев системы и несогласованности данных. </li><li><strong>Мониторинг распределенных транзакций и оповещение:</strong> Создайте полную распределенную систему мониторинга транзакций и оповещения для оперативного обнаружения и устранения нештатных ситуаций при обработке транзакций. Распределенные транзакции можно отслеживать посредством мониторинга ключевых индикаторов и журналов в режиме реального времени, а также можно устанавливать правила сигналов тревоги для своевременного обнаружения и решения потенциальных проблем. </li><p>Короче говоря, в конечном итоге согласованная обработка распределенных транзакций в сценариях с высоким уровнем параллелизма требует всестороннего рассмотрения очередей сообщений, распределенных блокировок, идемпотентного проектирования, структуры распределенных транзакций, синхронизации и избыточности данных, ограничения тока и деградации автоматических выключателей, а также технологий мониторинга и сигнализации, а также опыт обеспечения согласованности данных и производительности системы. </p><p
2360209
None
Read more...
Интерпретация стратегии синхронизации данных
<p>Мы все знаем, что в большинстве случаев данные, запрашиваемые через браузер, являются кешированными. Если существует большая разница между кешированными данными и данными в базе данных, это может иметь серьезные последствия. В связи с этим мы должны и должны обеспечить согласованность данных базы данных и данных кэша, то есть синхронизацию кэша и базы данных. </p><p>Кеширование широко используется в проектах из-за его высокого параллелизма и высоких характеристик производительности.При использовании кеша мы обычно сталкиваемся с проблемой обновления.Когда источник данных меняется, как обновить базу данных и кеш? обеспечить безопасность и производительность. </p><p><strong>Политика кэширования активных обновлений</strong></p><p> Вариант 1. Вызывающий кэш обновляет кэш одновременно с обновлением базы данных.</p><p> Вариант 2. Интегрируйте кэш и базу данных в один сервис и используйте этот сервис для обеспечения согласованности. Предоставляет внешний интерфейс, и вызывающая сторона вызывает интерфейс, предоставленный службой, не беспокоясь о проблемах согласованности кэша.</p><p> Вариант 3. Вызывающий объект управляет только кешем, а другие потоки асинхронно сохраняют данные кеша в базе данных, чтобы обеспечить конечную согласованность. </p><p>Конкретно: установите срок действия кэша и автоматически удалите его после истечения срока действия. При повторном запросе обновите данные. </p><p>Преимущества: просто, удобно и понятно;</p><p>Недостатки: низкая своевременность. Данные в базе данных и данные в кеше могут оказаться противоречивыми до истечения срока действия кеша. </p><p> Предположим, что срок действия кэша составляет 10 минут, но кэш изменяется через 5 минут после его создания. Запрос, выполненный в течение следующих 5 минут, будет считывать кэшированные данные, а не самые последние данные. </p><p>Сценарии использования: компании с низкой частотой обновлений и низкими требованиями к своевременности. </p><p>Конкретно: стратегия синхронной двойной записи заключается в изменении кэша при изменении базы данных. </p><p>Преимущества: высокая своевременность, высокая согласованность между кешем и базой данных;</p><p>Недостатки: происходит вторжение кода и высокая связанность; пока выполняются бизнес-операции, связанные с вставкой, обновлением и удалением базы данных, кэш должен обновляться синхронно. Эта связанность слишком высока;</p><p>Сценарий использования: кэшированные данные, требующие высокой согласованности и своевременности. </p><p>Конкретно: асинхронное уведомление фактически означает отправку уведомления о времени при изменении базы данных. Соответствующие службы будут асинхронно изменять кэшированные данные после прослушивания уведомления. </p><p>Преимущества: низкая связанность, одновременно можно уведомлять несколько служб кэширования. Вы можете использовать MQ и асинхронные функции для обновления кеша, чтобы обновление базы данных и обновление кеша были разделены, и одновременно можно было обновлять несколько служб. В то же время вторжение кода очень незначительное (только небольшое количество кода MQ отправляется) или даже нулевое вторжение. </p><p>Недостатки: своевременность средняя, в середине могут быть несоответствия. Поскольку он асинхронен, могут быть различия во времени, что приводит к несогласованности данных в определенный момент. Но конечная последовательность гарантирована. </p><p>Сценарий использования: требования к своевременности средние, и существует несколько служб, которым необходимо синхронно обновлять кэш. </p><p>Асинхронная реализация может быть реализована на основе MQ или Canal:</p><p><strong>1) Асинхронное уведомление на основе MQ:</strong></p><img src="https://developer.qcloudimg.com/http-save/10175571/58f6d2154a54f42d20b8d9aeab0dd910.png"/><img src="https://developer.qcloudimg.com/column/article/10175571/20231118-6e90c2ce.gif"/><img src="https://developer.qcloudimg.com/column/article/10175571/20231118-6e90c2ce.gif"/><img src="https://developer.qcloudimg.com/column/article/10175571/20231118-6e90c2ce.gif"/><p> 1: После изменения информации о продукте на странице информация о продукте сохраняется в базе данных и сохраняется в базе данных MySQL; 2. После успешного сохранения опубликуйте сообщение MQ; 3: Существует служба, которая отслеживает соответствующее сообщение MQ. Если сообщение получено, оно обновляет информацию о кэше соответствующего продукта. </p><p>Интерпретация:</p><p>Интерпретация:</p><li> После того как служба продукта завершит модификацию данных, ей останется только отправить сообщение в MQ. </li><li> Служба кэширования прослушивает сообщения MQ, а затем выполняет обновления кэша. </li><p>Незначительное вмешательство в код все еще имеет место. </p><p><strong>2) Уведомление на основе канала</strong></p><img src="https://developer.qcloudimg.com/http-save/10175571/4ea1a60fdfdbe14704067dd650107499.png"/><p> 1: После того, как служба продукта завершит модификацию продукта и информация о продукте будет сохранена в базе данных, соответствующий бизнес прекращается. Здесь нет никакого вмешательства в код; 2: Canal отслеживает изменения MySQL и немедленно уведомляет службу кэширования при обнаружении изменения; 3: После того как служба кэша получает уведомление о канале, она обновляет кэш. </p><li> После того, как служба продукта завершит модификацию продукта, бизнес прекращается напрямую без какого-либо вмешательства в код. </li><li> Canal отслеживает изменения в MySQL и немедленно уведомляет службу кэширования при обнаружении изменений. </li><li> Служба кэширования получает уведомление о канале и обновляет кэш. </li><p>Нулевое вторжение кода</p><p><strong>Canal [kə'næl]</strong>, что переводится как водный путь/трубопровод/канава, canal — это проект с открытым исходным кодом компании Alibaba, разработанный на основе Java. На основе инкрементного анализа журналов базы данных обеспечивается инкрементная подписка и потребление данных. Адрес GitHub: <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Falibaba%2Fcanal" rel="nofollow noopener" style="color:# 0052D9 " target="_blank">GitHub – Alibaba/canal: компонент дополнительной подписки и потребления binlog Alibaba MySQL</a></p><p>Canal реализован на основе синхронизации master-slave MySQL. Canal маскируется под подчиненный узел MySQL для отслеживания изменений в двоичном журнале мастера. Затем полученная информация об изменениях передается клиенту Canal, после чего синхронизация других баз данных завершается. </p><img src="https://developer.qcloudimg.com/http-save/10175571/2d0dd2a034bd22c9c11740fe879e07d8.png"/><li> 1) Мастер MySQL записывает изменения данных в двоичный журнал (двоичный журнал), а записанные данные называются событиями двоичного журнала. </li><li> 2) Подчиненное устройство MySQL копирует события двоичного журнала ведущего устройства в свой журнал реле (журнал реле). </li><li> 3) Подчиненное устройство MySQL воспроизводит события в журнале ретрансляции и отражает изменения данных в своих собственных данных.</li><p
2360208
None
Read more...
Создание службы Disconf (3) – завершено
<p> <strong>Описание</strong> </p><p> В дополнение к среде, описанной в первых двух статьях блога, службе Disconf также требуется контейнер сервлетов Java (tomcat). Поскольку проект Disconf отделен от передней и задней части, ему также необходим httpweb-сервер (nginx рекомендуется). Конечно, если также необходимо сохранение данных, база данных MySQL также сохранит наши данные.</p><p> <strong>Подготовка</strong> </p><p> ps: Disconf — это продукт с открытым исходным кодом, его код размещен на github<a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fknightliao %2Fdisconf " rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/knightliao/disconf</a>, проект создан с помощью maven, сначала загрузите проект , внутри будет три модуля, а именно основной модуль, клиентский модуль и веб-модуль. Чтобы развернуть нашу службу Disconf, нам нужно развернуть веб-модуль как войну. Нам нужно настроить соответствующую конфигурацию перед упаковкой.< /п><p>1. Прежде чем настраивать связанные сервисы, сначала создайте используемые нами данные. Предполагается, что у вас уже есть сервис mysql </p><p> В каталоге sql\ веб-модуля находится скрипт для сборки библиотеки </p><p> Чтобы облегчить каждому разработку, все SQL-коды были унифицированы. Пожалуйста, выполните: - 0-init_table.sql создать базу данных, таблицы - 1-init_data.sql создает данные - патч 201512/20151225.sql </p><p> <strong>Конфигурация</strong> </p><p> В профиле\rd веб-модуля находится множество файлов конфигурации. По именам файлов мы можем четко знать, каким сервисам соответствуют файлы конфигурации. Файлы конфигурации включают в себя: - jdbc-mysql.properties (конфигурация базы данных) - redis-config.properties (конфигурация Redis) -zoo.properties (конфигурация Zookeeper) - application.properties (конфигурация приложения) </p><p> <strong>Развертывание</strong> </p><p> Развернуть войну Измените файл конфигурации tomcat server.xml, установите контекст в узле Host, и docBase предоставит вам путь распаковки упакованной войны: и установите порт 8015 Запустите Tomcat и все. Интерфейс развертывания Измените nginx.conf сервер { слушай 8081; имя_сервера localhost; access_log /home/work/var/logs/disconf/access.log; Error_log /home/work/var/logs/disconf/error.log; Расположение / { Root /home/work/dsp/disconf-rd/war/html; #Укажите здесь путь к html-файлу веб-модуля вашего проекта disconf если ($query_string) { истекает максимум; } } } Местоположение ~ ^/(api|export) { proxy_pass_header Сервер; proxy_set_header Хост $http_host; proxy_redirect выключен; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-схема $scheme; proxy_pass http://127.0.0.1:8015;#Адрес прокси настроен как ваш адрес доступа tomcat } } </p><p> После выполнения вышеуказанных шагов вы можете запустить серверы tomcat и nginx и ввести localhost:8081l в адресной строке, чтобы получить доступ к центру конфигурации Disconf. В случае успеха вы увидите следующий экран </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-c51e521e.png"/><p> Вид вышеприведенного экрана может означать только то, что ваша служба nginx успешно запущена и каталог вашего html-проекта указан правильно. Если вы можете войти в систему правильно, имя пользователя и пароль по умолчанию — admin:admin, что означает ваш Disconf Конфигурация службы прошла успешно</p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-6bd13896.png"/><
2360207
None
Read more...
Создание службы Disconf (2) – установка системы хранения Redis
<p> <strong>Описание</strong> </p><p> Фоновая служба Disconf активно использует систему хранения Redis в качестве кэша данных, поэтому давайте установим нашу службу Redis </p><p> <strong>Познакомьтесь с Redis</strong> </p><p> Прежде чем устанавливать службу Redis, давайте сначала поговорим о Redis эмоционально. Ниже приводится определение Redis из энциклопедии: </p><p> redis — это система хранения значений ключа. Подобно Memcached, он поддерживает относительно больше типов хранимых значений, включая строку (строку), список (связный список), набор (набор), zset (отсортированный набор — упорядоченный набор) и хеш (тип хеша). Все эти типы данных поддерживают операции push/pop, добавления/удаления, пересечения, объединения, различия и более сложные операции, и все эти операции являются атомарными. Исходя из этого, Redis поддерживает различные способы сортировки. Как и в случае с memcached, данные кэшируются в памяти для обеспечения эффективности. Разница в том, что redis будет периодически записывать обновленные данные на диск или записывать операции модификации в дополнительные файлы записей, и на этой основе достигается синхронизация master-slave (главный-подчиненный). Redis — это высокопроизводительная база данных «ключ-значение». Появление Redis во многом компенсировало недостатки хранилищ ключей/значений, таких как memcached, и в некоторых ситуациях может сыграть очень хорошую дополнительную роль по отношению к реляционным базам данных. Он предоставляет Java, C/C++, C#, PHP, JavaScript, Perl, Object-C, Python, Ruby, Erlang и другие клиенты, что очень удобно в использовании. [1] Redis поддерживает синхронизацию «главный-подчиненный». Данные могут быть синхронизированы с главного сервера на любое количество подчиненных серверов, а подчиненный сервер может быть главным сервером, связанным с другими подчиненными серверами. Это позволяет Redis выполнять одноуровневую репликацию дерева. Сохранение может записывать данные намеренно или непреднамеренно. Поскольку механизм публикации/подписки полностью реализован, когда подчиненная база данных синхронизирует дерево где угодно, она может подписаться на канал и получать полную запись выпуска сообщения главного сервера. Синхронизация полезна для масштабируемости и избыточности данных операций чтения </p><p> <strong>Подготовка</strong> </p><p> Загрузите установочный пакет Redis: адрес официального сайта<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fredis.io%2F" rel="nofollow noopener" style="color:#0052D9" target="_blank">http://redis.io/</a> </p><p> Если вы используете Windows, вы можете загрузить его здесь: <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2FServiceStack%2Fredis-windows " rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/ServiceStack/redis-windows</a> </p><p> <strong>Установка и запуск (аналогично тому же под windows)</strong> </p><p> Разархивируйте: tar –zxvf redis-2.4.6.tar.gz компилировать Следует отметить, что установка Redis очень проста.Уже есть готовый Makefile.Просто запустите команду make напрямую. сделать установку Redis состоит из четырех исполняемых файлов: redis-benchmark, redis-cli, redis-server, redis-stat. Эти четыре файла, а также redis.conf составляют окончательный пригодный для использования пакет всего Redis. Их функции заключаются в следующем: redis-server: программа запуска демона сервера Redis. redis-cli: инструмент управления Redis из командной строки. Конечно, вы также можете использовать telnet для работы в соответствии с его текстовым протоколом. redis-benchmark: инструмент тестирования производительности Redis, тестирует производительность чтения и записи Redis в вашей системе и вашей конфигурации. redis-stat: инструмент определения статуса Redis, который может определять параметры текущего состояния Redis и условия задержки. Теперь вы можете запустить Redis. Redis имеет только один параметр запуска — путь к файлу конфигурации. Redis-сервер /etc/redis.conf Обратите внимание, что параметр daemonize скопированного файла redis.conf по умолчанию равен no, поэтому Redis не будет работать в фоновом режиме.Для проверки нам нужно повторно открыть терминал. Измените его на «да», чтобы Redis запускался в фоновом режиме. Кроме того, в файле конфигурации указаны адреса файла pid, файла журнала и файла данных. При необходимости сначала измените их. По умолчанию информация журнала направляется на стандартный вывод. Ниже приводится значение основных параметров конфигурации redis.conf: daemonize: запускать ли в фоновом режиме демона pidfile: расположение pid-файла порт: номер порта прослушивания тайм-аут: запросить тайм-аут loglevel: уровень информации журнала logfile: расположение файла журнала базы данных: количество открытых баз данных save * *: Частота сохранения снимков, первая * указывает, как долго, а третья * указывает, сколько операций записи выполняется. Снимки автоматически сохраняются при выполнении определенного количества операций записи в течение определенного периода времени. Можно задать несколько условий. rdbcompression: использовать ли сжатие dbfilename: имя файла моментального снимка данных (только имя файла, не включая каталог). каталог: каталог, в котором сохраняется снимок данных (это каталог) addonly: включить ли addonlylog. Если этот параметр включен, журнал будет записываться для каждой операции записи. Это улучшит способность данных противостоять рискам, но повлияет на эффективность. Appendfsync: Как синхронизировать addonlylog с диском (три варианта: заставить fsync вызываться при каждой записи, включить fsync один раз в секунду и не вызывать fsync, чтобы дождаться синхронизации системы) В это время вы можете открыть терминал для тестирования.Порт прослушивания по умолчанию в файле конфигурации — 6379. Мы можем открыть клиент Redis для тестирования. [root@SNDA-192-168-1-114 ~]# redis-cli Не удалось подключиться к Redis по адресу 127.0.0.1:6379: соединение отклонено. не подключено> выход [root@SNDA-192-168-1-114 ~]# redis-server /etc/redis.conf [root@SNDA-192-168-1-114 ~]# redis-cli redis 127.0.0.1:6379> выйти </p><p> <strong>хранилище данных Redis</strong> Хранилище Redis разделено на три части: хранилище памяти, дисковое хранилище и файл журнала. В файле конфигурации есть три параметра для его настройки. сохранять обновления в секундах, сохранять конфигурацию, указывает, сколько времени и сколько операций обновления требуется для синхронизации данных с файлом данных. Это можно комбинировать с несколькими условиями.Например, настройки в файле конфигурации по умолчанию задают три условия. «только для добавления» да/нет, конфигурация «только для добавления», указывает, следует ли вести журнал после каждой операции обновления.Если этот параметр не включен, данные могут быть потеряны на некоторое время во время отключения электроэнергии. Поскольку собственные синхронизированные файлы данных Redis синхронизируются в соответствии с указанными выше условиями сохранения, некоторые данные будут существовать в памяти только в течение определенного периода времени. Appendfsync no/always/everysec, конфигурация Appendfsync, no означает ожидание, пока операционная система синхронизирует кэш данных с диском, всегда означает ручной вызов fsync() для записи данных на диск после каждой операции обновления, а Everysec означает однократную синхронизацию в секунду. </p><p> ps: Наконец, прикрепите адрес документа общих команд Redis <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fdoc.redisfans.com%2Findex.html " rel ="nofollow noopener" style="color:#0052D9" target="_blank">http://doc.redisfans.com/index.html</a> </p><p> Простой демонстрационный адрес Java, работающего с Redis<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fflychao88.iteye.com%2Fblog%2F1527163" rel="nofollow noopener" style="color:#0052D9" target="_blank">http://flychao88.iteye.com/blog/1527163</a> </p><
2360206
None
Read more...
Создание службы Disconf (1) — кластерная среда ZooKeeper
<p> <strong>Описание</strong> </p><p> Откуда<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fwww.kailing.pub%2Farticle%2Findex%2Farcid%2F63.html" rel="nofollow noopener" style="color:#0052D9" target="_blank">"Принцип и конструкция Disconf для реализации управления распределенной конфигурацией"</a> Мы узнали, что для создания и развертывания нашего собственного распределенного центра конфигурации disconf требуются распределенные приложения Служба координации программ Поддержка Zookeeper, давайте развернем наш кластерный сервис Zookeeper</p><p> <strong>Познакомьтесь с Zookeeper</strong> </p><p> Прежде чем приступить к развертыванию, давайте сначала познакомимся с Zookeeper. Энциклопедия Baidu описывает Zookeeper следующим образом: </p><p> ZooKeeper — это распределенная служба координации распределенных приложений с открытым исходным кодом. Это реализация Google Chubby с открытым исходным кодом и важный компонент Hadoop и Hbase. Это программное обеспечение, которое предоставляет согласованные услуги для распределенных приложений. Предоставляемые функции включают в себя: обслуживание конфигурации, службы доменных имен, распределенную синхронизацию, групповые службы и т. д. Цель ZooKeeper — инкапсулировать сложные и подверженные ошибкам ключевые сервисы и предоставить пользователям простые и удобные в использовании интерфейсы, а также систему с эффективной производительностью и стабильными функциями. ZooKeeper содержит простой набор примитивов[1], обеспечивающих интерфейсы для Java и C. Версия кода ZooKeeper предоставляет интерфейсы для распределенных монопольных блокировок, выборов и очередей.Код находится в Zookeeper-3.4.3\src\recipes. Существует две версии блокировок и очередей распределения: Java и C, а у выборов есть только версии Java. </p><p> <strong>Приготовление (конечно, если попробовать самому, подойдет и машина)</strong> </p><p> Здесь в качестве примера мы возьмем три машины с Ubuntu для создания минимальной кластерной среды. Можно использовать три сервера или три виртуальных машины. Процесс установки сервера Ubuntu краток, его можно скачать с http://releases.ubuntu.com/precision/. </p><р> <strong>Шаг 1. Настройка сервера</strong> После того как три сервера Ubuntu будут готовы, предположим, что их IP-адреса — 192.168.0.11, 192.168.0.12 и 192.168.0.13. Назовите их хосты zkp1, zkp2 и zkp3 соответственно. Zookeeper разработан на Java, поэтому также требуется среда jdk. Если вы хотите установить Oracle JDK под Ubuntu, вы можете обратиться к этому сообщению в блоге<a class="" href="/developer/tools/blog-entry?target =http%3A%2F %2Fwww.linuxidc.com%2FLinux%2F2014-11%2F109216.htm" rel="nofollow noopener" style="color:#0052D9" target="_blank">http://www.linuxidc .com/Linux/2014-11/109216.htm</a>. <strong>Шаг 2. Загрузите Zookeeper.</strong> to<a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fzookeeper.apache.org%2F" rel="nofollow noopener" style="color:#0052D9" target ="_blank">Официальный сайт Zookeeper</a>, чтобы загрузить последнюю версию установочного пакета. <strong>Шаг 3. Установите Zookeeper</strong> Примечание. Сначала выполните шаги (1)–(3) на первом сервере server1. (1) Распаковка: предполагается, что в качестве имени пользователя для установки используется dennis, поместите Zookeeper-3.4.5.tar.gz в каталог /home/dennis, а затем выполните «tar zxfzookeeper-3.4.5.tar». .gz», чтобы распаковать . (2) Конфигурация: Создайте копию conf/zoo_sample.cfg и назовите ееzoo.cfg, а также поместите ее в каталог conf. Затем измените конфигурацию следующим образом: #Основная единица времени, используемая в Zookeeper, — миллисекунды. тикВремя=2000 #Каталог данных. Может быть любой каталог. dataDir=/var/lib/zookeeper/ #Кластер содержит несколько серверов, один из которых является ведущим, а остальные серверы в кластере являются ведомыми. Параметр initLimit настраивает максимальное время подтверждения между ведомым и ведущим при инициализации соединения. В настоящее время параметр имеет значение установлено на 5. Описание Ограничение по времени — 5 раз. initLimit=5 #Этот параметр настраивает максимальную продолжительность времени для отправки сообщений, запросов и ответов между лидером и последователем. В настоящее время для параметра установлено значение 2, что указывает на то, что ограничение по времени в 2 раза превышает TickTime, что составляет 4000 мс. syncLimit=2 #Номер порта для прослушивания клиентских подключений. клиентПорт=2181 #server.X=A:B:C где X — число, обозначающее номер сервера. A — IP-адрес сервера. B настраивает порт, используемый сервером для обмена сообщениями с лидером кластера. C Настроить порт, используемый при выборе лидера. server.1=zkp1:2888:3888 server.2=zkp2:2888:3888 server.3=zkp3:2888:3888 (3) Создайте каталог снимков /var/lib/zookeeper и создайте файл идентификатора сервера. $sudo mkdir /var/lib/zookeeper $ cd /var/lib/zookeeper Создайте в этом каталоге файл с именем myid и содержимым 1 (это значение меняется в зависимости от сервера, о котором будет сказано позже). (4) Скопируйте настроенные каталоги /home/dennis/zookeeper-3.4.5/ и /var/lib/zookeeper на сервере1 на сервер2 и сервер3 соответственно. Затем измените содержимое /var/lib/zookeeper/myid на 2 и 3. <strong>Шаг 4. Запустите Zookeeper</strong> Запустите три сервера одновременно, войдите в каталог Zookeeper-3.4.5 и выполните следующую команду запуска: $sudo java-cp Zookeeper-3.4.5.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.15.jar:conf\org .apache.zookeeper.server.quorum.QuorumPeerMain conf/zoo.cfg </p><p> Вы также можете перейти в каталог каждого сервера Zookeeper и выполнить: Запустить ./bin/zkServer.sh начать Закройте ./bin/zkServer.sh start Примечание. При запуске первого из них может появиться сообщение об ошибке с запросом Zoo2 и Zoo3. Об ошибке не будет сообщено после завершения всех запусков. </p><p> <strong>На этом этапе наша кластерная среда Zookeeper настроена и построена, а также завершена установка одной из зависимостей среды службы Disconf. Фактически, в дополнение к поддержке, предоставляемой Zookeeper, следующие зависимости: также требуется:</strong> </p><p> <strong>1.Mysql (версия 14.12 Distrib 5.0.45, для неизвестного-linux-gnu (x86_64) с использованием оболочки EditLine)</strong> <strong> 2.Tomcat(apache-tomcat-7.0.50)</strong> <strong> 3.Nginx(nginx/1.5.3)</strong> <strong> 4. Redis (2.4.5)</strong></p><
2360205
None
Read more...
Решения для обеспечения единообразия распределенных транзакций и обеспечения согласованности данных
<p>Рекомендуется подписаться, поставить лайк и собрать перед прочтением. </p><img src="https://developer.qcloudimg.com/http-save/yehe-admin/cc1a0690482a25cd13dc954c49493133.png"/><p>Другое распространенное решение для распределенных транзакций, обеспечивающее конечный результат за пределами TCC, основано на протоколе двухфазной фиксации (2PC). </p><li><strong>Этап подготовки:</strong><ul class="ul-level-1"><li>Координатор отправляет сообщение с запросом всем участникам, чтобы узнать, возможна ли операция отправки. </li><li>Участники выполняют фактические операции и отправляют координатору результаты операции и статус готовности (готовность к отправке или невозможность отправки). </li></ul></li><li>Координатор отправляет всем участникам сообщение с запросом, могут ли они выполнить операцию отправки. </li><li>Участники выполняют фактические операции и отправляют координатору результаты операции и статус готовности (можно отправить или нет). </li><li><strong>Фаза фиксации:</strong><ul class="ul-level-1"><li>Координатор отвечает на основе полученных участников и может быть отправлен, если все участники отвечают на статус, координатор отправляет сообщение фиксации всем участникам с запросом операции фиксации. </li><li>После получения сообщения об отправке участник выполняет операцию отправки и отправляет координатору подтверждающее сообщение. </li></ul></li><li>Координатор отвечает на основе полученных ответов участников. Если все участники отвечают с указанием статуса фиксации, координатор отправляет всем участникам сообщение о фиксации с запросом на операцию фиксации. </li><li>После получения сообщения об отправке участник выполняет операцию отправки и отправляет координатору подтверждающее сообщение. </li><li><strong>Обработка ситуации прерывания:</strong><ul class="ul-level-1"><li>Если какой-либо участник отвечает со статусом невозможности отправки или координатор не получает его в течение определенного периода времени время В ответ всем участникам координатор отправит всем участникам сообщения о прерывании, требуя от них выполнения операций прерывания. </li></ul></li><li>Если какой-либо участник отвечает со статусом «невозможно отправить» или координатор не получает ответов от всех участников в течение определенного периода времени, координатор отправит сообщение о прерывании всем участникам, требуя от них выполнить операции прерывания. </li><li>Общение и сотрудничество между координаторами и участниками. </li><li>Координатор определяет, можно ли выполнить операцию отправки, запрашивая и собирая статус участников. </li><li>Если все участники отвечают на статус фиксации, координатор отправляет запрос на фиксацию, и участники выполняют операцию фиксации. </li><li>Если какой-либо участник отвечает с сообщением о невозможности отправки или тайм-ауте, координатор отправляет сообщение о прерывании, и участники выполняют операции прерывания. </li><p>Хотя 2PC является распространенным решением, оно также имеет некоторые проблемы, такие как единая точка отказа координатора, блокировка и т. д. Поэтому в практических приложениях люди предпочитают использовать TCC или надежные решения для обмена сообщениями для достижения в конечном итоге согласованных распределенных транзакций. </p><li><strong>Двухэтапная фиксация (2ПК):</strong> Это один из наиболее часто используемых протоколов распределенных транзакций. В 2PC транзакция имеет координатора и нескольких участников. Координатор отвечает за координацию операций фиксации или отката различных участников. Его основной рабочий процесс выглядит следующим образом: <ul class="ul-level-1"><li>Этап подготовки: координатор отправляет запросы на подготовку всем участникам и ожидает ответов от участников. Участники выполняют транзакционные операции, записывают в журнал отмену и повтор, а затем отправляют ответы координатору. </li><li>Этап принятия решения: координатор решает, зафиксировать или откатить транзакцию на основе ответов участников, и отправляет соответствующие запросы всем участникам. </li><li>Фаза выполнения: участники выполняют операции фиксации или отката в соответствии с запросом координатора и отправляют результаты операции координатору. </li></ul></li><li>Этап подготовки: координатор отправляет запросы на подготовку всем участникам и ждет ответов от участников. Участники выполняют транзакционные операции, записывают в журнал отмену и повтор, а затем отправляют ответы координатору. </li><li>Этап принятия решения: координатор решает, зафиксировать или откатить транзакцию на основе ответов участников, и отправляет соответствующие запросы всем участникам. </li><li>Фаза выполнения: участники выполняют операции фиксации или отката в соответствии с запросом координатора и отправляют результаты операции координатору. </li><li><strong>Компенсирующая транзакция:</strong> Это механизм обработки транзакций, основанный на компенсации. В компенсирующей транзакции, когда участник не может завершить операцию, он выполняет противоположную операцию для отката предыдущей операции. Такой подход обеспечивает согласованность окончательных данных. Например, если служба запрашивает центр инвентаризации о сокращении запасов, а запрос не выполняется, компенсирующая транзакция выполнит увеличение запасов для обеспечения согласованности. </li><li><strong>Надежная очередь сообщений:</strong> Используя надежную систему очередей сообщений, можно гарантировать надежную доставку сообщений. В распределенной транзакции участники инкапсулируют операции транзакции в сообщения и отправляют их в очередь сообщений, а координатор обрабатывает сообщения после их получения. В случае сбоя операции участника операцию отката можно выполнить с помощью механизма повтора очереди сообщений. </li><li><strong>Режим саги:</strong> Saga — это модель управления распределенными транзакциями, которая может обеспечить максимальную согласованность распределенных систем. В режиме Saga большая транзакция разбивается на серию небольших локальных транзакций, и каждая локальная транзакция является атомарной. Каждая локальная транзакция имеет соответствующую операцию отката для обеспечения согласованности. Когда локальная транзакция будет успешной, Saga будет записана. Когда все локальные транзакции будут успешными, Saga будет помечена как зафиксированная. </li><p>Выше приведены некоторые распространенные решения, обеспечивающие согласованность данных в конечном итоге согласованных распределенных транзакциях. Основываясь на конкретных бизнес-сценариях и потребностях, вы можете выбрать подходящее решение для достижения согласованности распределенных транзакций. </p><p
2360204
None
Read more...
Принцип и конструкция Disconf для реализации распределенного управления конфигурацией
<p> В распределенной среде часто развертывается множество экземпляров одного и того же типа службы. Эти экземпляры используют некоторые конфигурации, и для лучшего обслуживания этих конфигураций создается служба управления конфигурациями. Эта служба позволяет легко решать проблемы конфигурации для тысяч или сотен экземпляров службы. </p><p> Ван Ацзин предложил разработать и реализовать решение для хранения информации о конфигурации на основе ZooKeeper [1], которое хранит все конфигурации в Zookeeper, что делает управление конфигурациями неудобным, и они не имеют соответствующей реализации исходного кода. Diamond[2] Taobao — это система, используемая внутри компании Taobao для управления постоянной конфигурацией. Она имеет полную реализацию с открытым исходным кодом. Она характеризуется простотой, надежностью и удобством использования. Большинство систем на Taobao настраиваются с использованием Diamond. Унифицированный управление. Он хранит конфигурации во всех файлах конфигурации фрагментарно.Он поддерживает только структуру KV, а передача обновлений конфигурации происходит не в режиме реального времени. Внутренний центр конфигурации BJF компании Baidu [3] использует реализацию, аналогичную Taobao Diamond, которая также имеет фрагментированную конфигурацию и поддерживает только KV и push-уведомления не в реальном времени. </p><p>Гомогенные системы являются основным направлением рынка. В частности, когда в отрасли активно используется виртуализация развертывания (например, система JPAAS, SAE, BAE), будет все больше и больше сценариев, в которых одна и та же система использует один и тот же пакет развертывания. Однако гетерогенные системы также имеют определенное значение для существования: например, для нескольких нижестоящих экземпляров в «режиме извлечения» одновременно может работать только один нижестоящий экземпляр. В этом сценарии возникает проблема, когда несколько компьютеров имеют режимы «активный и резервный». В настоящее время не существует очевидного внутреннего решения, позволяющего единообразно решить эту проблему. </p><p> disconf — это полное унифицированное решение для распределенной конфигурации на базе Zookeeper. </p><p> <strong>Его функциональные особенности</strong> </p><li>Поддерживает распределенное управление конфигурацией (элементы конфигурации + файлы конфигурации) </li><li>Единая конфигурация и выпуск </li><li>Единый выпуск и обновление конфигурации (облачное хранилище и выпуск). Конфигурация хранится в облачной системе, и пользователи могут выпускать и обновлять конфигурации на платформе унифицированным способом. </li><li>Автоматизация обновления конфигурации: пользователь обновляет конфигурацию на платформе, а система, использующая конфигурацию, автоматически обнаруживает ситуацию и применяет новую конфигурацию. В частности, если пользователь определяет класс функции обратного вызова для этой конфигурации, этот класс функции будет вызываться автоматически. </li><li>Настройка управления гетерогенной системой</li><li>Унифицированное развертывание разнородных пакетов. Под гетерогенной системой здесь понимается ситуация, когда система развертывает несколько экземпляров и требует несколько пакетов развертывания (jar или war) из-за разных конфигураций (то же самое ниже). После использования Disconf для развертывания гетерогенных систем требуется только один пакет развертывания, и конфигурации разных экземпляров будут назначены автоматически. В частности, поскольку в отрасли активно используется виртуализация развертывания (например, системы JPAAS, SAE, BAE), будет появляться все больше и больше сценариев, в которых одна и та же система использует один и тот же пакет развертывания, и Disconf естественным образом может вписаться в него. Гетерогенное активное и резервное автоматическое переключение: если в гетерогенной системе есть активный и резервный компьютер, а хост зависает, резервный компьютер может автоматически получить конфигурацию хоста и стать хостом. </li><li>Инструмент совместного использования контекста для гетерогенных активных и резервных компьютеров. В гетерогенных системах может потребоваться совместное использование контекста при переключении между активными и резервными компьютерами. Вы можете использовать инструмент совместного использования контекста, чтобы поделиться активным и резервным контекстами. </li><li>Программирование на основе аннотаций, минималистское использование. Мы стремимся к минималистическому методу программирования с хорошим пользовательским опытом программирования. Благодаря простой аннотации и чрезвычайно простому написанию кода можно выполнить сложное распределение конфигурации. </li><li>Требуется среда программирования Spring.</li><p> <strong>Его концепция дизайна: </strong> </p><li>Простой и удобный пользовательский интерфейс: <ul class="ul-level-1"><li>отказался от метода управления фрагментированной конфигурацией [2,3] и по-прежнему использует метод программирования на основе файлов конфигурации, который согласуется с предыдущими привычками программистов в программировании (конфигурации помещаются в файлы конфигурации). В частности, для поддержки функции фрагментированной конфигурации относительно ниши также поддерживаются элементы конфигурации. </li><li>Принимает программирование вторжений без кода на основе XML: для достижения унифицированного и автоматизированного выпуска и обновления файла конфигурации требуется всего несколько строк конфигурации XML. </li><li>Использует метод программирования взлома слабого кода на основе аннотаций: благодаря спецификациям программирования, одному файлу конфигурации и одному классу конфигурации структура кода проста и понятна. В XML почти нет изменений, он такой же, как и исходная конфигурация SpringXML. При собственно программировании практически невозможно почувствовать, что конфигурация распределена </li></ul></li><li>От метода управления фрагментированной конфигурацией отказались [2,3], и по-прежнему применяется метод программирования на основе файлов конфигурации, который соответствует предыдущим привычкам программистов в программировании (конфигурации помещаются в файлы конфигурации). В частности, для поддержки функции фрагментированной конфигурации относительно ниши также поддерживаются элементы конфигурации. </li><li>Применяет интрузивное программирование без кода на основе XML: требуется всего несколько строк конфигурации XML для достижения унифицированного и автоматизированного выпуска и обновления файла конфигурации. </li><li>Используется метод программирования взлома слабого кода на основе аннотаций: благодаря спецификациям программирования, одному файлу конфигурации и одному классу конфигурации структура кода проста и понятна. В XML почти нет изменений, он такой же, как и исходная конфигурация SpringXML. При собственно программировании практически невозможно почувствовать, что конфигурация распределена </li><li>Можно разместить файл конфигурации любого типа, что является большим улучшением по сравнению с [2,3], где поддерживается только структура KV. </li><li>Обновления конфигурации обновляются в режиме реального времени. </li><li>Предоставляет функцию веб-управления с хорошим интерфейсом, благодаря которому очень удобно проверять, какие экземпляры используются в конфигурации. </li><p> <strong>режим кластера службы disconf</strong>: </p><img src="https://developer.qcloudimg.com/http-save/yehe-1651485/17e9651a4912bdfdb50b184eed0c5a1d.jpg"/><p> <strong>Схема архитектуры модуля Disconf</strong>: </p><img src="https://developer.qcloudimg.com/http-save/yehe-1651485/30d7e14dfb77a039acb64179ec16fff3.jpg"/><p> Краткое введение в каждый модуль выглядит следующим образом: </p><li> Disconf-core <ul class="ul-level-1"><li> Модуль распределенных уведомлений: поддерживает уведомление об обновлениях конфигурации в режиме реального времени. </li><li> Модуль управления путями: унифицированное управление внутренним путем конфигурации. URL-адреса </li></ul></li><li> Модуль распределенных уведомлений: поддерживает уведомление об обновлениях конфигурации в режиме реального времени. </li><li> Модуль управления путями: унифицированное управление URL-адресами внутренних путей конфигурации </li><li> Disconf-client <ul class="ul-level-1"><li> Модуль контейнера хранилища конфигурации: унифицированное управление памятью хранения данных локальных файлов конфигурации и элементов конфигурации в пользовательских экземплярах </li><li> Конфигурация Модуль перезагрузки: отслеживает изменения в локальных файлах конфигурации и автоматически перезагружает их в указанные bean-компоненты. </li><li> Модуль сканирования: поддерживает сканирование всех аннотированных классов и доменов disconf. </li><li> Модуль загрузки: загружает файлы конфигурации в restful. элементы стиля и конфигурации </li><li> модуль наблюдения: отслеживает изменения в удаленных файлах конфигурации и элементах конфигурации </li><li> Модуль распределения активных и резервных элементов: после завершения конкуренции активных и резервных элементов единое управление активными и резервными элементами распределение, активный и резервный мониторинг и контроль </li><li> Модуль активной и резервной конкуренции: поддерживает активную и резервную конкуренцию в распределенной среде </li></ul></li><li> Модуль контейнера хранилища конфигурации: унифицированное управление хранением данных в памяти локальных файлов конфигурации и элементов конфигурации в пользовательских экземплярах </li><li> Настройте модуль перезагрузки: отслеживайте изменения в локальных файлах конфигурации и автоматически перезагружайте указанные bean-компоненты </li><li> Модуль сканирования: поддерживает сканирование всех аннотированных классов и доменов disconf </li><li> Модуль загрузки: загрузка файлов конфигурации и элементов конфигурации в спокойном стиле </li><li> модуль наблюдения: отслеживает изменения в удаленных файлах конфигурации и элементах конфигурации </li><li> Модуль активного и резервного распределения: после завершения конкуренции активных и резервных объектов обеспечивается единое управление активным и резервным распределением, а также мониторинг и контроль активных и резервных </li><li> Модуль активной и резервной конкуренции: поддерживает активную и резервную конкуренцию в распределенной среде. </li><li> Disconf-web <ul class="ul-level-1"><li> Модуль хранения конфигурации: управляет хранением и чтением всех конфигураций </li><li> Модуль управления конфигурацией: поддерживает загрузку и выгрузку конфигураций , Обновление </li><li> Модуль уведомлений: при обновлении конфигурации все экземпляры, использующие эти конфигурации, будут уведомлены в режиме реального времени. </li><li> Модуль мониторинга самопроверки конфигурации: автоматически регулярно проверять, соответствует ли локальная конфигурация экземпляра соответствует центральной конфигурации </li><li>Контроль разрешений: простой контроль разрешений в Интернете </li></ul></li><li> Модуль хранения конфигурации: управляет хранением и чтением всех конфигураций </li><li> Модуль управления конфигурацией: поддерживает загрузку, скачивание и обновление конфигурации. </li><li> Модуль уведомлений: при обновлении конфигурации все экземпляры, использующие эти конфигурации, будут уведомлены в режиме реального времени. </li><li> Настройте модуль мониторинга самопроверки: автоматически и регулярно проверяйте, соответствует ли локальная конфигурация экземпляра центральной конфигурации </li><li> Контроль разрешений: простой контроль разрешений для Интернета </li><li> Disconf-tools <ul class="ul-level-1"><li> Модуль совместного использования контекста: обеспечивает совместное использование контекста между несколькими экземплярами. </li></ul></li><li> Модуль совместного использования контекста: обеспечивает совместное использование контекста между несколькими экземплярами. </li><img src="https://developer.qcloudimg.com/http-save/yehe-1651485/1627d3be78c3a4ffe4f501c065ef32a2.jpg"/><p> <strong>Подробное введение в рабочий процесс:</strong> </p><p> Основное отличие от версии 2.0 заключается в том, что она поддерживает: функции активного и резервного распределения/события переключения активного и резервного. </p><li> <strong>Начать событие A</strong>: Следующие события происходят по порядку. <ul class="ul-level-1"><li> Ответ 3. Сканируйте статические данные аннотаций и добавляйте их в хранилище конфигурации. </li><li> A4+A2: В соответствии с файлами конфигурации и элементами конфигурации в хранилище загрузите данные конфигурации с платформы disconf-web. Здесь будет конкуренция между активными и резервными </li><li> A5: Внедрить в хранилище загруженные значения данных конфигурации. </li><li>A6: По конфигурационным файлам и элементам конфигурации на складе перейти на узел мониторинга ЗК. </li><li> A7+A2: В соответствии с определением конфигурации XML загрузите файл конфигурации с платформы disconf-web, поместите его в хранилище и контролируйте узел ZK. Соревнования пройдут между основной и резервной командами. </li><li>A8: A1-A6 все обрабатывают статические данные. A7 обрабатывает данные динамического класса, включая: создание экземпляра настроенного класса функции обратного вызова; внедрение настроенного значения в объект конфигурации. </li></ul></li><li> A3: Сканируйте статические данные аннотаций и добавляйте их в хранилище конфигурации. </li><li> A4+A2: На основе файлов конфигурации и элементов конфигурации в хранилище загрузите данные конфигурации с платформы disconf-web. Будет конкуренция между основным и резервным </li><li> A5: Внедрить загруженные значения данных конфигурации в хранилище. </li><li>A6: Согласно файлам конфигурации и элементам конфигурации, имеющимся на складе, перейдите на узел мониторинга ЗК. </li><li> A7+A2: В соответствии с определением конфигурации XML загрузите файл конфигурации с платформы disconf-web, поместите его в хранилище и отслеживайте узел ZK. Соревнования пройдут между основной и резервной командами. </li><li> A8: все A1–A6 обрабатывают статические данные. A7 обрабатывает данные динамического класса, включая: создание экземпляра настроенного класса функции обратного вызова; внедрение настроенного значения в объект конфигурации. </li><li> <strong>Событие обновления конфигурации B</strong>: Следующие события происходят последовательно. <ul class="ul-level-1"><li> B1: Администратор обновляет конфигурацию на платформе Disconf-web. </li><li> B2: Платформа Disconf-web отправляет сообщения об обновлении конфигурации узлам, указанным ZK. </li><li> B3: ZK уведомляет модуль Disconf-cient. </li><li>B4: То же, что и A4. </li><li> B5: То же, что и A5. </li><li> B6: По сути то же самое, что и A4, с той лишь разницей, что новое значение конфигурации также будет введено в объект конфигурации. </li></ul></li><li> B1: Администратор обновляет конфигурацию на платформе Disconf-web. </li><li> B2: Платформа Disconf-web отправляет сообщения об обновлении конфигурации узлам, указанным ZK. </li><li> B3: ZK информирует модуль несогласия. </li><li> B4: то же, что и A4. </li><li> B5: То же, что и A5. </li><li> B6: По сути то же самое, что и A4, с той лишь разницей, что новое значение конфигурации также будет введено в объект конфигурации. </li><li> <strong>Событие переключения активного режима ожидания C</strong>: последовательно происходят следующие события. <ul class="ul-level-1"><li> C1: Произошло зависание хоста. </li><li> C2: ZK уведомляет все затронутые резервные машины. </li><li>C4: То же, что и A2. </li><li>C5: то же, что и A4. </li><li>C6: То же, что и A5. </li><li>C7: То же, что и A6. </li></ul></li><li> C1: Произошло зависание хоста. </li><li> C2: ZK уведомляет все затронутые резервные машины. </li><li> C4: То же, что и A2. </li><li> C5: то же, что и A4. </li><li> C6: То же, что и A5. </li><li> C7: то же, что и A6. </li><p> disconf-web предоставляет веб-архитектуру, которая разделяет переднюю и внутреннюю части. Подробности см. в статье <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub. .com%2Fknightliao% 2Fdisconf%2Ftree%2Fmaster%2Fdisconf-web" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://github.com/knightliao/disconf/tree/master /disconf-web</a> </p><p> В этом разделе основное внимание будет уделено реализации disconf-client. </p><p> Эта реализация будет включать настройку модуля контейнера хранилища, модуля сканирования, модуля загрузки и модуля наблюдения. </p><img src="https://developer-public-1258344699.cos.ap-guangzhou.myqcloud.com/column/column/9118877/20231118-1949e8d5.png"/><p> Одним из преимуществ использования перехвата АОП является то, что управление конфигурацией может быть достигнуто относительно легко. Например, конфигурации в параллельных средах могут действовать единообразно. Обсуждение этого можно найти по адресу <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fknightliao%2Fdisconf%2Fwiki%2F%25E7%25BB% 2586 %25E8%258A%2582%25E8%25AE%25A8%25E8%25AE%25BA" rel="nofollow noopener" style="color:#0052D9" target="_blank">здесь</a>. </p><p> В частности, режим программирования, предоставляемый этим методом, очень прост. Например, когда программа, использующая следующий класс конфигурации, использует его, она может напрямую @Autowired его и выполнять вызовы. При его использовании это то же самое, что и используя обычный JavaBeans, но на самом деле он уже распространен. При обновлении конфигурации класс конфигурации также будет автоматически обновлен. </p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@Service @DisconfFile(filename = "redis.properties") public class JedisConfig { // 代表连接地址 private String host; // 代表连接port private int port; /** * 地址, 分布式文件配置 * * @return */ @DisconfFileItem(name = "redis.host", associateField = "host") public String getHost() { return host; } public void setHost(String host) { this.host = host; } /** * 端口, 分布式文件配置 * * @return */ @DisconfFileItem(name = "redis.port", associateField = "port") public int getPort() { return port; } public void setPort(int port) { this.port = port; } }</code></pre><p> Эта реализация обеспечивает распределенную конфигурацию без какого-либо вмешательства в код. </p><p> ReloadablePropertiesFactoryBean наследует класс PropertiesFactoryBean файла Spring Properties и управляет всеми файлами конфигурации, которые необходимо перезагрузить при обновлении конфигурации. Для каждого управляемого файла конфигурации он будет настроен и получен в хранилище конфигурации через модуль контейнера хранилища конфигурации, модуль сканирования, модуль загрузки и модуль наблюдения. </p><p> ReloadingPropertyPlaceholderConfigurer наследует класс управления значением конфигурации Spring Bean PropertyPlaceholderConfigurer. При первом сканировании Spring bean-компонентов disconf записывает, с какими bean-компонентами связан файл конфигурации. </p><p> ReloadConfigurationMonitor — это запланированная задача, которая регулярно проверяет, обновлен ли локальный файл конфигурации. </p><p> При обновлении конфигурации центра конфигурации файл конфигурации будет загружен в локальный экземпляр. ReloadConfigurationMonitor будет отслеживать это поведение и уведомлять ReloadingPropertyPlaceholderConfigurer о необходимости обновления значения соответствующего класса компонента. </p><p> В частности, этот метод не может решить проблему единообразной конфигурации, действующей в параллельных условиях. </p><p>В реализации предусмотрена концепция выбора активного и резервного режима для каждой конфигурации. Прежде чем получить конфигурацию, экземпляр пользователя должен конкурировать за глобальную уникальность, чтобы получить значение конфигурации. Здесь мы используем глобальную уникальную блокировку на основе Zookeeper для достижения этой цели. </p><p></p><p>TaobaoDiamond[2]</p><p>Дисконфигурация</p><p>Сравнить</p><p>Постоянство данных</p><p>Хранить на MySQL</p><p>Хранить на MySQL</p><p>Все они сохраняются в базе данных, и ими легко управлять</p><p>Модель «тяни-толкай»</p><p>Извлекайте модель и получайте полные данные каждые 15 секунд</p><p>Модель push-уведомлений на основе Zookeeper, push-уведомления в реальном времени</p><p>disconf передается в режиме реального времени на основе распределенного Zookeeper, который всегда лучше Diamond с точки зрения стабильности, эффективности и простоты использования.</p><p>Чтение и запись конфигурации</p><p>Поддерживает экземпляры для чтения и записи конфигураций. Поддерживает определенный экземпляр для записи данных конфигурации и их передачи другим экземплярам</p><p>Поддерживается только чтение экземпляров конфигурации. Обновив конфигурацию на disconf-web, ее можно будет передать всем экземплярам приложения</p><p>Судя по текущим сценариям применения, требования к написанию конфигурации экземпляров не столь очевидны. Централизованное широковещательное решение, поддерживаемое disconf, возможно, больше похоже на человеческое мышление. </p><p>Аварийное восстановление</p><p>Режим многоуровневого аварийного восстановления: данные конфигурации будут сбрасываться локально, чтобы центральная служба не стала недоступной в случае ее зависания.</p><p>Режим многоуровневого аварийного восстановления, приоритет отдается чтению локальных файлов конфигурации. </p><p>Обе стороны поддерживают возможность использования настроенного экземпляра даже после зависания центральной службы</p><p>Настройка модели данных</p><p>Поддерживается только данные структуры KV, режим файла без конфигурации</p><p>Поддерживает традиционный режим файла конфигурации (файл конфигурации), а также поддерживает данные структуры KV (элементы конфигурации)</p><p>Метод программирования с использованием файлов конфигурации может быть более похож на привычки программистов и его легче принять и использовать. </p><p>Модель программирования</p><p>Файл конфигурации необходимо разделить на несколько элементов конфигурации, и очевидной модели программирования нет</p><p>На основе использования файлов конфигурации предоставляются две модели программирования: на основе аннотаций и на основе XML</p><p>Нет</p><p>Нет</p><p>Параллелизм</p><p>Когда несколько конфигураций должны вступить в силу одновременно, проблема одновременного и одновременного действия не может быть решена</p><p>Конфигурация на основе аннотаций может решить проблемы параллелизма</p><
2360203
None
Read more...
Понимание bashrc, .bash_profile и .zshrc
<h2 id="13q7r" name="Understanding-bashrc-vs-.bash_profile-vs-.zshrc">Понимание bashrc, .bash_profile и .zshrc</h2><p>Углубляясь в мир интерфейсов командной строки (CLI), вы могли столкнуться с такими файлами, как <code>.bashrc</code>, <code>.bash_profile</code> и <code>.zshrc< /код>. Но что это такое и почему они так важны для разработчиков и системных администраторов? Давайте разгадаем эту тайну.</p><p>В Unix-подобных операционных системах файлы конфигурации оболочки, обычно называемые «точечными файлами», поскольку они обычно начинаются с точки (что делает их скрытыми файлами в системах Unix), определяют настройки, переменные среды и сценарии запуска для пользовательских сеансов. . Эти файлы определяют поведение вашей оболочки.</p><p>Суффикс «rc», встречающийся в таких именах, как <code>.bashrc</code> или <code>.zshrc</code>, происходит от слова «команды запуска». Исторически в системах Unix «rc» обозначал файлы, содержащие команды, запускаемые при запуске. Помните: файлы «rc» определяют команды инициализации.</p><li><strong>.bashrc</strong>:<ul class="ul-level-1"><li><strong>Использование</strong>: оболочки без входа в систему в Bash (например, новые сеансы терминала) .</li><li><strong>Содержимое</strong>: настройки среды, псевдонимы и функции, специфичные для Bash.</li></ul></li><li><strong>Применение</strong>: оболочки в Bash без входа в систему (например, новые сеансы терминала).</li><li><strong>Содержимое</strong>: настройки среды, псевдонимы и функции, специфичные для Bash.</li><li><strong>.bash_profile</strong> (иногда <code>.profile</code>): <ul class="ul-level-1"><li><strong>Использование</strong>: Вход оболочки в Bash (например, сеансы SSH).</li><li><strong>Содержание</strong>: команды для первоначальной настройки после входа в систему. Часто для обеспечения единообразия он использует <code>.bashrc</code>.</li></ul></li><li><strong>Применение</strong>: оболочки входа в Bash (например, сеансы SSH).</li><li><strong>Содержание</strong>: команды для первоначальной настройки после входа в систему. Часто для обеспечения единообразия он использует <code>.bashrc</code>.</li><li><strong>.zshrc</strong>:<ul class="ul-level-1"><li><strong>Использование</strong>: сеансы оболочки Zsh без входа в систему.</li><li ><strong>Содержимое</strong>: настройки, функции и псевдонимы, специфичные для Zsh.</li></ul></li><li><strong>Применение</strong>: сеансы оболочки Zsh без входа в систему.</li><li><strong>Содержимое</strong>: настройки, функции и псевдонимы, специфичные для Zsh.</li><li><strong>Оболочки входа</strong>: запускаются при входе пользователя в систему. Типично для SSH. Нацелен на <code>.bash_profile</code> или его эквиваленты.</li><li><strong>Оболочки без входа в систему</strong>: создаются в рамках существующего сеанса, как новая вкладка терминала. В случае Zsh используется <code>.bashrc</code> или <code>.zshrc</code>.</li><p>Чтобы обеспечить согласованное поведение, многие разработчики используют источник <code>.bashrc</code> из <code>.bash_profile</code>:</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">if [ -f ~/.bashrc ]; then source ~/.bashrc fi</code></pre><p>Есть и другие файлы конфигурации, на которые стоит обратить внимание:</p><p>Для <strong>Zsh</strong>:</p><li><strong>.zshenv</strong>: всегда загружается при запуске Zsh.</li><li><strong>.zprofile</strong>: аналогично <code>.bash_profile</code>, для оболочек входа.</li><li><strong>.zshrc</strong>: для интерактивных сеансов без входа в систему.</li><li><strong>.zlogin</strong>: загружается после <code>.zshrc</code> для оболочек входа.</li><li><strong>.zlogout</strong>: запускается при выходе из оболочки входа.</li><p>Для <strong>Bash</strong>:</p><li><strong>.bashrc</strong>: для интерактивных оболочек без входа в систему.</li><li><strong>.bash_profile</strong>: для оболочек входа в систему, и если <code>.bash_login</code> не существует, Bash читает это.</li><li><strong>.bash_login</strong>: читайте после <code>.bash_profile</code> для оболочек входа.</li><li><strong>.profile</strong>: действует как запасной вариант, если не найден ни <code>.bash_profile</code>, ни <code>.bash_login</code>.</li><p>Использование этих файлов конфигурации оболочки обеспечивает больший контроль над работой командной строки. Независимо от того, создаете ли вы новую среду или совершенствуете существующую, знание этих файлов имеет основополагающее значение для любого разработчика, работающего в среде Unix или Linux.</p><
2360202
None
Read more...
Повышение безопасности приложений с помощью OAuth 2.0 и OpenID Connect
<h2 id="7pf8q" name="Enhancing-Application-Security-with-OAuth-2.0-and-OpenID-Connect">Повышение безопасности приложений с помощью OAuth 2.0 и OpenID Connect</h2><p><strong>Повышение безопасности приложений с помощью OAuth 2.0 и OpenID Connect</strong></p><p><strong>Введение</strong></p><p>В эпоху взаимосвязанных систем и совместного использования данных обеспечение безопасного и бесперебойного потока информации имеет решающее значение. Два известных протокола, которые произвели революцию в сфере аутентификации и авторизации, — это OAuth 2.0 и OpenID Connect (OIDC). Эти открытые стандарты предоставляют приложениям безопасные способы доступа к пользовательским данным без раскрытия их учетных данных.</p><p><strong>OAuth 2.0: революция в авторизации</strong></p><img alt="OAuth 2.0 - Ein Überblick" src="https://developer.qcloudimg.com/http-save/yehe-5705150/78aedc6a9a6049e69a57f73b0f5fa6ca.jpg"/><p>OAuth 2.0 – это открытый стандарт делегирования доступа, позволяющий сторонним приложениям получать ограниченный доступ к пользовательским данным в другой службе, не раскрывая учетные данные пользователя. Например, приложению может потребоваться доступ к данным пользователя в Google или Facebook, и OAuth 2.0 предлагает безопасный способ сделать это.</p><p>Вот типичный процесс работы OAuth 2.0:</p><li>Пользователь инициирует процесс OAuth 2.0, нажав кнопку или ссылку, например «Войти через Google».</li><li>Приложение перенаправляет пользователя на веб-сайт поставщика услуг, где пользователь входит в систему и разрешает приложению доступ к своим данным.</li><li>Поставщик услуг перенаправляет пользователя обратно в приложение, включая код авторизации в URL-адресе.</li><li>Приложение получает код авторизации и запрашивает токен доступа у поставщика услуг.</li><li>Поставщик услуг возвращает токен доступа, который приложение может использовать для доступа к данным пользователя.</li><p>OAuth 2.0 предлагает несколько типов авторизации для разных типов приложений и сценариев. К ним относятся предоставление кода авторизации, неявное предоставление, предоставление учетных данных пароля владельца ресурса, предоставление учетных данных клиента и токен обновления.</p><p><strong>OpenID Connect: расширение OAuth 2.0 для аутентификации</strong></p><img src="https://developer.qcloudimg.com/http-save/yehe-5705150/e4bbe0e54cf8213f96f9c8fee6ce7dd9.jpg"/><p>Хотя OAuth 2.0 ориентирован на авторизацию, он не обеспечивает способа получения информации о личности пользователя. Именно здесь на сцену выходит OpenID Connect (OIDC). OIDC — это уровень идентификации, построенный на основе OAuth 2.0. Он представляет id_token, веб-токен JSON (JWT), содержащий информацию о личности пользователя, которую приложение может декодировать и использовать.</p><p>Поток OIDC аналогичен OAuth 2.0, но поставщик услуг возвращает дополнительный id_token, когда приложение запрашивает токен доступа:</p><li>Как и в случае с OAuth 2.0, пользователь инициирует процесс OIDC, нажав кнопку или ссылку.</li><li>Приложение перенаправляет пользователя на веб-сайт провайдера OIDC, где пользователь входит в систему и авторизует приложение.</li><li>Поставщик OIDC перенаправляет пользователя обратно в приложение, включая код авторизации в URL-адресе.</li><li>Приложение использует этот код авторизации для запроса токена доступа и id_token у поставщика OIDC.</li><li>Поставщик OIDC возвращает токен доступа и id_token. Приложение может использовать токен доступа для доступа к данным пользователя и декодировать id_token для получения идентификационной информации пользователя.</li><p><strong>Зачем использовать OAuth 2.0 и OpenID Connect?</strong></p><p>OAuth 2.0 и OIDC имеют значительные преимущества:</p><li><strong>Повышенная безопасность</strong>: они избавляют пользователей от необходимости передавать свои учетные данные сторонним приложениям, что снижает риск кражи или неправильного использования учетных данных.</li><li><strong>Улучшение взаимодействия с пользователем</strong>. Благодаря системе единого входа (SSO) пользователям достаточно пройти аутентификацию только один раз, чтобы получить доступ к нескольким приложениям, что упрощает работу пользователя.</li><li><strong>Масштабируемое управление пользователями</strong>. Поскольку информация о пользователях управляется поставщиком OAuth/OIDC, приложения могут разгружать задачи управления пользователями, что упрощает масштабирование.</li><li><strong>Взаимодействие</strong>. Будучи открытыми стандартами, OAuth 2.0 и OIDC обеспечивают совместимость различных систем, упрощая интеграцию разработчиков с различными сервисами.</li><p>В заключение отметим, что OAuth 2.0 и OpenID Connect играют важную роль в повышении безопасности и удобства использования современных приложений. Поняв и внедрив эти протоколы, разработчики могут обеспечить пользователям удобство и безопасность работы в Интернете.</p><
2360201
None
Read more...
TLS 1.3: повышенная безопасность, более быстрые соединения
<h2 id="7v5k6" name="TLS-1.3:-Enhanced-Security,-Faster-Connections">TLS 1.3: повышенная безопасность, более быстрые соединения</h2><p>В современном цифровом мире безопасность и скорость передачи данных имеют решающее значение. В этом отношении протокол Transport Layer Security (TLS) играет ключевую роль. Здесь мы углубимся в новый и улучшенный протокол TLS 1.3, уделив особое внимание процессу установления связи, который претерпел существенные улучшения с точки зрения скорости и безопасности по сравнению со своим предшественником TLS 1.2.</p><p>TLS 1.3, преемник TLS 1.2, произвел революцию в протоколах безопасной связи благодаря улучшенным мерам безопасности и оптимизации производительности. В этой статье мы углубимся в тонкости процесса установления связи TLS 1.3, подчеркнув его ключевые преимущества по сравнению с TLS 1.2.</p><img alt="tls.1.2.vs.tls.1.3.png" src="https://developer.qcloudimg.com/http-save/yehe-5705150/9036e9170cbfaa1abdbb5b8e5ba55b77.png"/><p>Подтверждение TLS 1.2 включает в себя более сложную последовательность шагов:</p><li><strong>ClientHello</strong>: клиент отправляет сообщение ClientHello, которое включает максимальную поддерживаемую версию TLS, случайное число (ClientRandom) и список поддерживаемых наборов шифров.</li><li><strong>ServerHello</strong>: сервер отвечает сообщением ServerHello, которое включает выбранный набор шифров, используемую версию TLS и другое случайное число (ServerRandom). Он также отправляет свой сертификат.</li><li><strong>Проверка сертификата</strong>. Клиент проверяет сертификат сервера по списку доверенных центров сертификации (CA). Если сервер аутентифицирован, клиент приступает к установлению связи.</li><li><strong>ClientKeyExchange</strong>: клиент генерирует новое случайное число (секрет PreMaster). Он шифрует его открытым ключом сервера (полученным из сертификата) и отправляет его в сообщении ClientKeyExchange.</li><li><strong>Расшифровка</strong>: сервер использует свой закрытый ключ для расшифровки секрета PreMaster.</li><li><strong>Генерация сеансового ключа</strong>. И клиент, и сервер генерируют сеансовые ключи на основе секретов ClientRandom, ServerRandom и PreMaster.</li><li><strong>Завершено</strong>: обе стороны обмениваются сообщениями «Завершено», зашифрованными с помощью сеансового ключа.</li><p>Для сравнения, TLS 1.3 вносит существенные изменения в протокол рукопожатия:</p><li><strong>ClientHello</strong>. Подобно TLS 1.2, клиент отправляет сообщение ClientHello со случайным числом (ClientHello.random) и поддерживаемыми наборами шифров. Кроме того, он отправляет расширение «key_share» для соглашения о ключах Диффи-Хеллмана.</li><li><strong>ServerHello</strong>: сервер отвечает сообщением ServerHello, содержащим выбранный им набор шифров, случайное число (ServerHello.random) и выбранный общий ключевой ресурс. Он также предоставляет цифровую подпись для проверки клиента.</li><li><strong>Параметры сервера</strong>. Сервер отправляет зашифрованные расширения (включая конфигурацию сервера и запрос сертификата клиента, если применимо) и его сертификат.</li><li><strong>Сервер завершен</strong>: сервер отправляет сообщение о завершении, предоставляя криптографический хэш разговора на данный момент.</li><li><strong>Завершение клиента</strong>: клиент вычисляет общий секрет на основе своего закрытого ключа и открытого ключа сервера. Клиент проверяет сертификат сервера, отправляет свой собственный сертификат (если требуется), проверяет хэш диалога в сообщении «Завершено» сервера и отправляет собственное сообщение «Завершено».</li><li><strong>Данные приложения</strong>. Теперь и клиент, и сервер могут отправлять зашифрованные данные приложения.<strong>Возобновление 0-RTT: преимущества и проблемы</strong></li><p>В TLS 1.3 представлена функция 0-RTT (нулевое время прохождения туда и обратно), которая позволяет клиенту отправлять данные на сервер в своем первом сообщении при возобновлении предыдущего сеанса, тем самым полностью устраняя необходимость в обратном пути. Это еще больше увеличивает скорость соединения, но вызывает потенциальные проблемы безопасности, связанные с атаками воспроизведения, когда злоумышленник перехватывает и воспроизводит данные 0-RTT. Чтобы избежать этого, конфиденциальные действия (например, совершение покупки) не следует выполнять с использованием данных 0-RTT.</p><p>TLS 1.3 представляет собой существенные улучшения по сравнению с TLS 1.2, оптимизируя процесс установления связи, удаляя устаревшие криптографические примитивы и вводя возобновление 0-RTT. Однако, как и в случае со всеми технологическими достижениями, важно понимать и смягчать потенциальные проблемы безопасности, связанные с этими новыми функциями.</p><li>[RFC 8446] — «Протокол безопасности транспортного уровня (TLS) версии 1.3». <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fdatatracker.ietf.org%2Fdoc%2Fhtml%2Frfc8446" rel="nofollow noopener" style="color:# 0052D9" target="_blank">https://datatracker.ietf.org/doc/html/rfc8446</a></li><li>Рукопопожатие TLS 1.3: более пристальный взгляд. <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fwww.thesslstore.com%2Fblog%2Ftls-1-3-handshake-tls-1-2%2F" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://www.thesslstore.com/blog/tls-1-3-handshake-tls-1-2/</a> </li><li>tls-1-3- Performance-part-2-full-handshake-2. <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fwww.wolfssl.com%2Ftls-1-3- Performance-part-2-full-handshake-2% 2F" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://www.wolfssl.com/tls-1-3- Performance-part-2-full-handshake-2/ </a></li><
2360200
None
Read more...
TLS 1.3: повышенная безопасность, более быстрые соединения
<h2 id="7v5k6" name="TLS-1.3:-Enhanced-Security,-Faster-Connections">TLS 1.3: повышенная безопасность, более быстрые соединения</h2><p>В современном цифровом мире безопасность и скорость передачи данных имеют решающее значение. В этом отношении протокол Transport Layer Security (TLS) играет ключевую роль. Здесь мы углубимся в новый и улучшенный протокол TLS 1.3, уделив особое внимание процессу установления связи, который претерпел существенные улучшения с точки зрения скорости и безопасности по сравнению со своим предшественником TLS 1.2.</p><p>TLS 1.3, преемник TLS 1.2, произвел революцию в протоколах безопасной связи благодаря улучшенным мерам безопасности и оптимизации производительности. В этой статье мы углубимся в тонкости процесса установления связи TLS 1.3, подчеркнув его ключевые преимущества по сравнению с TLS 1.2.</p><img alt="tls.1.2.vs.tls.1.3.png" src="https://developer.qcloudimg.com/http-save/yehe-5705150/9036e9170cbfaa1abdbb5b8e5ba55b77.png"/><p>Подтверждение TLS 1.2 включает в себя более сложную последовательность шагов:</p><li><strong>ClientHello</strong>: клиент отправляет сообщение ClientHello, которое включает максимальную поддерживаемую версию TLS, случайное число (ClientRandom) и список поддерживаемых наборов шифров.</li><li><strong>ServerHello</strong>: сервер отвечает сообщением ServerHello, которое включает выбранный набор шифров, используемую версию TLS и другое случайное число (ServerRandom). Он также отправляет свой сертификат.</li><li><strong>Проверка сертификата</strong>. Клиент проверяет сертификат сервера по списку доверенных центров сертификации (CA). Если сервер аутентифицирован, клиент приступает к установлению связи.</li><li><strong>ClientKeyExchange</strong>: клиент генерирует новое случайное число (секрет PreMaster). Он шифрует его открытым ключом сервера (полученным из сертификата) и отправляет его в сообщении ClientKeyExchange.</li><li><strong>Расшифровка</strong>: сервер использует свой закрытый ключ для расшифровки секрета PreMaster.</li><li><strong>Генерация сеансового ключа</strong>. И клиент, и сервер генерируют сеансовые ключи на основе секретов ClientRandom, ServerRandom и PreMaster.</li><li><strong>Завершено</strong>: обе стороны обмениваются сообщениями «Завершено», зашифрованными с помощью сеансового ключа.</li><p>Для сравнения, TLS 1.3 вносит существенные изменения в протокол рукопожатия:</p><li><strong>ClientHello</strong>. Подобно TLS 1.2, клиент отправляет сообщение ClientHello со случайным числом (ClientHello.random) и поддерживаемыми наборами шифров. Кроме того, он отправляет расширение «key_share» для соглашения о ключах Диффи-Хеллмана.</li><li><strong>ServerHello</strong>: сервер отвечает сообщением ServerHello, содержащим выбранный им набор шифров, случайное число (ServerHello.random) и выбранный общий ключевой ресурс. Он также предоставляет цифровую подпись для проверки клиента.</li><li><strong>Параметры сервера</strong>. Сервер отправляет зашифрованные расширения (включая конфигурацию сервера и запрос сертификата клиента, если применимо) и его сертификат.</li><li><strong>Сервер завершен</strong>: сервер отправляет сообщение о завершении, предоставляя криптографический хэш разговора на данный момент.</li><li><strong>Завершение клиента</strong>: клиент вычисляет общий секрет на основе своего закрытого ключа и открытого ключа сервера. Клиент проверяет сертификат сервера, отправляет свой собственный сертификат (если требуется), проверяет хэш диалога в сообщении «Завершено» сервера и отправляет собственное сообщение «Завершено».</li><li><strong>Данные приложения</strong>. Теперь и клиент, и сервер могут отправлять зашифрованные данные приложения.<strong>Возобновление 0-RTT: преимущества и проблемы</strong></li><p>В TLS 1.3 представлена функция 0-RTT (нулевое время прохождения туда и обратно), которая позволяет клиенту отправлять данные на сервер в своем первом сообщении при возобновлении предыдущего сеанса, тем самым полностью устраняя необходимость в обратном пути. Это еще больше увеличивает скорость соединения, но вызывает потенциальные проблемы безопасности, связанные с атаками воспроизведения, когда злоумышленник перехватывает и воспроизводит данные 0-RTT. Чтобы избежать этого, конфиденциальные действия (например, совершение покупки) не следует выполнять с использованием данных 0-RTT.</p><p>TLS 1.3 представляет собой существенные улучшения по сравнению с TLS 1.2, оптимизируя процесс установления связи, удаляя устаревшие криптографические примитивы и вводя возобновление 0-RTT. Однако, как и в случае со всеми технологическими достижениями, важно понимать и смягчать потенциальные проблемы безопасности, связанные с этими новыми функциями.</p><li>[RFC 8446] — «Протокол безопасности транспортного уровня (TLS) версии 1.3». <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fdatatracker.ietf.org%2Fdoc%2Fhtml%2Frfc8446" rel="nofollow noopener" style="color:# 0052D9" target="_blank">https://datatracker.ietf.org/doc/html/rfc8446</a></li><li>Рукопопожатие TLS 1.3: более пристальный взгляд. <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fwww.thesslstore.com%2Fblog%2Ftls-1-3-handshake-tls-1-2%2F" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://www.thesslstore.com/blog/tls-1-3-handshake-tls-1-2/</a> </li><li>tls-1-3- Performance-part-2-full-handshake-2. <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fwww.wolfssl.com%2Ftls-1-3- Performance-part-2-full-handshake-2% 2F" rel="nofollow noopener" style="color:#0052D9" target="_blank">https://www.wolfssl.com/tls-1-3- Performance-part-2-full-handshake-2/ </a></li><
2360199
None
Read more...
Проблемы дискового ввода-вывода: их понимание и устранение для повышения производительности системы
<h2 id="343te" name="Disk-I/O-issues:-Understanding-and-fixing-them-to-boost-system- Performance">Проблемы дискового ввода-вывода: понимание и устранение их для повышения производительности системы </h2><p>Проблемы дискового ввода-вывода и использования пространства являются распространенными причинами снижения производительности вычислительных систем. Низкая скорость системы может напрямую повлиять на ее способность извлекать и сохранять информацию на диске.</p><p>В этой статье мы узнаем, почему возникают проблемы с дисковым вводом-выводом, какие команды Linux можно использовать для диагностики и устранения проблем дискового ввода-вывода, а также распространенные методы их решения.</p><p>Проблемы дискового ввода-вывода могут быть результатом сложности хранилища, узких мест приложений, конфигураций RAID, времени отклика и конструкции. Давайте рассмотрим некоторые из этих моментов подробно.</p><p>Программно-определяемый или виртуальный уровень хранения данных работает поверх базового физического уровня хранения. Виртуальное хранилище увеличивает сложность и количество потенциальных точек сбоя из-за конкуренции за ресурсы, поскольку оно не может читать и записывать данные так же быстро, как физическое хранилище.</p><p>Приложения с интенсивным вводом-выводом часто вызывают узкие места и проблемы с задержками в хранилище. Чаще всего они возникают, когда одно и то же хранилище данных используют несколько загруженных приложений. Лучшее решение проблемы узких мест приложений — найти способ обрабатывать приложения с низкой пропускной способностью ввода-вывода хранилища и использовать большую базу пользователей.</p><p>Конфигурацию RAID можно использовать для хранения данных в приложении как на аппаратном, так и на программном уровне. Конфигурация RAID распределяет запросы ввода-вывода и копии данных на несколько дисков, увеличивая количество операций ввода-вывода и надежность хранилища. Любая проблема в физическом устройстве или программном обеспечении, управляющем массивом RAID (например, из-за возраста, недостаточной конфигурации или устаревшего программного обеспечения), может привести к замедлению обработки запросов ввода-вывода.</p><p>Увеличение времени отклика ввода-вывода хранилища может снизить производительность ввода-вывода. Когда устройству хранения данных требуется больше времени для ответа на запрос ввода-вывода, это указывает на наличие узкого места на уровне хранения. Дополнительная нагрузка на существующие узкие места ввода-вывода хранилища приводит к постоянной задержке времени отклика.</p><p>Другая причина медленного ввода-вывода — плохое состояние физических устройств хранения данных. По мере старения жестких дисков или повышения температуры они с меньшей вероятностью смогут достичь максимальной скорости ввода-вывода, а задержка ввода-вывода начнет ухудшаться. Старые диски следует заменять до того, как они начнут портиться и в конечном итоге изнашиваться, что приведет к ошибкам ввода-вывода.</p><p>Чтобы выявить и устранить проблемы дискового ввода-вывода, важно понимать, как они могут проявляться в вашей системе. Проблемы дискового ввода-вывода могут повлиять на производительность системы по-разному:</p><li>Чрезмерное количество операций ввода-вывода может привести к высокой загрузке системы, потенциально превышающей максимальную допустимую нагрузку, равную 1.</li><li>Оповещения могут срабатывать, например, когда служба недоступна или если система не может запустить службу.</li><li>Размещенные веб-сайты могут загружаться неожиданно долго или перестать отвечать на запросы.</li><li>Виртуальные машины могут работать медленно или не отвечать на запросы в течение длительного времени.</li><li>Диски могут работать плохо из-за увеличения задержки во время резервного копирования.</li><li>Доставка электронной почты может замедляться, поскольку почтовому серверу необходимо считывать и записывать данные с жестких дисков и на них.</li><p>Как только мы заподозрим потенциальную проблему дискового ввода-вывода, мы можем использовать метрики для анализа производительности дискового ввода-вывода. Вот некоторые из этих важных показателей:</p><li>Запросов на чтение в секунду</li><li>Запросов на запись в секунду</li><li>Общее количество записанных байт и записанных байт в секунду</li><li>Общее количество прочитанных байт и число прочитанных байт в секунду</li><li>Запросы, ожидающие в очереди</li><p>После того как мы измерим и проконтролируем производительность диска с помощью вышеуказанных показателей, мы сможем использовать команды для выявления проблем дискового ввода-вывода. Три наиболее часто используемые команды для устранения неполадок — это <code>df, iostat и</code> и <code>vmstat.</code></p><p>Команда <code>df</code> — это сокращенная форма для <strong>файловой системы диска</strong>. Это одна из самых простых команд для устранения проблем дискового ввода-вывода. Если места недостаточно, операции записи завершатся неудачно. Команда <code>df</code> отображает используемое и доступное пространство для всех смонтированных файловых систем в Linux. Используемое и оставшееся пространство по умолчанию отображается блоками по 1 КБ.</p><p><strong>Синтаксис:</strong></p><p><strong>Синтаксис:</strong></p><p><strong>Синтаксис:</strong></p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">df [OPTIONS] [FILES]</code></pre><p><strong>Пример:</strong></p><p><strong>Пример:</strong></p><p><strong>Пример:</strong></p><p>Выполнив команду <code>df</code>, вы увидите результат, аналогичный показанному ниже:</p><img alt="Fig. 1: Output of the df command" src="https://developer.qcloudimg.com/http-save/yehe-5705150/05f540e86c1eb0d342eedf08969f4d15.png"/><p><em style="font-style:italic">Рис. 1: вывод команды </em><code>df</code></p><p>Как вы можете видеть в приведенном выше выводе, он отображает следующую информацию для всех смонтированных файловых систем:</p><li><strong>Файловая система:</strong> Имя файловой системы или устройства.</li><li><strong>Блоки по 1 КБ:</strong> Общий размер файловой системы или устройства в блоках по 1 КБ.</li><li><strong>Используется</strong>. Общий объем пространства, используемого существующими файлами в файловой системе.</li><li><strong>Доступно:</strong> Общий объем свободного места в файловой системе.</li><li><strong>%: процент</strong> блоков, используемых файловой системой.</li><li><strong>Место установки:</strong> точка монтирования или каталог, в котором смонтирована файловая система.</li><p>Команда <code>vmstat</code> также известна как статистика виртуальной памяти. Это утилита мониторинга производительности системы в Linux, которая отображает информацию о процессах, памяти, планировании ЦП, диске и блоках ввода-вывода. Он показывает пользователям производительность системы в реальном времени в течение периода выборки. Если вы не укажете никаких параметров, команда <code>vmstat</code> по умолчанию покажет статистику с момента последней перезагрузки системы.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">vmstat [options][delay [count]]</code></pre><p>Задержка и количество — два важных параметра для команды vmstat. Они используются для непрерывного отображения производительности системы в реальном времени с частотой заданного интервала и определенное количество раз.</p><li><strong>Задержка</strong> – это временной интервал или задержка между двумя обновлениями выходных данных.</li><li><strong>Count</strong> определяет количество отображаемых выходных обновлений. Если этот счетчик не установлен, команда <code>vmstat</code> выполняется бесконечно.</li><p>Выполнение команды <code>vmstat</code> даст вам результат, аналогичный показанному ниже:</p><img alt="Fig. 2: Output of the vmstat command" src="https://developer.qcloudimg.com/http-save/yehe-5705150/e333843b9a98c50b8f62ff1cb6866921.png"/><p><em style="font-style:italic">Рис. 2: Вывод команды </em><code>vmstat</code></p><p>Это основной вывод, отображающий общую статистику. Вы также можете указать параметры задержки и подсчета для непрерывного отображения статистики в реальном времени. Например, запуск <code>vmstat</code> 5 3 отобразит в реальном времени три приведенные ниже статистические данные, каждая через 5-секундный интервал.</p><img alt="Fig. 3: Real-time output of vmstat command" src="https://developer.qcloudimg.com/http-save/yehe-5705150/26f50b87cea6c6ef3842044374fbe433.png"/><p><em style="font-style:italic">Рис. 3. Вывод команды </em><code>vmstat</code> в режиме реального времени</p><p>Вышеуказанные результаты разделены на четыре области. Наше основное внимание уделяется разделу io. Он показывает два столбца:</p><li><strong>bi:</strong> количество блоков данных, полученных от устройства.</li><li><strong>bo:</strong> количество блоков данных, отправленных на устройство.</li><p>Мы можем использовать эту информацию для анализа случаев интенсивной записи или чтения данных. Затем мы можем использовать другую команду, например <code>iostat,</code>, чтобы увидеть, какой жесткий диск принимает на себя нагрузку, и попытаться найти основную причину проблемы дискового ввода-вывода.</p><p>Как следует из названия, команда <code>iostat</code> используется для мониторинга статистики ввода-вывода в системе. Он генерирует эти отчеты, отслеживая взаимосвязь между продолжительностью активного времени устройств и их средней скоростью передачи. Созданные отчеты можно использовать для обновления конфигурации системы для достижения лучшего баланса ввода/вывода между различными доступными физическими дисками.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">iostat [option] [interval] [count]</code></pre><p>Подобно тому, что мы видели в команде vmstat, параметры интервала и количества используются для бесконечного отображения обновлений в реальном времени или только для определенных значений.</p><p>Выполнение команды <code>iostat</code> даст вам результат, аналогичный показанному ниже:</p><img alt="Fig 4: Output of the iostat command" src="https://developer.qcloudimg.com/http-save/yehe-5705150/5eef0b273874ba76e47a0a23b80c9660.png"/><p><em style="font-style:italic">Рис. 4: Вывод команды </em><code>iostat</code></p><p>В отчетах о выводе по умолчанию отображается статистика ЦП и статистика ввода-вывода устройства с момента последней перезагрузки системы. Из двух разделов нас больше интересует раздел <strong>Устройство</strong>. Он генерирует следующую информацию для всех разделов или устройств:</p><li><strong>Устройство:</strong> Имя раздела/устройства.</li><li><strong>tps:</strong> «Передача в секунду»; более высокий показатель tps означает более загруженный процессор.</li><li><strong>Blk_read/s (kB_read/s) и Blk_wrtn/s (kB_wrtn/s):</strong> Скорость передачи операций чтения или записи, выраженная в виде количества блоков, прочитанных/записанных в секунду <li><strong>Blk_read (kB_read) и Blk_wrtn (kB_wrtn):</strong> Общее количество блоков, прочитанных и записанных на это устройство с момента последней перезагрузки.</li><p>Приведенные выше примеры указывают на проблемы с производительностью диска в системе. Вы можете внести несколько исправлений программного и аппаратного обеспечения, чтобы уменьшить проблемы с дисковым вводом-выводом и использованием пространства.</p><li>Используйте отдельные виртуальные и физические жесткие диски.</li><li>Установите операционную систему хоста на диск, отличный от диска виртуальных машин.</li><li>Оптимизируйте жесткие диски, реализовав разделение дисков в гостевой и хостовой ОС.</li><li>Обновите тип RAID в соответствии с рабочей нагрузкой приложения, чтобы повысить производительность приложения.</li><li>Включите прямой доступ к памяти.</li><li>Замените жесткие диски на твердотельные (SSD) или более быстровращающиеся диски.</li><li>Распределите нагрузку приложений между жесткими дисками, чтобы лучше справляться с нагрузкой ввода-вывода.</li><li>Обновите кэш в памяти большего размера, чтобы приложения могли реже выполнять прямое чтение и запись из файловых систем.</li><p>Использование дискового пространства и проблемы ввода-вывода могут значительно ухудшить производительность системы. Прежде чем принимать соответствующие меры для их устранения, необходимо устранить неполадки и найти основную причину таких проблем, как высокое использование пространства или медленные запросы ввода-вывода.</p><p>В Linux есть различные команды, которые вы можете использовать, чтобы определить причину проблем с дисковым вводом-выводом. Трех наиболее часто используемых команд, обсуждаемых здесь, — <code>df, iostat</code> и <code>vmstat</code> — достаточно, чтобы помочь вам найти основную причину. Хотя мы рассмотрели ряд полезных программных исправлений проблем дискового ввода-вывода, полезно помнить, что иногда обновления оборудования являются лучшим постоянным решением.</p><
2360198
None
Read more...
Раскрытие возможностей хранилища в Kubernetes: подробное руководство
<h2 id="efbiu" name="Раскрытие возможностей хранилища-в-Kubernetes:-A-Comprehensive-Guide">Раскрытие возможностей хранилища в Kubernetes: комплексное руководство</h2><li>Почему постоянное хранилище важно в контейнерных средах.</li><li>Постоянные тома (PV): их роль и жизненный цикл.</li><li>Заявки на постоянные тома (PVC): как они запрашивают ресурсы хранения.</li><li>Классы хранилища: определение способа предоставления хранилища.</li><li>Локальные тома, NFS, iSCSI: плюсы и минусы.</li><li>Облачные решения: EBS, Azure Disk, Google Persistent Disk.</li><li>Новые решения для хранения данных, на которые стоит обратить внимание.</li><li>Аспекты производительности: количество операций ввода-вывода в секунду, пропускная способность, задержка.</li><li>Советы по эффективному управлению хранилищем.</li><li>Соображения безопасности: контроль доступа и шифрование.</li><li>Стратегии резервного копирования и аварийного восстановления.</li><li>Масштабирование и управление ресурсами хранения.</li><li>Развивающаяся среда хранения данных в Kubernetes.</li><li>Поощрение исследований и непрерывного обучения.</li><
2360197
None
Read more...
Ошибка заголовка с нулевым значением: почему клиенты не получали пакеты в Spring Gateway
<h2 id="arjr5" name="The-Null-Value-Header-Bug:-Why-Clients-Didn't-Receive-Packets-in-Spring-Gateway">Ошибка заголовка с нулевым значением: почему клиенты этого не сделали t Получать пакеты в Spring Gateway</h2><li>Spring Boot: 2.2.6.RELEASE</li><li>Встроенное ядро Tomcat: 9.0.79</li><p>Эта проблема возникла в нашей службе шлюза API, которую мы создали с помощью Spring Gateway. Служба обрабатывает исключения, реализуя интерфейс <code>ErrorWebExceptionHandler</code>, возвращая клиенту детали обработанного исключения и добавляя некоторую информацию заголовка. Все работало хорошо, пока однажды после слияния кода не начали время от времени возникать проблемы. Вот что мы заметили:</p><p>Всякий раз, когда возникает исключение обработки запроса, оно обрабатывается с помощью <code>GatewayErrorWebExceptionHandler</code>. Однако, как ни странно, клиенты не получили никаких ответов. Наши журналы на стороне сервера выглядели нормально, но казалось, что соединение каким-то образом застопорилось, что не позволило клиентской стороне получить какую-либо обратную связь. Дальнейший анализ, в частности перехват пакетов, подтвердил наши подозрения: пакеты данных не передавались. Более глубокое изучение <code>GatewayErrorWebExceptionHandler</code> выявило несоответствие с идентификатором трассировки. В некоторых случаях этот идентификатор трассировки может отсутствовать. Примечательно, что, поскольку шлюз основан на WebFlux и Netty в качестве основной сетевой библиотеки, важно подчеркнуть, что Netty выполняет проверки на ноль при добавлении заголовков. Обнаружение нулевого значения вызывает исключение, что нам показалось нелогичным.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public class GatewayErrorWebExceptionHandler implements ErrorWebExceptionHandler { public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { ... String traceID = exchange.getRequest().getHeaders().getFirst("traceID"); exchange.getResponse().getHeaders().add("traceID", traceID); ... } }</code></pre><p>С помощью инструмента arthas был отслежен стек вызовов:</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">[arthas@3423878]$ stack *.GatewayErrorWebExceptionHandler *</code></pre><p>Было замечено, что базовый сервлет изменился на Tomcat вместо ожидаемого Netty:</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">[arthas@3423878]$ stack *.GatewayErrorWebExceptionHandler * Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 11) cost in 212 ms, listenerId: 1 ts=2023-07-29 19:01:14;thread_name=http-nio-8080-exec-1;id=20;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@6cc8c13c @com.xxx.server.gateway.filter.GatewayErrorWebExceptionHandler.handle() at org.springframework.web.server.handler.ExceptionHandlingWebHandler.lambda$handle$0(ExceptionHandlingWebHandler.java:77) ... at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) at reactor.core.publisher.Mono.subscribe(Mono.java:4210) at org.springframework.http.server.reactive.ServletHttpHandlerAdapter.service(ServletHttpHandlerAdapter.java:192) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:829)</code></pre><p>В ходе дальнейшего расследования было обнаружено, что пакет <code>tomcat-embed-core</code> был добавлен в зависимости проекта, что изменило базовый контейнер сервлетов Spring Gateway:</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0"><dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </dependency></code></pre><p>Впоследствии я предположил, мог ли Tomcat проглотить исключение нулевого указателя во время обработки. Пришло время углубиться в исходный код Tomcat: <a class="" href="/developer/tools/blog-entry?target=http%3A%2F%2Fhttp11processor.java%2F" rel="nofollow noopener" style=" color:#0052D9" target="_blank"><strong>Http11Processor.java</strong></a></p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">/** * When committing the response, we have to validate the set of headers, as * well as setup the response filters. */ @Override protected final void prepareResponse() throws IOException { ... // Build the response header try { outputBuffer.sendStatus(); int size = headers.size(); for (int i = 0; i < size; i++) { outputBuffer.sendHeader(headers.getName(i), headers.getValue(i)); } outputBuffer.endHeaders(); } catch (Throwable t) { ... outputBuffer.resetHeaderBuffer(); throw t; } outputBuffer.commit(); }</code></pre><p>Как и ожидалось, исключение может возникнуть в <code>headers.getValue(i)</code>. Более того, когда это исключение выбрасывается наружу, внешне обрабатываются только исключения ввода-вывода:</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public final void action(ActionCode actionCode, Object param) { switch (actionCode) { // 'Normal' servlet support case COMMIT: { if (!response.isCommitted()) { try { // Validate and write response headers prepareResponse(); } catch (IOException e) { handleIOException(e); } } break; } ... } private void handleIOException (IOException ioe) { if (ioe instanceof CloseNowException) { // Close the channel but keep the connection open setErrorState(ErrorState.CLOSE_NOW, ioe); } else { // Close the connection and all channels within that connection setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); } } public static void handleThrowable(Throwable t) { if (t instanceof ThreadDeath) { throw (ThreadDeath) t; } ... // All other instances of Throwable will be silently swallowed }</code></pre><p>Журналы не распечатываются, а исключения не выбрасываются. Соединение закрывается только при возникновении <code>IOException</code>. В данном случае это исключение нулевого указателя, которое объясняет, почему клиент не отвечает. Когда <code>OutputBuffer</code> очищает кеш, он просто устанавливает для <code>doFlush</code> значение false, эффективно поглощая исключение.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">@Override public void flush() throws IOException { doFlush(true); }</code></pre><p>Более того, класс реализации Spring Reactor для <code>AbstractListenerWriteFlushProcessor</code> Tomcat не обрабатывает событие при получении сигнала отправки. Ни одна из двух библиотек ничего не делает и не печатает журналы, что приводит к тому, что клиент постоянно ожидает ответа на запрос. Эту часть кода можно найти по адресу: <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fspring-projects%2Fspring-framework%2Fblob% 2Fv5.2.25.RELEASE%2Fspring-web%2Fsrc%2Fmain%2Fjava%2Forg%2Fspringframework%2Fhttp%2Fserver%2Freactive%2FAbstractListenerWriteFlushProcessor.java%23L194C20-L194C20" rel="nofollow noopener" style="color:#0052D9" target = "_blank">AbstractListenerWriteFlushProcessor.java</a></p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">try { processor.flush(); } catch (Throwable ex) { processor.flushingFailed(ex); return; }</code></pre><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public abstract class AbstractListenerWriteFlushProcessor<T> implements Processor<Publisher<? extends T>, Void> { /** * Invoked when an error happens while flushing. Sub-classes may choose * to ignore this if they know the underlying API will provide an error * notification in a container thread. * <p>Defaults to no-op. */ protected void flushingFailed(Throwable t) { } }</code></pre><p>По сравнению с WebMvc, при использовании Tomcat в качестве контейнера сервлетов стратегия обработки заголовков следующая: заголовки с нулевыми значениями напрямую отфильтровываются во время процесса фильтрации: <a class="" href="/developer/tools/blog -entry?target=http%3A%2F%2Fresponse.java%2F" rel="nofollow noopener" style="color:#0052D9" target="_blank">Response.java</a></p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">private void addHeader(String name, String value, Charset charset) { if (name == null || name.length() == 0 || value == null) { return; } ... }</code></pre><p>Однако эта операция фильтрации существует только в <strong>цепочке обработки Spring MVC.</strong> В этом случае проект шлюза использует <code>WebFlux</code>. Таким образом, когда заголовок <code>traceID</code> с нулевым значением игнорируется, Tomcat сталкивается с исключением нулевого указателя при подготовке к записи буферизованных данных в сокет. Это исключение поглощается внутренне, в результате чего соединение остается открытым неопределенное время без записи каких-либо данных.</p><li>Удалите зависимость <code>tomcat-embed-core</code> из общего модуля и введите только <code>java-servlet-api</code>, что позволит Spring Gateway вернуться к использованию Netty в качестве базового сервер.</li><li>В <code>GatewayErrorWebExceptionHandler</code> выполните проверку нуля для <code>traceID</code>, чтобы предотвратить добавление пустых заголовков.</li><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">public class GatewayErrorWebExceptionHandler implements ErrorWebExceptionHandler { ... public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { ... String traceID = exchange.getRequest().getHeaders().getFirst("traceID"); if(traceID != null){ exchange.getResponse().getHeaders().add("traceID", traceID); } } }</code></pre><p>Этот случай подчеркивает важность понимания технического стека и четкого понимания зависимостей проекта. Только так мы сможем быстро обнаружить и решить проблемы, когда они возникнут. Кроме того, тестирование подтвердило, что <code>подъем</code> не вызывает этой проблемы. Это связано с тем, что рассматриваемая версия Spring перегрузила <code>flushingFailed</code> для класса реализации <code>AbstractListenerWriteFlushProcessor</code> <code>undertow</code>. Таким образом только Tomcat обрабатывает внутренние нулевые указатели.</p><p>Однако два года назад кто-то уже <a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fgithub.com%2Fspring-projects%2Fspring-framework% 2Fcommit%2F5e5d8e4a2314b06e7318865016758774f36f2a1d" rel="nofollow noopener" style="color:#0052D9" target="_blank">исправлено</a> это <a class="" href="/developer/tools/blog-entry?target= https%3A%2F%2Fgithub.com%2Fspring-projects%2Fspring-framework%2Fissues%2F26434" rel="nofollow noopener" style="color:#0052D9" target="_blank">проблема</a>. Но версия в нашем проекте устарела.</p><p>Это на самом деле отражает проблему:</p><li>Между версиями библиотек с открытым исходным кодом, особенно такими платформами, как Spring, существуют существенные различия. Взаимодействие между ними и базовыми контейнерами сервлетов может меняться с обновлениями версий, о чем разработчикам необходимо знать в процессе разработки.</li><
2360196
None
Read more...
Внутри сети Linux: исследование IPVS и IPTABLES на уровне кода
<h2 id="eb44p" name="Внутри-Linux-Networking:-A-Code-Level-Exploration-of-IPVS-and-IPTABLES">Внутри сети Linux: исследование IPVS и IPTABLES на уровне кода</h2 ><li>Краткий обзор сетей Linux.</li><li>Важность маршрутизации и фильтрации пакетов.</li><li>Что такое IPVS и его исторический контекст.</li><li>Основные функции IPVS.</li><li>Структура кода и ключевые компоненты.</li><li>Пошаговое описание прохождения типичного пакета через IPVS.</li><li>Используемые алгоритмы и стратегии (раунд-робин, наименьшее соединение и т. д.)</li><li>Роль и значение IPTABLES в сетях Linux.</li><li>Историческая эволюция и ее место в современных системах.</li><li>Понимание ключевых файлов и модулей.</li><li>Отслеживание потока пакетов через цепочки IPTABLES.</li><li>Изучение соответствия и целевых расширений.</li><li>Основные различия и сходства.</li><li>Примеры использования: когда какой использовать?</li><li>Реальные тесты производительности.</li><li>Соображения масштабируемости.</li><li>Распространенные ошибки и проблемы при работе с IPVS и IPTABLES.</li><li>Отзывы и критика сообщества.</li><li>Новые тенденции и инструменты.</li><li>Эволюция сетевых инструментов в Linux.</li><li>Подведение итогов исследования.</li><li>Поощрение практического изучения и дальнейшего изучения.</li><
2360195
None
Read more...
В чем разница между блокировкой и неблокировкой, синхронизацией и асинхронностью?
<h2 id="fvj8a" name="В чем-разница-между-блокировкой-и-не-блокировкой-и-синхронизацией-и-асинхронной?">В чем разница между блокировкой и неблокировкой и синхронизацией и асинхронностью? </h2><p>При разработке приложений мы часто сталкиваемся с такими терминами, как «блокировка», «неблокировка», «синхронный» и «асинхронный». Считать эти понятия синонимами — распространенное заблуждение. На самом деле они представляют собой отдельные, хотя и переплетенные, концепции.</p><p>Одна из частых путаниц — между «Блокировкой» и «Синхронностью», а также между «Неблокировкой» и «Асинхронностью».</p><p>По сути:</p><li>В «синхронных» и «асинхронных» процессах участвуют как минимум два субъекта. Когда продолжительность их задач совпадает, это «синхронно»; если нет, то это «Асинхронный».</li><li>"Блокировка" и "Неблокировка" описывают, как системы справляются с задачами. Эта терминология в основном применяется к операциям ввода-вывода.</li><p>Давайте углубимся в эти понятия более подробно.</p><p>Суть этого различия заключается в том, как система реагирует на ожидание другого процесса.</p><li><strong>Блокировка</strong>: система ожидает завершения другого процесса, прежде чем возобновить выполнение задачи. Представьте себе Java JDBC, запрашивающий базу данных — он ждет ответа.</li><li><strong>Неблокируемый</strong>: система продолжает свою работу независимо от других процессов. Оно не ждет.</li><p>При рассмотрении нескольких субъектов, выполняющих задачи:</p><li><strong>Синхронно</strong>: задачи синхронизируются, начинаются или заканчиваются одновременно.</li><li><strong>Асинхронный</strong>: время начала и окончания задачи не зависит друг от друга.</li><p>При вызове функции ввода-вывода:</p><li><strong>Блокировка</strong>: ожидание завершения процесса перед возвратом.</li><li><strong>Неблокируемый</strong>: возвращается немедленно, независимо от того, завершена ли задача.</li><p>Что касается того, кто контролирует выполнение задач для функции ввода-вывода:</p><li><strong>Синхронный</strong>: управляется приложением.</li><li><strong>Асинхронный</strong>: контролируется ядром.</li><p>На основе комбинаций «Блокировка/Неблокировка» и «Синхронный/Асинхронный режим» четыре результирующих квадранта показаны на диаграмме ниже:</p><li><strong>Синхронная блокировка ввода-вывода</strong></li><p>Это самый простой метод ввода-вывода. Когда вы совершаете звонок, программа ожидает завершения операции, прежде чем продолжить.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">#include <iostream> #include <fstream> int main() { std::ifstream file("example.txt"); std::string content; // This line blocks until the entire file is read std::getline(file, content, '\0'); std::cout << content; file.close(); return 0; }</code></pre><li><strong>Синхронный неблокирующий ввод-вывод</strong></li><p>В этом режиме система будет регулярно проверять (или опрашивать) наличие данных. В противном случае он будет продолжать делать что-то другое.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">// This is a simplified example. True non-blocking I/O in C++ can be complex. // Assuming a non-blocking I/O library function 'try_read' /* bool try_read(std::ifstream& file, std::string& content); */ int main() { std::ifstream file("example.txt"); std::string content; while (!try_read(file, content)) { // Do other tasks or sleep for a while } std::cout << content; file.close(); return 0; }</code></pre><li><strong>Асинхронный блокирующий ввод-вывод</strong></li><p>Это звучит противоречиво, но это можно рассматривать как асинхронный запуск операции ввода-вывода, но после запуска эта конкретная операция ввода-вывода будет блокироваться до завершения. Это часто используется с мультиплексированием ввода-вывода.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">// An example using pseudo-code, as actual implementations vary. // Assuming a function 'async_read' that starts reading and blocks until it completes. /* void async_read(std::ifstream& file, void (*callback)(std::string content)); */ void print_content(std::string content) { std::cout << content; } int main() { std::ifstream file("example.txt"); async_read(file, print_content); // Do other tasks while I/O is ongoing file.close(); return 0; }</code></pre><li><strong>Асинхронный неблокирующий ввод-вывод (AIO)</strong>:</li><p>В этом режиме запускается операция ввода-вывода, и управление немедленно возвращается, позволяя программе продолжать выполнение последующих операторов без ожидания.</p><pre class="prism-token token language-javascript"><code class="line-numbers language-javascript" style="margin-left:0">// Assuming a library function 'async_read_nonblocking' /* void async_read_nonblocking(std::ifstream& file, void (*callback)(std::string content)); */ void print_content(std::string content) { std::cout << content; } int main() { std::ifstream file("example.txt"); async_read_nonblocking(file, print_content); // Do other tasks immediately without waiting for the I/O to complete // Wait or poll for the asynchronous I/O to complete if needed file.close(); return 0; }</code></pre><p>Эти концепции вращаются вокруг того, как взаимодействуют приложения и ядра. Чтобы различать их, необходимо понимать разницу между доменами приложения и ядра. Просмотр приведенных выше объяснений, связанных с ними диаграмм и примеров кода может дать более четкое представление.</p><li><a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FAsynchronous_I%2FO" rel="nofollow noopener" style=" color:#0052D9" target="_blank">Википедия – асинхронный ввод-вывод</a></li><li><a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fwww.tornadoweb.org%2Fen%2Fstable%2Fguide%2Fasync.html" rel="nofollow noopener " style="color:#0052D9" target="_blank">Асинхронный и неблокирующий ввод-вывод</a></li><li><a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F2625493%2Fasynchronous-and-non-blocking-calls-also-between -blocking-and-synchronous" rel="nofollow noopener" style="color:#0052D9" target="_blank">Обсуждение переполнения стека</a></li><li><a class="" href="/developer/tools/blog-entry?target=https%3A%2F%2Finterconnection.tistory.com%2F141" rel="nofollow noopener" style="color:#0052D9 " target="_blank">Блокирующий или неблокирующий, синхронный и асинхронный</a></li><
2360194
None
Read more...
Сеть Kubernetes: от основ к лучшим практикам
<h2 id="6sp76" name="Kubernetes-Networking:-From-Basics-to-Best-Practices">Сетевые сети Kubernetes: от основ к лучшим практикам</h2><li>Важность Kubernetes в современных облачных архитектурах.</li><li>Центральное место в сети K8s.</li><li>Сеть Pod.</li><li>Сервисная сеть.</li><li>Механизмы входа и выхода.</li><li>Сетевые политики.</li><li>Обзор распространенных сетевых плагинов (Calico, Flannel, Cilium и т. д.).</li><li>Как работают эти плагины.</li><li>Преимущества и недостатки каждого решения.</li><li>Роль и функционирование kube-proxy.</li><li>Важность и конфигурация CoreDNS.</li><li>Применение и примеры сетевых политик.</li><li>Сетевая безопасность: использование TLS, сетевых политик и т. д.</li><li>Межкластерная сеть.</li><li>Service Mesh (например, Istio, Linkerd) и их роли в K8s.</li><li>Балансировка нагрузки и обнаружение сервисов.</li><li>Проблемы с производительностью сети.</li><li>Стратегии оптимизации сети K8s.</li><li>Устранение неполадок и мониторинг сети.</li><li>Реализация сети K8s в настройках предприятия или проекта.</li><li>Распространенные сетевые ошибки и их решения.</li><li>Лучшие практики работы в сети K8s.</li><li>Предстоящие тенденции в сетевых технологиях Kubernetes.</li><li>Новые технологии и решения в этой области.</li><li>Подтверждаем важность и проблемы сетей K8.</li><li>Поощрение дальнейших исследований и исследований.</li><
2360193
None
Read more...