Исправление форматирования
This commit is contained in:
parent
b4b8f83b1f
commit
d0de9bc884
@ -9,13 +9,13 @@ parents:
|
|||||||
- "[[Реактивное программирование]]"
|
- "[[Реактивное программирование]]"
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
По сути, Event Loop - это реализация [шаблона Reactor](http://design-pattern.ru/patterns/reactor.html). Является неблокирующим потоком ввода-вывода, который работает непрерывно. Его основная задача — проверка новых событий. И как только событие пришло перенаправлять его тому, кто в данный момент может его обработать. Иногда их может быть несколько для увеличения производительности.
|
По сути, Event Loop - это реализация [шаблона Reactor](http://design-pattern.ru/patterns/reactor.html). Является неблокирующим потоком ввода-вывода, который работает непрерывно. Его основная задача — проверка новых событий. И как только событие пришло перенаправлять его тому, кто в данный момент может его обработать. Иногда их может быть несколько для увеличения производительности.
|
||||||
|
|
||||||
![](../../meta/files/images/Pasted%20image%2020231026115508.png)
|
![](../../meta/files/images/Pasted%20image%2020231026115508.png)
|
||||||
|
|
||||||
Выше приведён абстрактный дизайн цикла событий, который представляет идеи реактивного асинхронного программирования:
|
Выше приведён абстрактный дизайн цикла событий, который представляет идеи реактивного асинхронного программирования:
|
||||||
|
|
||||||
- Цикл событий выполняется непрерывно в одном потоке, хотя у нас может быть столько циклов событий, сколько доступно [[../fundamental/Ядро процессора|ядер]].
|
- Цикл событий выполняется непрерывно в одном потоке, хотя у нас может быть столько циклов событий, сколько доступно [[../fundamental/Ядро процессора|ядер]].
|
||||||
- Цикл событий последовательно обрабатывает события из очереди событий и возвращается сразу после регистрации [[../../../../_inbox/Callback|обратного вызова]] в платформе.
|
- Цикл событий последовательно обрабатывает события из очереди событий и возвращается сразу после регистрации [[../../../../_inbox/Callback|обратного вызова]] в платформе.
|
||||||
- Платформа может инициировать завершение операции, такой как вызов базы данных или вызов внешней службы.
|
- Платформа может инициировать завершение операции, такой как вызов базы данных или вызов внешней службы.
|
||||||
- Цикл событий может запускать обратный вызов при уведомлении о завершении операции и отправлять результат обратно исходному вызывающему.
|
- Цикл событий может запускать обратный вызов при уведомлении о завершении операции и отправлять результат обратно исходному вызывающему.
|
||||||
|
@ -13,7 +13,7 @@ linked: []
|
|||||||
|
|
||||||
Самый простой способ побороть эту проблему, это использовать fingerprint файла. То есть, когда файл меняется, вы меняете его название. Делается это обычно добавлением какого-нибудь префикса/суфикса к названию файла.
|
Самый простой способ побороть эту проблему, это использовать fingerprint файла. То есть, когда файл меняется, вы меняете его название. Делается это обычно добавлением какого-нибудь префикса/суфикса к названию файла.
|
||||||
|
|
||||||
Например у нас есть файл стилей `style.css`, мы можем посчитать для него [[../cryptography/MD5|MD5]] хеш и добавить его в название. Тогда у нас получится следующее название: `style.e626dd36e0085927f334adbe3eb38e7a.css`.
|
Например у нас есть файл стилей `style.css`, мы можем посчитать для него [[../cryptography/MD5|MD5]] хеш и добавить его в название. Тогда у нас получится следующее название: `style.e626dd36e0085927f334adbe3eb38e7a.css`.
|
||||||
|
|
||||||
При любом изменении файла [[../cryptography/MD5|MD5]] хеш должен пересчитываться. Таким образом при изменении файла у него будет другое название, и браузер будет вынужден скачать его в любом случае.
|
При любом изменении файла [[../cryptography/MD5|MD5]] хеш должен пересчитываться. Таким образом при изменении файла у него будет другое название, и браузер будет вынужден скачать его в любом случае.
|
||||||
***
|
***
|
||||||
|
@ -18,7 +18,7 @@ linked:
|
|||||||
sudo mkdir -p /var/nginx/cache
|
sudo mkdir -p /var/nginx/cache
|
||||||
```
|
```
|
||||||
|
|
||||||
Чтобы включить кэширование, нужно прописать несколько директив в основной конфигурации `nginx.conf`.
|
Чтобы включить кэширование, нужно прописать несколько директив в основной конфигурации `nginx.conf`.
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
http {
|
http {
|
||||||
@ -29,16 +29,16 @@ http {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`proxy_cache_path` указывает путь в файловой системе.
|
`proxy_cache_path` указывает путь в файловой системе.
|
||||||
|
|
||||||
Не кэшируйте HTTP-ответы при первом обращении. Используйте `proxy_cache_min_uses 2`, чтобы кэшировать только те элементы, к которым обращались более одного раза. Таким образом, вы уменьшите нагрузку прокси-кэша на запись и предотвратите заполнение кэша содержимым, к которому редко обращаются.
|
Не кэшируйте HTTP-ответы при первом обращении. Используйте `proxy_cache_min_uses 2`, чтобы кэшировать только те элементы, к которым обращались более одного раза. Таким образом, вы уменьшите нагрузку прокси-кэша на запись и предотвратите заполнение кэша содержимым, к которому редко обращаются.
|
||||||
|
|
||||||
Ключ кэширования Nginx по умолчанию не очень хорошо работает с сайтами с несколькими поддоменами. Вы можете настроить ключ кэширования, задав proxy_cache_key. В своей конфигурации я использую вот такой ключ: `proxy_cache_key $scheme$host$uri$is_args$args;`
|
Ключ кэширования Nginx по умолчанию не очень хорошо работает с сайтами с несколькими поддоменами. Вы можете настроить ключ кэширования, задав proxy_cache_key. В своей конфигурации я использую вот такой ключ: `proxy_cache_key $scheme$host$uri$is_args$args;`
|
||||||
|
|
||||||
## Переносим кэш Nginx в RAM
|
## Переносим кэш Nginx в RAM
|
||||||
Можно значительно ускорить кэш, если смонтировать его не в файловую систему а в RAM.
|
Можно значительно ускорить кэш, если смонтировать его не в файловую систему а в RAM.
|
||||||
|
|
||||||
Для этого также создаем папку для кэша, можно использовать ту же, но ее нужно очистить от папок. Далее монтируем созданный каталог в RAM с помощью команды [tmpfs](https://wiki.archlinux.org/index.php/Tmpfs), выделяя 256 мегабайт под кэш:
|
Для этого также создаем папку для кэша, можно использовать ту же, но ее нужно очистить от папок. Далее монтируем созданный каталог в RAM с помощью команды [tmpfs](https://wiki.archlinux.org/index.php/Tmpfs), выделяя 256 мегабайт под кэш:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo mount -t tmpfs -o size=256M tmpfs /var/nginx/cache
|
sudo mount -t tmpfs -o size=256M tmpfs /var/nginx/cache
|
||||||
@ -50,7 +50,7 @@ sudo mount -t tmpfs -o size=256M tmpfs /var/nginx/cache
|
|||||||
sudo umount /var/nginx/cache
|
sudo umount /var/nginx/cache
|
||||||
```
|
```
|
||||||
|
|
||||||
Чтобы автоматически пересоздать каталог к'ша в RAM после перезагрузки сервера, нам нужно обновить файл `/etc/fstab`. Добавьте в него следующую строку:
|
Чтобы автоматически пересоздать каталог к'ша в RAM после перезагрузки сервера, нам нужно обновить файл `/etc/fstab`. Добавьте в него следующую строку:
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
tmpfs /var/nginx/cache tmpfs defaults,size=256M 0 0
|
tmpfs /var/nginx/cache tmpfs defaults,size=256M 0 0
|
||||||
|
@ -22,7 +22,7 @@ linked:
|
|||||||
![](../../meta/files/images/Pasted%20image%2020240319200211.png)
|
![](../../meta/files/images/Pasted%20image%2020240319200211.png)
|
||||||
|
|
||||||
## Почему простаивание потока — это проблема?
|
## Почему простаивание потока — это проблема?
|
||||||
Каждый поток нуждается в памяти для хранения своего стека вызовов и других связанных с ним структур данных. ==Когда поток простаивает, он продолжает потреблять ресурсы для поддержания своего состояния.==
|
Каждый поток нуждается в памяти для хранения своего стека вызовов и других связанных с ним структур данных. ==Когда поток простаивает, он продолжает потреблять ресурсы для поддержания своего состояния.==
|
||||||
|
|
||||||
Кроме того, процессорное время, которое выделяется неработающим потокам, могло бы быть использовано для других задач. Если большое количество потоков простаивает, это может привести к увеличению загрузки процессора и снижению производительности, так как операционная система будет тратить больше времени на переключение между потоками.
|
Кроме того, процессорное время, которое выделяется неработающим потокам, могло бы быть использовано для других задач. Если большое количество потоков простаивает, это может привести к увеличению загрузки процессора и снижению производительности, так как операционная система будет тратить больше времени на переключение между потоками.
|
||||||
## Заметки
|
## Заметки
|
||||||
|
@ -9,10 +9,10 @@ zero-link:
|
|||||||
parents:
|
parents:
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Циклические зависимости между сервисами возникают, когда сервисы взаимно внедряются друг в друга. Например, сервис А внедряет сервис Б, но в тоже время сервис Б внедряет сервис А. В этом случае [SpringBoot](../../meta/zero/00%20SpringBoot.md) и [Quarkus](../../meta/zero/00%20Quarkus.md) не знают, как создать такие бины и внедрить их друг в друга.
|
Циклические зависимости между сервисами возникают, когда сервисы взаимно внедряются друг в друга. Например, сервис А внедряет сервис Б, но в тоже время сервис Б внедряет сервис А. В этом случае [SpringBoot](../../meta/zero/00%20SpringBoot.md) и [Quarkus](../../meta/zero/00%20Quarkus.md) не знают, как создать такие бины и внедрить их друг в друга.
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Обычно такая ситуация сигнализирует о плохо продуманной архитектуре приложения.
|
> Обычно такая ситуация сигнализирует о плохо продуманной архитектуре приложения.
|
||||||
|
|
||||||
Пример циклической зависимости в Spring:
|
Пример циклической зависимости в Spring:
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ public class ServiceTwo {
|
|||||||
|
|
||||||
Вот что вы можете с этим сделать:
|
Вот что вы можете с этим сделать:
|
||||||
## Пересмотреть архитектуру приложения
|
## Пересмотреть архитектуру приложения
|
||||||
==Это предпочтительный вариант.== Возможно вам стоит создать сервис В, который внедрит в себя сервисы А и Б. В таком случае вы распутаете циклическую зависимость.
|
==Это предпочтительный вариант.== Возможно вам стоит создать сервис В, который внедрит в себя сервисы А и Б. В таком случае вы распутаете циклическую зависимость.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Service
|
@Service
|
||||||
@ -75,7 +75,7 @@ public class ServiceTwo {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
## Ленивое внедрение
|
## Ленивое внедрение
|
||||||
В Spring вы можете указать аннотацию `@Lazy` у аргумента конструктора одного их сервисов. Таким образом сначала будет создан один сервис, для второго сервиса спринг создаст прокси класс, создаст из него бин и внедрит его в ваш сервис. После чего создаст второй сервис и внедрит туда уже созданный первый. А далее заменит ссылку с прокси объекта на второй сервис.
|
В Spring вы можете указать аннотацию `@Lazy` у аргумента конструктора одного их сервисов. Таким образом сначала будет создан один сервис, для второго сервиса спринг создаст прокси класс, создаст из него бин и внедрит его в ваш сервис. После чего создаст второй сервис и внедрит туда уже созданный первый. А далее заменит ссылку с прокси объекта на второй сервис.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Service
|
@Service
|
||||||
|
@ -19,13 +19,13 @@ linked:
|
|||||||
ssh-keygen -t ed25519-sk -O resident -O application=ssh:key_name -f ~/.ssh/key_name
|
ssh-keygen -t ed25519-sk -O resident -O application=ssh:key_name -f ~/.ssh/key_name
|
||||||
```
|
```
|
||||||
|
|
||||||
Все как с обычными SSH ключами, появится 2 файла в папке ssh `key_name` и `key_name.pub`. Только вот, воспользоваться секретным ключом без подключения аппаратного ([Yubikey](Yubikey.md)) не выйдет.
|
Все как с обычными SSH ключами, появится 2 файла в папке ssh `key_name` и `key_name.pub`. Только вот, воспользоваться секретным ключом без подключения аппаратного ([Yubikey](Yubikey.md)) не выйдет.
|
||||||
|
|
||||||
Флаги:
|
Флаги:
|
||||||
- `-O verify-required`. Потребует вводить пароль от аппаратного ключа для доступа к SSH ключу.
|
- `-O verify-required`. Потребует вводить пароль от аппаратного ключа для доступа к SSH ключу.
|
||||||
- `-O application=ssh:key_name`. Позволяет установить название ключу, которое можно будет увидеть в приложении Yubico Authentification. ![](../../meta/files/images/Pasted%20image%2020240113100105.png)
|
- `-O application=ssh:key_name`. Позволяет установить название ключу, которое можно будет увидеть в приложении Yubico Authentification. ![](../../meta/files/images/Pasted%20image%2020240113100105.png)
|
||||||
|
|
||||||
Такой ключ подойдет и для доступа к репозиториям. Но необходимо будет прописать в `~/.ssh/config` информацию о том, какой ключ использовать:
|
Такой ключ подойдет и для доступа к репозиториям. Но необходимо будет прописать в `~/.ssh/config` информацию о том, какой ключ использовать:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
Host github.com
|
Host github.com
|
||||||
|
@ -74,7 +74,7 @@ MySQL не решает из коробки проблемы кластериз
|
|||||||
***
|
***
|
||||||
|
|
||||||
- В InnoDB, заметьте, т.е. у нас архитектура разделяет репликацию выше, а storage engine ниже. Но storage engine, для того, чтобы репликация работала, должен, грубо говоря, замедлять insert'ы в таблицу.
|
- В InnoDB, заметьте, т.е. у нас архитектура разделяет репликацию выше, а storage engine ниже. Но storage engine, для того, чтобы репликация работала, должен, грубо говоря, замедлять insert'ы в таблицу.
|
||||||
- Другая проблема состоит в том, что мастер выполняет запросы параллельно, т.е. одновременно, а слэйв их может применять последовательно. Возникает вопрос – а почему слэйв не может применять их параллельно? На самом деле, с этим все непросто. Есть теорема о сериализации транзакций, которая рассказывает, когда мы можем выполнять запросы параллельно, а когда последовательно. Это отдельная сложная тема, разберитесь в ней, если вам интересно и нужно, например, почитав по ссылке – [http://plumqqz.livejournal.com/387380.html](http://plumqqz.livejournal.com/387380.html).
|
- Другая проблема состоит в том, что мастер выполняет запросы параллельно, т.е. одновременно, а слэйв их может применять последовательно. Возникает вопрос – а почему слэйв не может применять их параллельно? На самом деле, с этим все непросто. Есть теорема о сериализации транзакций, которая рассказывает, когда мы можем выполнять запросы параллельно, а когда последовательно. Это отдельная сложная тема, разберитесь в ней, если вам интересно и нужно, например, почитав по ссылке – [http://plumqqz.livejournal.com/387380.html](http://plumqqz.livejournal.com/387380.html).
|
||||||
- В MySQL репликация упирается в процессор. Это прекрасная картинка – большой, мощный сервер, 12 ядер. Работает одно ядро, заодно занято репликацией. Из-за этого реплика задыхается. Это очень грустно.
|
- В MySQL репликация упирается в процессор. Это прекрасная картинка – большой, мощный сервер, 12 ядер. Работает одно ядро, заодно занято репликацией. Из-за этого реплика задыхается. Это очень грустно.
|
||||||
|
|
||||||
Для того чтобы выполнять запросы параллельно существует группировка запросов. В InnoDB есть специальная опция, которая управляет тем, как именно мы группируем транзакции, как именно мы их пишем на диск. Проблема в том, что мы можем их сгруппировать на уровне InnoDB, а уровнем выше – на уровне репликации – этой функциональности не было. В 2010 г. Кристиан Нельсен из MariaDB реализовал такую фичу, которая называется Group Binary Log Commit. Получается, мы журнал повторяем на двух уровнях – Storage Engine и репликация, и нам нужно таскать фичи из одного уровня на другой. Это сложный механизм. Более того, нам нужно одновременно консистентно писать сразу в два журнала – two-phase-commit. Это еще хуже.
|
Для того чтобы выполнять запросы параллельно существует группировка запросов. В InnoDB есть специальная опция, которая управляет тем, как именно мы группируем транзакции, как именно мы их пишем на диск. Проблема в том, что мы можем их сгруппировать на уровне InnoDB, а уровнем выше – на уровне репликации – этой функциональности не было. В 2010 г. Кристиан Нельсен из MariaDB реализовал такую фичу, которая называется Group Binary Log Commit. Получается, мы журнал повторяем на двух уровнях – Storage Engine и репликация, и нам нужно таскать фичи из одного уровня на другой. Это сложный механизм. Более того, нам нужно одновременно консистентно писать сразу в два журнала – two-phase-commit. Это еще хуже.
|
||||||
|
@ -59,7 +59,7 @@ Logical Decoding – способ визуализировать то, что н
|
|||||||
### Дополнительные материалы
|
### Дополнительные материалы
|
||||||
- [[Настройка репликации в PostgreSQL]]
|
- [[Настройка репликации в PostgreSQL]]
|
||||||
- [BDR User Guide - PostgreSQL wiki](https://wiki.postgresql.org/wiki/Logical_Log_Streaming_Replication)
|
- [BDR User Guide - PostgreSQL wiki](https://wiki.postgresql.org/wiki/Logical_Log_Streaming_Replication)
|
||||||
- [PostgreSQL: Documentation: 16: Chapter 31. Logical Replication](https://www.postgresql.org/docs/current/logical-replication.html)
|
- [PostgreSQL: Documentation: 16: Chapter 31. Logical Replication](https://www.postgresql.org/docs/current/logical-replication.html)
|
||||||
- [PostgreSQL: Documentation: 9.4: Logical Decoding](https://www.postgresql.org/docs/9.4/logicaldecoding.html). Аналог [libslave](libslave.md) в MySQL
|
- [PostgreSQL: Documentation: 9.4: Logical Decoding](https://www.postgresql.org/docs/9.4/logicaldecoding.html). Аналог [libslave](libslave.md) в MySQL
|
||||||
- [Отладка и устранение проблем в PostgreSQL Streaming Replication / Хабр](https://m.habr.com/ru/company/oleg-bunin/blog/414111/)
|
- [Отладка и устранение проблем в PostgreSQL Streaming Replication / Хабр](https://m.habr.com/ru/company/oleg-bunin/blog/414111/)
|
||||||
- [An Overview of Logical Replication in PostgreSQL | Severalnines](https://severalnines.com/blog/overview-logical-replication-postgresql/)
|
- [An Overview of Logical Replication in PostgreSQL | Severalnines](https://severalnines.com/blog/overview-logical-replication-postgresql/)
|
||||||
|
@ -14,7 +14,7 @@ linked:
|
|||||||
|
|
||||||
Для решения этой проблемы нужно изменить подсеть Docker по умолчанию. Таким образом, вы можете выбрать те подсети, которые не конфликтует с вашей корпоративной сетью.
|
Для решения этой проблемы нужно изменить подсеть Docker по умолчанию. Таким образом, вы можете выбрать те подсети, которые не конфликтует с вашей корпоративной сетью.
|
||||||
|
|
||||||
Откройте файл настроек `/etc/docker/daemon.json` и введите IP-адрес сетевой маски:
|
Откройте файл настроек `/etc/docker/daemon.json` и введите IP-адрес сетевой маски:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ zero-link:
|
|||||||
parents:
|
parents:
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Гайдов, как устанавливать docker полно в интернете. [Официальная документации](https://docs.docker.com/engine/install/) написана доступным языком.
|
Гайдов, как устанавливать docker полно в интернете. [Официальная документации](https://docs.docker.com/engine/install/) написана доступным языком.
|
||||||
|
|
||||||
Команды установки docker для CentOS 8 и RHEL 8.
|
Команды установки docker для CentOS 8 и RHEL 8.
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ chmod +x ~/.docker/cli-plugins/docker-compose
|
|||||||
[Актуальная версия docker-compose](https://github.com/docker/compose/releases/)
|
[Актуальная версия docker-compose](https://github.com/docker/compose/releases/)
|
||||||
|
|
||||||
> [!INFO]
|
> [!INFO]
|
||||||
> Эта команда устанавливает Compose V2 для активного пользователя в каталог `$HOME`. Чтобы установить Docker Compose для всех пользователей вашей системы, замените `~/.docker/cli-plugins` на `/usr/local/lib/docker/cli-plugins`.
|
> Эта команда устанавливает Compose V2 для активного пользователя в каталог `$HOME`. Чтобы установить Docker Compose для всех пользователей вашей системы, замените `~/.docker/cli-plugins` на `/usr/local/lib/docker/cli-plugins`.
|
||||||
|
|
||||||
Проверяем, что установка прошла успешно.
|
Проверяем, что установка прошла успешно.
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ Docker Compose 2.2.3
|
|||||||
```
|
```
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Также обращаю ваше внимание, что в Compose V1 для работы использовалась команда `docker-compose`, а в V2 отказались от дефиса `docker compose`
|
> Также обращаю ваше внимание, что в Compose V1 для работы использовалась команда `docker-compose`, а в V2 отказались от дефиса `docker compose`
|
||||||
|
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
|
@ -12,7 +12,7 @@ linked:
|
|||||||
|
|
||||||
В такие моменты главное не поддаваться панике 😅
|
В такие моменты главное не поддаваться панике 😅
|
||||||
|
|
||||||
В Idea есть [замечательная функция LocalHisotry](https://www.jetbrains.com/help/idea/local-history.html), которая автоматически сохраняет все изменения над файлами. Если затертых файлов было не много, то нажмите ПКМ и в меню выберете `Local History —> Show History`.
|
В Idea есть [замечательная функция LocalHisotry](https://www.jetbrains.com/help/idea/local-history.html), которая автоматически сохраняет все изменения над файлами. Если затертых файлов было не много, то нажмите ПКМ и в меню выберете `Local History —> Show History`.
|
||||||
|
|
||||||
![](../../meta/files/images/Pasted%20image%2020240908122428.png)
|
![](../../meta/files/images/Pasted%20image%2020240908122428.png)
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ linked:
|
|||||||
---
|
---
|
||||||
Когда-то давным давно скачал [JDK](JDK.md), работает и ладно. Посмотрел доклад про [нативные сборки](Нативные%20сборки%20в%20Java.md), и там упоминалось про [JDK](JDK.md) для Apple Silicon. Решил проверить, а такой ли у меня. Оказалось не такой.
|
Когда-то давным давно скачал [JDK](JDK.md), работает и ладно. Посмотрел доклад про [нативные сборки](Нативные%20сборки%20в%20Java.md), и там упоминалось про [JDK](JDK.md) для Apple Silicon. Решил проверить, а такой ли у меня. Оказалось не такой.
|
||||||
|
|
||||||
В итоге вот сколько собирался большой [монолит](../../../../_inbox/Монолитная%20архитектура.md) (с генерацией javadoc), состоящий из 22 модуля на обычной [JDK](JDK.md). Все зависимости были закачены заранее и сборка была запущена в [многопоточном режиме](Параллельная%20сборка%20модулей%20в%20Maven.md).
|
В итоге вот сколько собирался большой [монолит](../../../../_inbox/Монолитная%20архитектура.md) (с генерацией javadoc), состоящий из 22 модуля на обычной [JDK](JDK.md). Все зависимости были закачены заранее и сборка была запущена в [многопоточном режиме](Параллельная%20сборка%20модулей%20в%20Maven.md).
|
||||||
|
|
||||||
![](../../meta/files/images/Pasted%20image%2020240908115826.png)
|
![](../../meta/files/images/Pasted%20image%2020240908115826.png)
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ zero-link:
|
|||||||
parents:
|
parents:
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Столкнулся с неочевидным поведением `@ElementCollection` в связке с `@OneToMany`. Может случиться так, что в `@OneToMany` будет дублирование значений из-за `@ElementCollection`. Проще объяснить на примере.
|
Столкнулся с неочевидным поведением `@ElementCollection` в связке с `@OneToMany`. Может случиться так, что в `@OneToMany` будет дублирование значений из-за `@ElementCollection`. Проще объяснить на примере.
|
||||||
|
|
||||||
Допустим у нас есть три таблицы: `user`, `user_nickname`, `address`. Есть сущность `User`:
|
Допустим у нас есть три таблицы: `user`, `user_nickname`, `address`. Есть сущность `User`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Entity
|
@Entity
|
||||||
@ -37,15 +37,15 @@ public class User {
|
|||||||
|
|
||||||
Допустим у нас одна запись про пользователя, у которого есть три адреса и один никнейм. В этом случае все хорошо, все придет корректно.
|
Допустим у нас одна запись про пользователя, у которого есть три адреса и один никнейм. В этом случае все хорошо, все придет корректно.
|
||||||
|
|
||||||
==Добавим этому пользователю еще один никнейм. Теперь мы получаем шесть адресов и два никнейма. Откуда взялись еще три лишних адреса, в базе данных их все еще три.== Это дубликаты. При этом, если вы воспользуетесь пагинацией JPA, то дублей уже не будет. It is magic 💫
|
==Добавим этому пользователю еще один никнейм. Теперь мы получаем шесть адресов и два никнейма. Откуда взялись еще три лишних адреса, в базе данных их все еще три.== Это дубликаты. При этом, если вы воспользуетесь пагинацией JPA, то дублей уже не будет. It is magic 💫
|
||||||
|
|
||||||
Магии в программировании, как вы понимаете, нет. Они создаются при использовании `FetchType.EAGER` у `@OneToMany` в совокупности с `@ElementCollection(fetch = FetchType.EAGER)`. Hibernate генерирует запрос с двумя-тремя полными соединениями, отсюда и берутся дубли. При этом в пагинации Hibernate не генерирует джойны, а использует кучу селектов, отсюда и отсутствие дублей при пагинации.
|
Магии в программировании, как вы понимаете, нет. Они создаются при использовании `FetchType.EAGER` у `@OneToMany` в совокупности с `@ElementCollection(fetch = FetchType.EAGER)`. Hibernate генерирует запрос с двумя-тремя полными соединениями, отсюда и берутся дубли. При этом в пагинации Hibernate не генерирует джойны, а использует кучу селектов, отсюда и отсутствие дублей при пагинации.
|
||||||
|
|
||||||
Эта проблема решается несколькими способами:
|
Эта проблема решается несколькими способами:
|
||||||
|
|
||||||
- Переделайте `List` в `Set` у `@OneToMany`.
|
- Переделайте `List` в `Set` у `@OneToMany`.
|
||||||
- Уберите `FetchType.EAGER` у `@OneToMany`.
|
- Уберите `FetchType.EAGER` у `@OneToMany`.
|
||||||
- Добавьте `@Fetch(FetchMode.SUBSELECT)` у `@OneToMany`. это аннотация Hibernate, которая вместо JOIN использует подзапрос. О [подзапросах я писал в отдельной статье](https://struchkov.dev/blog/ru/select-subquery).
|
- Добавьте `@Fetch(FetchMode.SUBSELECT)` у `@OneToMany`. это аннотация Hibernate, которая вместо JOIN использует подзапрос. О [подзапросах я писал в отдельной статье](https://struchkov.dev/blog/ru/select-subquery).
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
**Область**:: [[../../../meta/zero/00 Hibernate|00 Hibernate]]
|
**Область**:: [[../../../meta/zero/00 Hibernate|00 Hibernate]]
|
||||||
|
@ -12,7 +12,7 @@ linked:
|
|||||||
---
|
---
|
||||||
Провозился два дня, но в итоге смог собрать один из микро-сервисов в нативном режиме. Ничего сложного, но было много нюансов в настройке CICD.
|
Провозился два дня, но в итоге смог собрать один из микро-сервисов в нативном режиме. Ничего сложного, но было много нюансов в настройке CICD.
|
||||||
|
|
||||||
Самое полезное, это вот [эта документация Quarkus](https://quarkus.io/guides/building-native-image). А конкретно флаги:
|
Самое полезное, это вот [эта документация Quarkus](https://quarkus.io/guides/building-native-image). А конкретно флаги:
|
||||||
- `-Dquarkus.native.container-build=true`
|
- `-Dquarkus.native.container-build=true`
|
||||||
- `-Dquarkus.native.remote-container-build=true`
|
- `-Dquarkus.native.remote-container-build=true`
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
|||||||
|
|
||||||
Сервис стал собираться в 2,5 раза больше, около 5 минут, вместо 2. Но теперь он стартует моментально, наверное за доли секунды. При этом на под выделяется всего 256 mb ОЗУ на старте и 512 mb в момент работы.
|
Сервис стал собираться в 2,5 раза больше, около 5 минут, вместо 2. Но теперь он стартует моментально, наверное за доли секунды. При этом на под выделяется всего 256 mb ОЗУ на старте и 512 mb в момент работы.
|
||||||
## Более сложный путь
|
## Более сложный путь
|
||||||
Также слепил образ для GitLab-раннера, который совмещает GraalVM и Docker, осталось добавить в него Gradle, но пока использую `./gradlew`. Оставлю это тут на всякий случай.
|
Также слепил образ для GitLab-раннера, который совмещает GraalVM и Docker, осталось добавить в него Gradle, но пока использую `./gradlew`. Оставлю это тут на всякий случай.
|
||||||
|
|
||||||
```Dockerfile
|
```Dockerfile
|
||||||
FROM ghcr.io/graalvm/graalvm-ce:ol9-java17-22.3.0
|
FROM ghcr.io/graalvm/graalvm-ce:ol9-java17-22.3.0
|
||||||
|
@ -72,16 +72,16 @@ public class Binary {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Если элемент не найден, то вернется `-1`.
|
Если элемент не найден, то вернется `-1`.
|
||||||
|
|
||||||
> [!WARNING] m = l + (r - l) / 2;
|
> [!WARNING] m = l + (r - l) / 2;
|
||||||
> Во многих примерах в интернете можно встретить запись `int m = (l + r) / 2;`, вместо `int mid = l + (r - l) / 2;`.
|
> Во многих примерах в интернете можно встретить запись `int m = (l + r) / 2;`, вместо `int mid = l + (r - l) / 2;`.
|
||||||
>
|
>
|
||||||
> Но использование второго варианта является лучшей практикой, так как это помогает избежать переполнения, когда размер массива велик.
|
> Но использование второго варианта является лучшей практикой, так как это помогает избежать переполнения, когда размер массива велик.
|
||||||
>
|
>
|
||||||
> Например, если `l = 2147483647` и `r = 2147483647`, сумма `l` и `r` будет равна 4294967294, что превышает максимальное значение, которое может хранить `int`, вызывая переполнение.
|
> Например, если `l = 2147483647` и `r = 2147483647`, сумма `l` и `r` будет равна 4294967294, что превышает максимальное значение, которое может хранить `int`, вызывая переполнение.
|
||||||
>
|
>
|
||||||
> С другой стороны, если вы используете `mid = l + (r - l) / 2;` это будет работать, как и ожидалось, потому что вычитание будет сделано первым, а результат будет равен нулю, поэтому деление будет равно нулю, а сложение вернет значение `l`.
|
> С другой стороны, если вы используете `mid = l + (r - l) / 2;` это будет работать, как и ожидалось, потому что вычитание будет сделано первым, а результат будет равен нулю, поэтому деление будет равно нулю, а сложение вернет значение `l`.
|
||||||
|
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
|
@ -9,9 +9,9 @@ zero-link:
|
|||||||
parents:
|
parents:
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Разработчики Java используют подстановочный знак (`*`) в операторах `import` для добавления всех классов из определенного пакета. Но в ходе ревью большинство из вас, возможно, просили убрать этот подстановочный знак импорта и добавить полное имя класса. Разберемся почему не стоит использовать знак подстановки?
|
Разработчики Java используют подстановочный знак (`*`) в операторах `import` для добавления всех классов из определенного пакета. Но в ходе ревью большинство из вас, возможно, просили убрать этот подстановочный знак импорта и добавить полное имя класса. Разберемся почему не стоит использовать знак подстановки?
|
||||||
|
|
||||||
Но прежде, давайте вспомним, что полное имя класса, помимо названия, содержит также пакет, например: `java.util.List`. ==Такая запись позволяет нам иметь классы с одинаковыми именами, которые находятся в разных пакетах.==
|
Но прежде, давайте вспомним, что полное имя класса, помимо названия, содержит также пакет, например: `java.util.List`. ==Такая запись позволяет нам иметь классы с одинаковыми именами, которые находятся в разных пакетах.==
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package com.example;
|
package com.example;
|
||||||
@ -26,7 +26,7 @@ public class WithoutImport {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Однако, полная запись весьма непрактична, поэтому в Java существует оператор импорта – `import`. Операторы импорта объявляют компилятору источник имен классов, статических переменных и статических имен методов, используемых в коде. Один раз написали полное имя класса, а дальше используем только название класса.
|
Однако, полная запись весьма непрактична, поэтому в Java существует оператор импорта – `import`. Операторы импорта объявляют компилятору источник имен классов, статических переменных и статических имен методов, используемых в коде. Один раз написали полное имя класса, а дальше используем только название класса.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package com.example;
|
package com.example;
|
||||||
@ -88,13 +88,13 @@ public class com.example.WithWildCard {
|
|||||||
|
|
||||||
Если сравнить его с байт-кодом прошлого примера, то они оба имеют одинаковый байт-код.
|
Если сравнить его с байт-кодом прошлого примера, то они оба имеют одинаковый байт-код.
|
||||||
|
|
||||||
Во время выполнения Java использует байт-код, а не исходный код. ==В байт-коде нет операторов импорта.== Из этого ясно следует, что использование импорта с подстановочными знаками не влияет на производительность Java-приложения во время выполнения.
|
Во время выполнения Java использует байт-код, а не исходный код. ==В байт-коде нет операторов импорта.== Из этого ясно следует, что использование импорта с подстановочными знаками не влияет на производительность Java-приложения во время выполнения.
|
||||||
|
|
||||||
## Недостатки
|
## Недостатки
|
||||||
Так если использование подстановочного знака не приводит к проблемам производительности, то почему бы его не использовать?
|
Так если использование подстановочного знака не приводит к проблемам производительности, то почему бы его не использовать?
|
||||||
|
|
||||||
### Конфликты имен
|
### Конфликты имен
|
||||||
Самая серьезная проблема это возможные конфликты именования. Представьте, что у нас есть два класса из разных библиотек `org.test.Parser` и `dev.lib.Parser`. В нашем коде мы используем импорт с wildcard:
|
Самая серьезная проблема это возможные конфликты именования. Представьте, что у нас есть два класса из разных библиотек `org.test.Parser` и `dev.lib.Parser`. В нашем коде мы используем импорт с wildcard:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import org.test.*
|
import org.test.*
|
||||||
@ -103,7 +103,7 @@ import dev.lib.*
|
|||||||
|
|
||||||
Компилятор никак не отреагирует на наличие классов с одинаковыми именами в двух разных пакетах, импортируемых таким образом, если только не будет предпринята попытка воспользоваться одним из этих классов.
|
Компилятор никак не отреагирует на наличие классов с одинаковыми именами в двух разных пакетах, импортируемых таким образом, если только не будет предпринята попытка воспользоваться одним из этих классов.
|
||||||
|
|
||||||
Также проблема может возникнуть в будущем, когда вы обновите версию какую-то из библиотек. Допустим у нас была библиотека с классом `org.test.Parser`, а потом разработчик второй библиотеки тоже добавил класс `dev.lib.Parser`, таким образом мы получили конфлик именования в будущем, хотя раньше все было нормально.
|
Также проблема может возникнуть в будущем, когда вы обновите версию какую-то из библиотек. Допустим у нас была библиотека с классом `org.test.Parser`, а потом разработчик второй библиотеки тоже добавил класс `dev.lib.Parser`, таким образом мы получили конфлик именования в будущем, хотя раньше все было нормально.
|
||||||
### Чистый код
|
### Чистый код
|
||||||
Импорты с подстановочными знаками помогают нам избежать длинного списка импортов. Следовательно, это влияет на читабельность кода, так как читателю может потребоваться прокрутить много страниц в каждом файле исходного кода, прежде чем он доберется до кода, который показывает логику. Несомненно, более читабельный код - это также чистый код.
|
Импорты с подстановочными знаками помогают нам избежать длинного списка импортов. Следовательно, это влияет на читабельность кода, так как читателю может потребоваться прокрутить много страниц в каждом файле исходного кода, прежде чем он доберется до кода, который показывает логику. Несомненно, более читабельный код - это также чистый код.
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ SonarLint работает так же, как статический анали
|
|||||||
|
|
||||||
Если ваш проект анализируется в SonarQube или SonarCloud, SonarLint может подключиться к серверу, чтобы получить соответствующие профили качества и настройки для этого проекта.
|
Если ваш проект анализируется в SonarQube или SonarCloud, SonarLint может подключиться к серверу, чтобы получить соответствующие профили качества и настройки для этого проекта.
|
||||||
|
|
||||||
**Кому рекомендую:** Если вы Junior, то для вас это незаменимый инструмент, который позволит улучшить ваш код.
|
**Кому рекомендую:** Если вы Junior, то для вас это незаменимый инструмент, который позволит улучшить ваш код.
|
||||||
|
|
||||||
**Ссылка для установки:** [SonarLint - IntelliJ IDEs Plugin | Marketplace](https://plugins.jetbrains.com/plugin/7973-sonarlint)
|
**Ссылка для установки:** [SonarLint - IntelliJ IDEs Plugin | Marketplace](https://plugins.jetbrains.com/plugin/7973-sonarlint)
|
||||||
## Translation
|
## Translation
|
||||||
@ -37,11 +37,11 @@ SonarLint работает так же, как статический анали
|
|||||||
- Перевод JavaDoc
|
- Перевод JavaDoc
|
||||||
- Озвучивание текста
|
- Озвучивание текста
|
||||||
|
|
||||||
**Кому подойдет:** Этот плагин для тех, кто плохо знает английский язык.
|
**Кому подойдет:** Этот плагин для тех, кто плохо знает английский язык.
|
||||||
|
|
||||||
**Ссылка на установку:** [Translation - IntelliJ IDEs Plugin | Marketplace](https://plugins.jetbrains.com/plugin/8579-translation)
|
**Ссылка на установку:** [Translation - IntelliJ IDEs Plugin | Marketplace](https://plugins.jetbrains.com/plugin/8579-translation)
|
||||||
## .ignore
|
## .ignore
|
||||||
Простой плагин, который помогает генерировать файлы исключений, такие как `.gitignore` и `.dockerignore`.
|
Простой плагин, который помогает генерировать файлы исключений, такие как `.gitignore` и `.dockerignore`.
|
||||||
|
|
||||||
![](../../meta/files/images/plugin-ignore.gif)
|
![](../../meta/files/images/plugin-ignore.gif)
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ SonarLint работает так же, как статический анали
|
|||||||
## Presentation Assistant
|
## Presentation Assistant
|
||||||
Этот плагин отлично дополнит ваш live coding, потому что его задача ненавязчиво выводить комбинации клавиш, которые вы нажимаете. Даже если вы не будете нажимать сочетание клавиш, а просто кликаете мышкой, но для этого есть хоткей, то он также будет выведен.
|
Этот плагин отлично дополнит ваш live coding, потому что его задача ненавязчиво выводить комбинации клавиш, которые вы нажимаете. Даже если вы не будете нажимать сочетание клавиш, а просто кликаете мышкой, но для этого есть хоткей, то он также будет выведен.
|
||||||
|
|
||||||
**Кому подойдет:** Тем кто проводит вебинары. Также он мне больше нравится, чем Key Promoter X для изучения хоткеев.
|
**Кому подойдет:** Тем кто проводит вебинары. Также он мне больше нравится, чем Key Promoter X для изучения хоткеев.
|
||||||
|
|
||||||
![](../../meta/files/images/Pasted%20image%2020240908110354.png)
|
![](../../meta/files/images/Pasted%20image%2020240908110354.png)
|
||||||
|
|
||||||
|
@ -11,16 +11,16 @@ linked:
|
|||||||
---
|
---
|
||||||
Многие разработчики в принципе против использования Lombok. В общем, это холиварная тема. Но вы используете Lombok в проекте, то не используйте хотя бы спорные и откровенно вредные аннотации.
|
Многие разработчики в принципе против использования Lombok. В общем, это холиварная тема. Но вы используете Lombok в проекте, то не используйте хотя бы спорные и откровенно вредные аннотации.
|
||||||
|
|
||||||
Одна из таких – это `@Data`. Во-первых, [мало кто помнит, что она под собой скрывает](https://projectlombok.org/features/Data).
|
Одна из таких – это `@Data`. Во-первых, [мало кто помнит, что она под собой скрывает](https://projectlombok.org/features/Data).
|
||||||
|
|
||||||
- `@ToString`. Не помню, когда последний раз переопределял `toString()`. А если объект содержит чувствительную информацию?
|
- `@ToString`. Не помню, когда последний раз переопределял `toString()`. А если объект содержит чувствительную информацию?
|
||||||
- `@EqualsAndHashCode`. Это самая вредная аннотация в @Data. ==Потому что она генерирует `equals()` и `hashCode()` по всем полям.== Обычно вы не хотите, чтобы генерация осуществлялась по всем полям. Например, для сущности достаточно идентификатора.
|
- `@EqualsAndHashCode`. Это самая вредная аннотация в @Data. ==Потому что она генерирует `equals()` и `hashCode()` по всем полям.== Обычно вы не хотите, чтобы генерация осуществлялась по всем полям. Например, для сущности достаточно идентификатора.
|
||||||
- `@Getter` / `@Setter`. Здесь ничего плохого.
|
- `@Getter` / `@Setter`. Здесь ничего плохого.
|
||||||
- `@RequiredArgsConstructor`. Тоже окей.
|
- `@RequiredArgsConstructor`. Тоже окей.
|
||||||
|
|
||||||
Основная проблема в `@EqualsAndHashCode`. Можно, конечно, использовать `@EqualsAndHashCode.Exclude`. Эта аннотация запрещает использовать поле при генерации, но вы хотите расставлять это над почти всеми полями в сущности? Потому что `@EqualsAndHashCode.Include` просто не сработает, нельзя объявить только нужные поля, нужно будет именно исключать все ненужные.
|
Основная проблема в `@EqualsAndHashCode`. Можно, конечно, использовать `@EqualsAndHashCode.Exclude`. Эта аннотация запрещает использовать поле при генерации, но вы хотите расставлять это над почти всеми полями в сущности? Потому что `@EqualsAndHashCode.Include` просто не сработает, нельзя объявить только нужные поля, нужно будет именно исключать все ненужные.
|
||||||
|
|
||||||
Также избегайте всех аннотаций из пакета `experemental`. Все аннотации из этого пакета могут работать не стабильно, и при этом могут быть удалены из следующих версий. Исключением из этого пакета является [@FieldNameConstants](https://projectlombok.org/features/experimental/FieldNameConstants), за пару лет с ней не было никаких проблем, а все имеющиеся альтернативы не очень.
|
Также избегайте всех аннотаций из пакета `experemental`. Все аннотации из этого пакета могут работать не стабильно, и при этом могут быть удалены из следующих версий. Исключением из этого пакета является [@FieldNameConstants](https://projectlombok.org/features/experimental/FieldNameConstants), за пару лет с ней не было никаких проблем, а все имеющиеся альтернативы не очень.
|
||||||
|
|
||||||
С Lombok код выглядит чище, но, как и в случае с любым другим магическим инструментом, важно понимать, как именно он работает и когда его использовать. В противном случае производительность приложения может снизиться, либо оно вовсе может перестать работать корректно.
|
С Lombok код выглядит чище, но, как и в случае с любым другим магическим инструментом, важно понимать, как именно он работает и когда его использовать. В противном случае производительность приложения может снизиться, либо оно вовсе может перестать работать корректно.
|
||||||
***
|
***
|
||||||
|
@ -22,7 +22,7 @@ mvn -T 1C clean install
|
|||||||
|
|
||||||
![400](../../meta/files/images/Pasted%20image%2020231120092703.png)
|
![400](../../meta/files/images/Pasted%20image%2020231120092703.png)
|
||||||
|
|
||||||
По факту эти группы модулей зависят только друг от друга. Сначала собирается группа `domain`, от нее зависит группа `context`, потом core и так далее. Без `context` не собрать `core`, думаю суть понятна. Но вот модули core не зависят друг от друга, и могут собираться параллельно.
|
По факту эти группы модулей зависят только друг от друга. Сначала собирается группа `domain`, от нее зависит группа `context`, потом core и так далее. Без `context` не собрать `core`, думаю суть понятна. Но вот модули core не зависят друг от друга, и могут собираться параллельно.
|
||||||
|
|
||||||
Для примера вот время сборки в последовательном режиме:
|
Для примера вот время сборки в последовательном режиме:
|
||||||
|
|
||||||
|
@ -15,19 +15,19 @@ Enum это объект, как и все в Java. Однако это особ
|
|||||||
enum TestEnum {ONE, TWO, THREE}
|
enum TestEnum {ONE, TWO, THREE}
|
||||||
```
|
```
|
||||||
|
|
||||||
Если мы создадим 10 переменных `TestEnum.ONE`, то все они будут ссылаться на один и тот же объект. И поэтому enum можно сравнивать с помощью `==` и это корректно и будет работать.
|
Если мы создадим 10 переменных `TestEnum.ONE`, то все они будут ссылаться на один и тот же объект. И поэтому enum можно сравнивать с помощью `==` и это корректно и будет работать.
|
||||||
|
|
||||||
Сторонники такого подхода называют следующие преимущества. Давайте их разберем.
|
Сторонники такого подхода называют следующие преимущества. Давайте их разберем.
|
||||||
|
|
||||||
**Вы никогда не получите `NullPointerException`.** И это правда, но если вы будете придерживаться правила ["сравнение константы слева"](Сравнение%20константы%20слева%20в%20Java.md), то и при использовании `.equals()` `NullPointerException` вам не страшен.
|
**Вы никогда не получите `NullPointerException`.** И это правда, но если вы будете придерживаться правила ["сравнение константы слева"](Сравнение%20константы%20слева%20в%20Java.md), то и при использовании `.equals()` `NullPointerException` вам не страшен.
|
||||||
|
|
||||||
**Оператор == работает быстрее.** Быстрее чего? Видимо метода `.equals()`. Давайте посмотрим реализацию метода `.equals()` у enum.
|
**Оператор == работает быстрее.** Быстрее чего? Видимо метода `.equals()`. Давайте посмотрим реализацию метода `.equals()` у enum.
|
||||||
|
|
||||||
![](../../meta/files/images/Pasted%20image%2020231120093026.png)
|
![](../../meta/files/images/Pasted%20image%2020231120093026.png)
|
||||||
|
|
||||||
**Оператор == более понятный синтаксически.** Это еще почему? Для сравнения объектов в Java используется `.equals()`. Enum это объект. Логичнее и очевиднее использовать `.equals()` для сравнения, чтобы не нарушать единообразие сравнения объектов.
|
**Оператор == более понятный синтаксически.** Это еще почему? Для сравнения объектов в Java используется `.equals()`. Enum это объект. Логичнее и очевиднее использовать `.equals()` для сравнения, чтобы не нарушать единообразие сравнения объектов.
|
||||||
|
|
||||||
На мой взгляд, правильнее использовать `.equals()`, главное не забывать о правиле "[Сравнение константы слева](Сравнение%20константы%20слева%20в%20Java.md)".
|
На мой взгляд, правильнее использовать `.equals()`, главное не забывать о правиле "[Сравнение константы слева](Сравнение%20константы%20слева%20в%20Java.md)".
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
**Область**:: [[../../meta/zero/00 Java разработка|00 Java разработка]]
|
**Область**:: [[../../meta/zero/00 Java разработка|00 Java разработка]]
|
||||||
|
@ -41,9 +41,9 @@ if (user.getStatus().equals(UserStatus.ONLINE)) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Вроде бы все отлично, миссия выполнена. Но есть одно НО. Что если `getStatus()` вернет вам `null`? Правильно, вы получите `NullPointerException`.
|
Вроде бы все отлично, миссия выполнена. Но есть одно НО. Что если `getStatus()` вернет вам `null`? Правильно, вы получите `NullPointerException`.
|
||||||
|
|
||||||
Чтобы этого избежать следует придерживаться правила "Сравнения константы слева". Оно очень простое. В нашем примере, мы точно уверены, что `UserStatus.ONLINE` существует, поэтому `.equals()` стоит вызывать от него.
|
Чтобы этого избежать следует придерживаться правила "Сравнения константы слева". Оно очень простое. В нашем примере, мы точно уверены, что `UserStatus.ONLINE` существует, поэтому `.equals()` стоит вызывать от него.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
if (UserStatus.ONLINE.equals(user.getStatus())) {
|
if (UserStatus.ONLINE.equals(user.getStatus())) {
|
||||||
@ -59,7 +59,7 @@ if ("Иванов".equals(user.getLastName())) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Это простое правило защитит вас от `NullPointerException`.
|
Это простое правило защитит вас от `NullPointerException`.
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
**Область**:: [[../../meta/zero/00 Java разработка|00 Java разработка]]
|
**Область**:: [[../../meta/zero/00 Java разработка|00 Java разработка]]
|
||||||
|
@ -8,13 +8,13 @@ zero-link:
|
|||||||
parents:
|
parents:
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Ремарка, которую можно пропустить: Помню свой первый день на работе, тогда мне поручили настраивать сервер на CentOS 7. Установить необходимые пакеты, уже не помню точно что, но не суть. Я тогда еще обладатель ПК на windows погуглил и нашел команду `yum install pack_name`.
|
Ремарка, которую можно пропустить: Помню свой первый день на работе, тогда мне поручили настраивать сервер на CentOS 7. Установить необходимые пакеты, уже не помню точно что, но не суть. Я тогда еще обладатель ПК на windows погуглил и нашел команду `yum install pack_name`.
|
||||||
|
|
||||||
И как же я был удивлен, когда это не сработало. Корпоративные сервера чаще всего находятся в изоляции от интернета, и для доступа необходимо настраивать прокси. Но я тогда не знал об этом, и устанавливал пакеты вручную, скачивая их сначала к себе и перенося на сервер, то еще занятие, на это ушел целый день 😄
|
И как же я был удивлен, когда это не сработало. Корпоративные сервера чаще всего находятся в изоляции от интернета, и для доступа необходимо настраивать прокси. Но я тогда не знал об этом, и устанавливал пакеты вручную, скачивая их сначала к себе и перенося на сервер, то еще занятие, на это ушел целый день 😄
|
||||||
|
|
||||||
Потом я узнал о существовании прокси, которое открывало доступ в интернет. Сейчас расскажу, как его настроить.
|
Потом я узнал о существовании прокси, которое открывало доступ в интернет. Сейчас расскажу, как его настроить.
|
||||||
|
|
||||||
Особенность использования прокси в том, что его надо настраивать везде. Недостаточно настроить только на уровне ОС, надо также настроить на уровне каждого приложения, даже у пакетного менеджера типа `yum` и `dnf`, нужно указать прокси.
|
Особенность использования прокси в том, что его надо настраивать везде. Недостаточно настроить только на уровне ОС, надо также настроить на уровне каждого приложения, даже у пакетного менеджера типа `yum` и `dnf`, нужно указать прокси.
|
||||||
## Настройка для ОС
|
## Настройка для ОС
|
||||||
Первым делом настраиваем прокси на linux машине. Для этого нужно установить значения для некоторых переменных среды.
|
Первым делом настраиваем прокси на linux машине. Для этого нужно установить значения для некоторых переменных среды.
|
||||||
|
|
||||||
@ -41,10 +41,10 @@ export NO_PROXY="127.0.0.1,localhost"
|
|||||||
```
|
```
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Если в имени пользователя или пароле используется символ `@`, добавьте обратную косую черту (`\`) перед `@`.
|
> Если в имени пользователя или пароле используется символ `@`, добавьте обратную косую черту (`\`) перед `@`.
|
||||||
|
|
||||||
|
|
||||||
Данным способом мы установили временное прокси, ==после перезагрузки подключение пропадет.== Чтобы добавить постоянное прокси, нужно изменить файл `/etc/environment`.
|
Данным способом мы установили временное прокси, ==после перезагрузки подключение пропадет.== Чтобы добавить постоянное прокси, нужно изменить файл `/etc/environment`.
|
||||||
|
|
||||||
Если вам повезло и редактор nano был предустановлен, то воспользуйтесь им, добавив следующие строчки:
|
Если вам повезло и редактор nano был предустановлен, то воспользуйтесь им, добавив следующие строчки:
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ export HTTPS_PROXY="http://USERNAME:PASSWORD@SERVER:PORT/"
|
|||||||
export NO_PROXY="127.0.0.1,localhost"
|
export NO_PROXY="127.0.0.1,localhost"
|
||||||
```
|
```
|
||||||
|
|
||||||
Чтобы сохранинть изменения санчала нажмите `ESC`, а далее наберите `:wq`, чтобы выйти без сохранения нажмите `ESC` и наберите просто `:q`
|
Чтобы сохранинть изменения санчала нажмите `ESC`, а далее наберите `:wq`, чтобы выйти без сохранения нажмите `ESC` и наберите просто `:q`
|
||||||
|
|
||||||
Если вам совсем не повезло, и по какой-то причине редакторов совсем не предустановлено, то воспользуйтесь следующей командой:
|
Если вам совсем не повезло, и по какой-то причине редакторов совсем не предустановлено, то воспользуйтесь следующей командой:
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ export NO_PROXY="127.0.0.1,localhost"
|
|||||||
EOFXX
|
EOFXX
|
||||||
```
|
```
|
||||||
## Настройка для пакетных менеджеров
|
## Настройка для пакетных менеджеров
|
||||||
Теперь настроим прокси для пакетных менеджеров `yum` и `dnf`. Для этого отредактируем файл `/etc/yum.conf`, добавив в конец следующие строки:
|
Теперь настроим прокси для пакетных менеджеров `yum` и `dnf`. Для этого отредактируем файл `/etc/yum.conf`, добавив в конец следующие строки:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
proxy=http://SERVER:PORT
|
proxy=http://SERVER:PORT
|
||||||
|
@ -31,7 +31,7 @@ ssh username@192.168.0.1
|
|||||||
|
|
||||||
Первым делом нам надо узнать, какой интерфейс был присвоен нашему соединению на роутере. Если это ваше первое соединение с Wireguard, то скорее всего это Wireguard0. Но давайте убедимся в этом.
|
Первым делом нам надо узнать, какой интерфейс был присвоен нашему соединению на роутере. Если это ваше первое соединение с Wireguard, то скорее всего это Wireguard0. Но давайте убедимся в этом.
|
||||||
|
|
||||||
Для этого необходимо ввести `interface Wire` и нажать `Tab`:
|
Для этого необходимо ввести `interface Wire` и нажать `Tab`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
(config)> interface Wire
|
(config)> interface Wire
|
||||||
@ -87,7 +87,7 @@ ssh username@192.168.0.1
|
|||||||
|
|
||||||
![](../../meta/files/images/Pasted%20image%2020240908112035.png)
|
![](../../meta/files/images/Pasted%20image%2020240908112035.png)
|
||||||
|
|
||||||
Нужно добавить правило на IN, иначе запросы в локальную сеть будут дропаться. Не забудьте заменить `Wireguard0` на другое значение, если у вас задействован другой интерфейс.
|
Нужно добавить правило на IN, иначе запросы в локальную сеть будут дропаться. Не забудьте заменить `Wireguard0` на другое значение, если у вас задействован другой интерфейс.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
(config)> interface Wireguard0
|
(config)> interface Wireguard0
|
||||||
@ -106,9 +106,9 @@ Network::RoutingTable: Added static route: 10.66.67.0/24 via Wireguard0.
|
|||||||
```
|
```
|
||||||
|
|
||||||
> [!DANGER]
|
> [!DANGER]
|
||||||
> Не забудьте заменить значения на свои. `10.66.67.0` на свою подсеть Wireguard, а `Wireguard0` на свой интерфейс.
|
> Не забудьте заменить значения на свои. `10.66.67.0` на свою подсеть Wireguard, а `Wireguard0` на свой интерфейс.
|
||||||
## Настройка сервера WG
|
## Настройка сервера WG
|
||||||
Теперь нужно настроить сервер Wireguard. Для этого нужно отредактировать файл конфигурации, обычно он лежит в папке `/etc/wireguard/wg0.conf`. Зайдите под root.
|
Теперь нужно настроить сервер Wireguard. Для этого нужно отредактировать файл конфигурации, обычно он лежит в папке `/etc/wireguard/wg0.conf`. Зайдите под root.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
su
|
su
|
||||||
@ -136,7 +136,7 @@ PresharedKey = PRESHARED_KEY
|
|||||||
AllowedIPs = 10.66.67.3/32,fd42:42:43::3/128
|
AllowedIPs = 10.66.67.3/32,fd42:42:43::3/128
|
||||||
```
|
```
|
||||||
|
|
||||||
У нас тут все стандартно. Два пира, один из них роутер, второй телефон. Для роутера необходимо указать в `AllowedIPs` вашу локальную сеть, в данном случае `192.168.1.0/24`.
|
У нас тут все стандартно. Два пира, один из них роутер, второй телефон. Для роутера необходимо указать в `AllowedIPs` вашу локальную сеть, в данном случае `192.168.1.0/24`.
|
||||||
|
|
||||||
После этого отключим и включим WG соединение.
|
После этого отключим и включим WG соединение.
|
||||||
|
|
||||||
|
@ -19,13 +19,13 @@ linked:
|
|||||||
![](../../meta/files/images/Pasted%20image%2020240407184611.png)
|
![](../../meta/files/images/Pasted%20image%2020240407184611.png)
|
||||||
|
|
||||||
## 2. Убедитесь, что процесс сборки использует ваш порт
|
## 2. Убедитесь, что процесс сборки использует ваш порт
|
||||||
Нажмите `Ctrl+Shift+A` и найдите пункт “Edit Custom VM Options…”
|
Нажмите `Ctrl+Shift+A` и найдите пункт “Edit Custom VM Options…”
|
||||||
|
|
||||||
Добавьте новую строку `-Dcompiler.process.debug.port=8000` и ==перезапустите IDEA.==
|
Добавьте новую строку `-Dcompiler.process.debug.port=8000` и ==перезапустите IDEA.==
|
||||||
|
|
||||||
![](../../meta/files/images/Pasted%20image%2020240407184626.png)
|
![](../../meta/files/images/Pasted%20image%2020240407184626.png)
|
||||||
## 3. Включите “Debug build process”
|
## 3. Включите “Debug build process”
|
||||||
Нажмите `Ctrl+Shift+A` и пункт “Debug build process”.
|
Нажмите `Ctrl+Shift+A` и пункт “Debug build process”.
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Вам нужно будет повторять этот шаг каждый раз при перезапуске IDEA.
|
> Вам нужно будет повторять этот шаг каждый раз при перезапуске IDEA.
|
||||||
@ -34,7 +34,7 @@ linked:
|
|||||||
|
|
||||||
![](Pasted%20image%2020240407184705.png)
|
![](Pasted%20image%2020240407184705.png)
|
||||||
|
|
||||||
Для запуска вашего обработчика аннотаций пересоберите проект: `Build -> Rebuild Project`. ==При выборе пункта Build Project обработчик аннотации может не запуститься.==
|
Для запуска вашего обработчика аннотаций пересоберите проект: `Build -> Rebuild Project`. ==При выборе пункта Build Project обработчик аннотации может не запуститься.==
|
||||||
|
|
||||||
Процесс сборки приостановится, и вы сможете подключить отладчик:
|
Процесс сборки приостановится, и вы сможете подключить отладчик:
|
||||||
|
|
||||||
|
@ -81,13 +81,13 @@ public class OkHttpUtil {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
## Как это использовать?
|
## Как это использовать?
|
||||||
Перед получением `OkHttpClient` необходимо инициализировать настройки игнорирования сертификатов. Для этого вызываем метод:
|
Перед получением `OkHttpClient` необходимо инициализировать настройки игнорирования сертификатов. Для этого вызываем метод:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
OkHttpUtil.init(true);
|
OkHttpUtil.init(true);
|
||||||
```
|
```
|
||||||
|
|
||||||
После этого можете получить `OkHttpClient`:
|
После этого можете получить `OkHttpClient`:
|
||||||
```java
|
```java
|
||||||
OkHttpUtil.getClient();
|
OkHttpUtil.getClient();
|
||||||
```
|
```
|
||||||
|
@ -8,7 +8,7 @@ zero-link:
|
|||||||
parents:
|
parents:
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Когда я создаю [обучающие репозитории к своим статьям](https://github.com/Example-uPagge), то использую H2 в качестве базы данных. Проблема с H2 в том, что когда запущено приложение, нельзя просто подключиться и посмотреть что происходит в БД. Эта заметка показывает, как провернуть этот финт.
|
Когда я создаю [обучающие репозитории к своим статьям](https://github.com/Example-uPagge), то использую H2 в качестве базы данных. Проблема с H2 в том, что когда запущено приложение, нельзя просто подключиться и посмотреть что происходит в БД. Эта заметка показывает, как провернуть этот финт.
|
||||||
|
|
||||||
Имеем следующее подключение к базе данных:
|
Имеем следующее подключение к базе данных:
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ spring:
|
|||||||
database-platform: org.hibernate.dialect.H2Dialect
|
database-platform: org.hibernate.dialect.H2Dialect
|
||||||
```
|
```
|
||||||
|
|
||||||
В вашем Spring приложении необходимо создать следующий `@Bean`:
|
В вашем Spring приложении необходимо создать следующий `@Bean`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import org.h2.tools.Server;
|
import org.h2.tools.Server;
|
||||||
@ -44,7 +44,7 @@ public class BeanConfig {
|
|||||||
Это фактически создает сервер для остальных подключений к H2.
|
Это фактически создает сервер для остальных подключений к H2.
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Если класс `org.h2.tools.Server` не находится, то скорее всего у зависимости для H2 установлен scope `runtime`. Удалите значение `scope` и класс появится.
|
> Если класс `org.h2.tools.Server` не находится, то скорее всего у зависимости для H2 установлен scope `runtime`. Удалите значение `scope` и класс появится.
|
||||||
|
|
||||||
Теперь можно подсоединиться к H2 используя следующий url:
|
Теперь можно подсоединиться к H2 используя следующий url:
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ jdbc:h2:tcp://localhost:9090/mem:blog
|
|||||||
|
|
||||||
![Так выглядит окно соединения в IntelliJ Idea](../../meta/files/images/data-sources-in-idea.png)
|
![Так выглядит окно соединения в IntelliJ Idea](../../meta/files/images/data-sources-in-idea.png)
|
||||||
|
|
||||||
Ограничение этого способа в том, что ==нельзя подключиться к базе, если приложение не работает.==
|
Ограничение этого способа в том, что ==нельзя подключиться к базе, если приложение не работает.==
|
||||||
|
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
|
@ -10,7 +10,7 @@ linked:
|
|||||||
---
|
---
|
||||||
PNG и JPG являются хорошими форматами изображений, которые можно [сжать без потери качества](Сжатие%20изображений%20без%20потери%20качества.md). Однако, на сегодняшний день существует более современный формат WebP, который может показать еще более эффективные результаты при сжатии изображений, но с едва заметным ухудшением качества.
|
PNG и JPG являются хорошими форматами изображений, которые можно [сжать без потери качества](Сжатие%20изображений%20без%20потери%20качества.md). Однако, на сегодняшний день существует более современный формат WebP, который может показать еще более эффективные результаты при сжатии изображений, но с едва заметным ухудшением качества.
|
||||||
|
|
||||||
В [документации WebP](https://developers.google.com/speed/webp/docs/cwebp?hl=ru) перечислено множество параметров, которые повлияют на качество получаемого изображения. Вы можете провести экспериментальный подбор параметров онлайн на сайте [https://squoosh.app](https://squoosh.app/).
|
В [документации WebP](https://developers.google.com/speed/webp/docs/cwebp?hl=ru) перечислено множество параметров, которые повлияют на качество получаемого изображения. Вы можете провести экспериментальный подбор параметров онлайн на сайте [https://squoosh.app](https://squoosh.app/).
|
||||||
|
|
||||||
Я вы выбрал для себя следующий набор параметров:
|
Я вы выбрал для себя следующий набор параметров:
|
||||||
|
|
||||||
@ -18,17 +18,17 @@ PNG и JPG являются хорошими форматами изображе
|
|||||||
cwebp -mt -af -progress -m 6 -q 80 -pass 10 input.jpg -o output.webp
|
cwebp -mt -af -progress -m 6 -q 80 -pass 10 input.jpg -o output.webp
|
||||||
```
|
```
|
||||||
|
|
||||||
Это команда преобразует JPG файл `input.jpg` в файл изображения WebP с именем `output.webp`. Команда включает несколько опций, которые управляют процессом кодирования:
|
Это команда преобразует JPG файл `input.jpg` в файл изображения WebP с именем `output.webp`. Команда включает несколько опций, которые управляют процессом кодирования:
|
||||||
- `-mt` включает многопоточность, что может улучшить производительность на многоядерных процессорах.
|
- `-mt` включает многопоточность, что может улучшить производительность на многоядерных процессорах.
|
||||||
- `-af` включает автоматическую фильтрацию, которая применяет алгоритм фильтрации для повышения эффективности сжатия.
|
- `-af` включает автоматическую фильтрацию, которая применяет алгоритм фильтрации для повышения эффективности сжатия.
|
||||||
- `-progress` выводит показывает процент обработки файла.
|
- `-progress` выводит показывает процент обработки файла.
|
||||||
- `-m 6` устанавливает максимальное количество сегментов, используемых в процессе кодирования, равным 6, что может повысить эффективность сжатия за счет увеличения времени кодирования.
|
- `-m 6` устанавливает максимальное количество сегментов, используемых в процессе кодирования, равным 6, что может повысить эффективность сжатия за счет увеличения времени кодирования.
|
||||||
- `-q 80` устанавливает коэффициент качества на `80`, который контролирует степень сжатия и влияет на визуальное качество выходного изображения.
|
- `-q 80` устанавливает коэффициент качества на `80`, который контролирует степень сжатия и влияет на визуальное качество выходного изображения.
|
||||||
- `-pass 10` устанавливает число проходов кодирования равным 10, что может повысить эффективность сжатия за счет увеличения времени кодирования.
|
- `-pass 10` устанавливает число проходов кодирования равным 10, что может повысить эффективность сжатия за счет увеличения времени кодирования.
|
||||||
|
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> `-lossless` позволяет использовать сжатие без потерь. Но тогда ваше новое изображение может оказаться существенно тяжелее исходного.
|
> `-lossless` позволяет использовать сжатие без потерь. Но тогда ваше новое изображение может оказаться существенно тяжелее исходного.
|
||||||
|
|
||||||
Улучшим [скрипт сжатия изображений](Сжатие%20изображений%20без%20потери%20качества.md) и добавим преобразование в webp:
|
Улучшим [скрипт сжатия изображений](Сжатие%20изображений%20без%20потери%20качества.md) и добавим преобразование в webp:
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ find ./images/comp -type f -iregex '.*\.\(jpg\|jpeg\|png\)' -not -iregex '.*no-c
|
|||||||
' _ {} \;
|
' _ {} \;
|
||||||
```
|
```
|
||||||
|
|
||||||
Мы берем сжатые изображения из папки `comp` и преобразуем их в WebP, складывая в отдельную папку `webp`. Если вы захотите использовать другие параметры сжатия, вы всегда сможете пересоздать изображения с новыми параметрами.
|
Мы берем сжатые изображения из папки `comp` и преобразуем их в WebP, складывая в отдельную папку `webp`. Если вы захотите использовать другие параметры сжатия, вы всегда сможете пересоздать изображения с новыми параметрами.
|
||||||
## Тесты преобразования
|
## Тесты преобразования
|
||||||
Продолжим наши эксперименты со сжатием. Теперь сожмем наши файл размером в 2,7 мб и 2.2 в формат WebP с разными параметрами качества:
|
Продолжим наши эксперименты со сжатием. Теперь сожмем наши файл размером в 2,7 мб и 2.2 в формат WebP с разными параметрами качества:
|
||||||
- -q 90: Размер 325 кб.
|
- -q 90: Размер 325 кб.
|
||||||
@ -59,7 +59,7 @@ find ./images/comp -type f -iregex '.*\.\(jpg\|jpeg\|png\)' -not -iregex '.*no-c
|
|||||||
## Nginx
|
## Nginx
|
||||||
Теперь мы научим nginx при запросе изображений сначала пытаться найти WebP файл, и только потом отдавать сжатый PNG/JPG, а если и сжатого нет, то отдавать обычный файл.
|
Теперь мы научим nginx при запросе изображений сначала пытаться найти WebP файл, и только потом отдавать сжатый PNG/JPG, а если и сжатого нет, то отдавать обычный файл.
|
||||||
|
|
||||||
Для этого напишем следующий `location`:
|
Для этого напишем следующий `location`:
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
location ~* ^(/blog/ru/content/images/)(.+)\.(png|jpe?g)$ {
|
location ~* ^(/blog/ru/content/images/)(.+)\.(png|jpe?g)$ {
|
||||||
@ -71,12 +71,12 @@ location ~* ^(/blog/ru/content/images/)(.+)\.(png|jpe?g)$ {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Данный `location` обрабатывает все запросы к адресам, которые начинаются с `/images/`, за которым следует любое количество символов, затем точка, а затем формат файла png/jpeg/jpg.
|
Данный `location` обрабатывает все запросы к адресам, которые начинаются с `/images/`, за которым следует любое количество символов, затем точка, а затем формат файла png/jpeg/jpg.
|
||||||
|
|
||||||
Для запросов, соответствующих этому шаблону, выполняются следующие действия:
|
Для запросов, соответствующих этому шаблону, выполняются следующие действия:
|
||||||
- Директива `alias` указывает путь к локальной директории, из которой будут отдаваться файлы. В данном случае путь к директории `/images`.
|
- Директива `alias` указывает путь к локальной директории, из которой будут отдаваться файлы. В данном случае путь к директории `/images`.
|
||||||
- Директивы `set` назначают переменные, которые будут использоваться в последующих директивах. Переменная `$webp_image_subdir` устанавливается в `/webp/`, а переменная `$basename` устанавливается в захваченную подстроку шаблона регулярного выражения (т.е. имя файла без расширения).
|
- Директивы `set` назначают переменные, которые будут использоваться в последующих директивах. Переменная `$webp_image_subdir` устанавливается в `/webp/`, а переменная `$basename` устанавливается в захваченную подстроку шаблона регулярного выражения (т.е. имя файла без расширения).
|
||||||
- Директива `try_files` пытается отдать Webp-версию запрошенного файла изображения, добавляя к переменным `$webp_image_subdir` и `$basename` суффикс `.webp`. Если NGINX сможет найти Webp-версию запрашиваемого файла изображения, он отдаст его. Если он не может найти WebP-версию, то отдаст сжатый JPG/PNG, если и сжатого файла не будет, то отдаст не сжатое.
|
- Директива `try_files` пытается отдать Webp-версию запрошенного файла изображения, добавляя к переменным `$webp_image_subdir` и `$basename` суффикс `.webp`. Если NGINX сможет найти Webp-версию запрашиваемого файла изображения, он отдаст его. Если он не может найти WebP-версию, то отдаст сжатый JPG/PNG, если и сжатого файла не будет, то отдаст не сжатое.
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
**Область**:: [[../../meta/zero/00 Снипеты на bash|00 Снипеты на bash]]
|
**Область**:: [[../../meta/zero/00 Снипеты на bash|00 Снипеты на bash]]
|
||||||
|
@ -9,11 +9,11 @@ parents:
|
|||||||
- "[[../../../../knowledge/dev/java/other/Jackson|Jackson]]"
|
- "[[../../../../knowledge/dev/java/other/Jackson|Jackson]]"
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Чаще всего по работе я сталкиваюсь с проблемой десериализации и сериализации даты. Многие разработчики отступают от стандартного формата времени `yyyy-MM-dd'T'HH:mm:ss*SSSZZZZ` и изобретают свои форматы.
|
Чаще всего по работе я сталкиваюсь с проблемой десериализации и сериализации даты. Многие разработчики отступают от стандартного формата времени `yyyy-MM-dd'T'HH:mm:ss*SSSZZZZ` и изобретают свои форматы.
|
||||||
|
|
||||||
К сожалению, в Jackson не заложены все возможные форматы даты, поэтому необходимо написать свой десериализатор.
|
К сожалению, в Jackson не заложены все возможные форматы даты, поэтому необходимо написать свой десериализатор.
|
||||||
## Десериализация
|
## Десериализация
|
||||||
В данном случае это преобразование json формата в Java объект. Необходимо расширить абстрактный класс `StdDeserializer`.
|
В данном случае это преобразование json формата в Java объект. Необходимо расширить абстрактный класс `StdDeserializer`.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
@ -47,7 +47,7 @@ public class CustomDeserializer extends StdDeserializer<LocalDateTime> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
После этого необходимо над полем поставить аннотацию `@JsonDeserialize` c указанием нашего кастомного десериализатора.
|
После этого необходимо над полем поставить аннотацию `@JsonDeserialize` c указанием нашего кастомного десериализатора.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Foo {
|
public class Foo {
|
||||||
@ -63,7 +63,7 @@ public class Foo {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Сериализация
|
## Сериализация
|
||||||
В данном случае это преобразование Java объекта в json формат. Для сериализации необходимо расширить класс `StdSerializer`.
|
В данном случае это преобразование Java объекта в json формат. Для сериализации необходимо расширить класс `StdSerializer`.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
@ -93,7 +93,7 @@ public class CustomSerializer extends StdSerializer<LocalDateTime> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Для работы над полем поставить аннотацию `@JsonSerialize`
|
Для работы над полем поставить аннотацию `@JsonSerialize`
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Foo {
|
public class Foo {
|
||||||
|
@ -40,24 +40,24 @@ touch $file
|
|||||||
echo "$(date)" > $file
|
echo "$(date)" > $file
|
||||||
```
|
```
|
||||||
|
|
||||||
Этот скрипт сжимает изображения без потери качества. Он размещается рядом с каталогом `images`, в котором находятся ваши изображения. Разберемся, как он работает.
|
Этот скрипт сжимает изображения без потери качества. Он размещается рядом с каталогом `images`, в котором находятся ваши изображения. Разберемся, как он работает.
|
||||||
|
|
||||||
Сначала скрипт проверяет, существует ли в текущем каталоге файл `comp.flag`. Если файл существует, он устанавливает значение `-newer $file` в переменную `option`, которая будет использоваться в качестве фильтра для поиска только тех файлов, которые были изменены после даты создания файла `optimg.flag`. Если файл не существует, переменная `option` будет пустой.
|
Сначала скрипт проверяет, существует ли в текущем каталоге файл `comp.flag`. Если файл существует, он устанавливает значение `-newer $file` в переменную `option`, которая будет использоваться в качестве фильтра для поиска только тех файлов, которые были изменены после даты создания файла `optimg.flag`. Если файл не существует, переменная `option` будет пустой.
|
||||||
|
|
||||||
Затем скрипт использует команду `find` для рекурсивного поиска файлов в каталоге `images` и его подкаталогах, которые:
|
Затем скрипт использует команду `find` для рекурсивного поиска файлов в каталоге `images` и его подкаталогах, которые:
|
||||||
- `-type f`. Являются обычными файлами.
|
- `-type f`. Являются обычными файлами.
|
||||||
- Имеют расширение имени файла `.png`, `.jpeg` или `.jpg`.
|
- Имеют расширение имени файла `.png`, `.jpeg` или `.jpg`.
|
||||||
- `-not -path`_._ Не находятся в указанных каталогах_._ В данном случае это каталоги `./images/comp`. Мы будем складывать туда сжатые изображения, и мы не хотим заново по ним проходить поиском и сжимать снова.
|
- `-not -path`_._ Не находятся в указанных каталогах_._ В данном случае это каталоги `./images/comp`. Мы будем складывать туда сжатые изображения, и мы не хотим заново по ним проходить поиском и сжимать снова.
|
||||||
- `! -name "-no-comp."`. Оставим возможность не сжимать изображение, если его имя заканчивается на `-no-comp`.
|
- `! -name "-no-comp."`. Оставим возможность не сжимать изображение, если его имя заканчивается на `-no-comp`.
|
||||||
- Для каждого из этих файлов сценарий использует свою команду оптимизации.
|
- Для каждого из этих файлов сценарий использует свою команду оптимизации.
|
||||||
|
|
||||||
Мы не будем затирать оригиналы изображений. Вместо этого мы создадим дополнительную папку `comp` в каталоге `images`, в которую и сложим преобразованные изображения. Создаваемая структура подкаталогов в `comp` будет повторять структуру подкатологов в `images`.
|
Мы не будем затирать оригиналы изображений. Вместо этого мы создадим дополнительную папку `comp` в каталоге `images`, в которую и сложим преобразованные изображения. Создаваемая структура подкаталогов в `comp` будет повторять структуру подкатологов в `images`.
|
||||||
|
|
||||||
Для файлов PNG сначала используется `optipng` для сжатия с самым высоким уровнем оптимизации (`-o7`). Далее используем `advpng` для дальнейшего сжатия с уровнем сжатия 4 (`-z4`). И наконец `pngcrush` для удаления из файла определенных фрагментов, которые можно безопасно удалить для уменьшения размера файла.
|
Для файлов PNG сначала используется `optipng` для сжатия с самым высоким уровнем оптимизации (`-o7`). Далее используем `advpng` для дальнейшего сжатия с уровнем сжатия 4 (`-z4`). И наконец `pngcrush` для удаления из файла определенных фрагментов, которые можно безопасно удалить для уменьшения размера файла.
|
||||||
|
|
||||||
Для файлов JPEG используется `jpegoptim` для их оптимизации со сжатием без потерь (`--all-progressive --strip-all`).
|
Для файлов JPEG используется `jpegoptim` для их оптимизации со сжатием без потерь (`--all-progressive --strip-all`).
|
||||||
|
|
||||||
После оптимизации всех подходящих изображений сценарий пересоздает файл `comp.flag`. Это гарантирует, что скрипт будет оптимизировать только те файлы, которые были изменены с момента последнего запуска.
|
После оптимизации всех подходящих изображений сценарий пересоздает файл `comp.flag`. Это гарантирует, что скрипт будет оптимизировать только те файлы, которые были изменены с момента последнего запуска.
|
||||||
## Тесты на сжатие
|
## Тесты на сжатие
|
||||||
Возьмем два одинаковых изображения (3456 x 2234): одно форматом jpg и размером 2.2 мб, второе форматом png и размером 2,7 мб.
|
Возьмем два одинаковых изображения (3456 x 2234): одно форматом jpg и размером 2.2 мб, второе форматом png и размером 2,7 мб.
|
||||||
|
|
||||||
|
@ -8,13 +8,13 @@ zero-link:
|
|||||||
parents:
|
parents:
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
Для запуска `jar` файла в linux в виде сервиса, необходимо создать файл конфигурации.
|
Для запуска `jar` файла в linux в виде сервиса, необходимо создать файл конфигурации.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
sudo nano /etc/systemd/system/app_name_service.service
|
sudo nano /etc/systemd/system/app_name_service.service
|
||||||
```
|
```
|
||||||
|
|
||||||
В этот файл вставляем примерно следующее. Не забудьте заменить в выделенных строках `app_path`, `app_name`.
|
В этот файл вставляем примерно следующее. Не забудьте заменить в выделенных строках `app_path`, `app_name`.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
[Unit]
|
[Unit]
|
||||||
|
@ -3,6 +3,6 @@ tags:
|
|||||||
- type/people
|
- type/people
|
||||||
link: https://mnogosdelal.ru/
|
link: https://mnogosdelal.ru/
|
||||||
---
|
---
|
||||||
Прокрастинатолог, специалист по продуктивности, тренер. Руководил проектами в компаниях DC BARS, Auriga, в Лаборатории Касперского, проработал в области разработки ПО почти 15 лет.
|
Прокрастинатолог, специалист по продуктивности, тренер. Руководил проектами в компаниях DC BARS, Auriga, в Лаборатории Касперского, проработал в области разработки ПО почти 15 лет.
|
||||||
|
|
||||||
С 2013 ведет тренинги по продуктивности. Окончил физический факультет МГУ.
|
С 2013 ведет тренинги по продуктивности. Окончил физический факультет МГУ.
|
@ -31,9 +31,9 @@ linked:
|
|||||||
- [Производительность SQL запросов](_inbox/Производительность%20SQL%20запросов.md)
|
- [Производительность SQL запросов](_inbox/Производительность%20SQL%20запросов.md)
|
||||||
|
|
||||||
## Заметки
|
## Заметки
|
||||||
- Классические СУБД хранят данные в двух местах: на диске и в памяти.
|
- Классические СУБД хранят данные в двух местах: на диске и в памяти.
|
||||||
- [[../../dev/fundamental/Страница|Страница]] модифицируется сначала в оперативной памяти, потом попадает на диск.
|
- [[../../dev/fundamental/Страница|Страница]] модифицируется сначала в оперативной памяти, потом попадает на диск.
|
||||||
- ![](Pasted%20image%2020240531082744.png)
|
- ![](Pasted%20image%2020240531082744.png)
|
||||||
- Часто думают, что реляционная таблица — это массив. Некоторые даже думают, что это двумерный массив. На самом деле, это гораздо более сложная штука. Это мультимножество – набор определенного сорта кортежей, над которым не задано порядка. В SQL-таблице нет порядка. Это важно. И, как результат, когда вы делаете SELECT* из БД (просканировать все записи), результат выполнения запроса может меняться – строчки могут быть в одном порядке, а могут и в другом. Про это нужно помнить.
|
- Часто думают, что реляционная таблица — это массив. Некоторые даже думают, что это двумерный массив. На самом деле, это гораздо более сложная штука. Это мультимножество – набор определенного сорта кортежей, над которым не задано порядка. В SQL-таблице нет порядка. Это важно. И, как результат, когда вы делаете SELECT* из БД (просканировать все записи), результат выполнения запроса может меняться – строчки могут быть в одном порядке, а могут и в другом. Про это нужно помнить.
|
||||||
- Профиль нагрузки на реляционную базу данных выглядит следующим образом: 80% запросов это чтение, 20% запросов это запись. Если запросов на запись больше, то возможно реляционная база данных вам не подходит.
|
- Профиль нагрузки на реляционную базу данных выглядит следующим образом: 80% запросов это чтение, 20% запросов это запись. Если запросов на запись больше, то возможно реляционная база данных вам не подходит.
|
||||||
|
|
||||||
|
@ -5,4 +5,4 @@ title: Образование
|
|||||||
---
|
---
|
||||||
- [[../../education/Метапознание|Метапознание]]
|
- [[../../education/Метапознание|Метапознание]]
|
||||||
## Свободные заметки
|
## Свободные заметки
|
||||||
- Согласно исследованиям, оптимальное время для начала обучения и работы [лежит в промежутке 11:00-12:00](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5395635/). Хотя исследователи и признают, что это довольно индивидуально, и важно слушать свои ощущения.
|
- Согласно исследованиям, оптимальное время для начала обучения и работы [лежит в промежутке 11:00-12:00](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5395635/). Хотя исследователи и признают, что это довольно индивидуально, и важно слушать свои ощущения.
|
@ -24,15 +24,15 @@ zero-link:
|
|||||||
- Нейромедиаторы и гормоны: [Кортизол](Кортизол.md), [Адреналин](Адреналин.md), [Норадреналин](Норадреналин.md), [Аденозин](Аденозин.md)
|
- Нейромедиаторы и гормоны: [Кортизол](Кортизол.md), [Адреналин](Адреналин.md), [Норадреналин](Норадреналин.md), [Аденозин](Аденозин.md)
|
||||||
- [Фазы сна](Фазы%20сна.md): [Поверхностный сон](_inbox/Поверхностный%20сон.md), [Глубокая фаза сна](Глубокая%20фаза%20сна.md), [REM](Фаза%20быстрого%20сна.md)
|
- [Фазы сна](Фазы%20сна.md): [Поверхностный сон](_inbox/Поверхностный%20сон.md), [Глубокая фаза сна](Глубокая%20фаза%20сна.md), [REM](Фаза%20быстрого%20сна.md)
|
||||||
## Зачем нужен сон?
|
## Зачем нужен сон?
|
||||||
**Сон играет роль уборщика**, [удаляя](https://www.sciencedirect.com/science/article/abs/pii/S2468867319301609#:~:text=The%20discovery%20that,dependence%20on%20glia.) из мозга продукты метаболизма — ненужные белки, которые накапливаются во время бодрствования и приводят к заболеваниям нервной системы. Среди таких белков — бета-амилоид, большая концентрация которого приводит к [гибели](https://med.stanford.edu/news/all-news/2013/09/scientists-reveal-how-beta-amyloid-may-cause-alzheimers.html#:~:text=Scientists%20at%20the%20Stanford%20University%20School%20of%20Medicine%20have%20shown%20how%20a%20protein%20fragment%20known%20as%20beta%2Damyloid%2C%20strongly%20implicated%20in%20Alzheimer%E2%80%99s%20disease%2C%20begins%20destroying%20synapses%20before%20it%20clumps%20into%20plaques%20that%20lead%20to%20nerve%20cell%20death.) нервных клеток и, [вероятно](https://www.medicalnewstoday.com/articles/325493#:~:text=If%20the%20cellular%20system%20became%20overloaded%20or%20slowed%20down%20as%20we%20aged%2C%20metabolic%20garbage%20would%20build%20up%20between%20the%20cells.%20This%20garbage%20includes%20products%20such%20as%20beta%2Damyloid%20%E2%80%94%20the%20protein%20associated%20with%20Alzheimer%E2%80%99s%20disease.), к [[../../../../knowledge/health/болезни/Болезнь Альцгеймера|болезни Альцгеймера]]. Всего одна бессонная ночь значительно [повышает](https://www.pnas.org/doi/10.1073/pnas.1721694115#:~:text=We%20show%20that%20one%20night%20of%20sleep%20deprivation%2C%20relative%20to%20baseline%2C%20resulted%20in%20a%20significant%20increase%20in%20A%CE%B2%20burden%20in%20the%20right%20hippocampus%20and%20thalamus.) объем этого белка в мозге человека.
|
**Сон играет роль уборщика**, [удаляя](https://www.sciencedirect.com/science/article/abs/pii/S2468867319301609#:~:text=The%20discovery%20that,dependence%20on%20glia.) из мозга продукты метаболизма — ненужные белки, которые накапливаются во время бодрствования и приводят к заболеваниям нервной системы. Среди таких белков — бета-амилоид, большая концентрация которого приводит к [гибели](https://med.stanford.edu/news/all-news/2013/09/scientists-reveal-how-beta-amyloid-may-cause-alzheimers.html#:~:text=Scientists%20at%20the%20Stanford%20University%20School%20of%20Medicine%20have%20shown%20how%20a%20protein%20fragment%20known%20as%20beta%2Damyloid%2C%20strongly%20implicated%20in%20Alzheimer%E2%80%99s%20disease%2C%20begins%20destroying%20synapses%20before%20it%20clumps%20into%20plaques%20that%20lead%20to%20nerve%20cell%20death.) нервных клеток и, [вероятно](https://www.medicalnewstoday.com/articles/325493#:~:text=If%20the%20cellular%20system%20became%20overloaded%20or%20slowed%20down%20as%20we%20aged%2C%20metabolic%20garbage%20would%20build%20up%20between%20the%20cells.%20This%20garbage%20includes%20products%20such%20as%20beta%2Damyloid%20%E2%80%94%20the%20protein%20associated%20with%20Alzheimer%E2%80%99s%20disease.), к [[../../../../knowledge/health/болезни/Болезнь Альцгеймера|болезни Альцгеймера]]. Всего одна бессонная ночь значительно [повышает](https://www.pnas.org/doi/10.1073/pnas.1721694115#:~:text=We%20show%20that%20one%20night%20of%20sleep%20deprivation%2C%20relative%20to%20baseline%2C%20resulted%20in%20a%20significant%20increase%20in%20A%CE%B2%20burden%20in%20the%20right%20hippocampus%20and%20thalamus.) объем этого белка в мозге человека.
|
||||||
|
|
||||||
**Сон важен для физического самочувствия.** Пока мы спим, [усиливается](https://erj.ersjournals.com/content/38/4/870#:~:text=The%20release%20of%20GH%20is%20greatly%20enhanced%20during%20sleep%2C%20especially%20early%20in%20the%20night) выработка [«гормона роста»](https://ru.wikipedia.org/wiki/%D0%93%D0%BE%D1%80%D0%BC%D0%BE%D0%BD_%D1%80%D0%BE%D1%81%D1%82%D0%B0), который [восстанавливает](https://www.healthline.com/health/hgh-side-effects#:~:text=HGH%20helps%20to%20maintain%2C%20build%2C%20and%20repair%20healthy%20tissue%20in%20the%20brain%20and%20other%20organs.%20This%20hormone%20can%20help%20to%20speed%20up%20healing%20after%20an%20injury%20and%20repair%20muscle%20tissue%20after%20exercise.%20This%20helps%20to%20build%20muscle%20mass%2C%20boost%20metabolism%2C%20and%20burn%20fat.) мышцы после нагрузок и травм. Нехватка этого гормона [приводит](https://academic.oup.com/jcem/article/83/2/382/2865179?login=false#:~:text=1.%20Lean%20Body%20Mass%20(LBM).%20Reduced%20LBM%20is%20an%20important%20feature%20of%20AO%20GH%20deficiency.%20Initial%20studies%20demonstrated%20a%20mean%20reduction%20in%20LBM%20of%207%E2%80%938%25%2C%20corresponding%20to%20approximately%204%20kg%20lean%20tissue%20(6).%20Subsequent%20studies%20have%20confirmed%20these%20results%20(12%2C%2014%E2%80%9316).) к тому, что мышцы атрофируются. Также сон помогает нормализовать артериальное давление.
|
**Сон важен для физического самочувствия.** Пока мы спим, [усиливается](https://erj.ersjournals.com/content/38/4/870#:~:text=The%20release%20of%20GH%20is%20greatly%20enhanced%20during%20sleep%2C%20especially%20early%20in%20the%20night) выработка [«гормона роста»](https://ru.wikipedia.org/wiki/%D0%93%D0%BE%D1%80%D0%BC%D0%BE%D0%BD_%D1%80%D0%BE%D1%81%D1%82%D0%B0), который [восстанавливает](https://www.healthline.com/health/hgh-side-effects#:~:text=HGH%20helps%20to%20maintain%2C%20build%2C%20and%20repair%20healthy%20tissue%20in%20the%20brain%20and%20other%20organs.%20This%20hormone%20can%20help%20to%20speed%20up%20healing%20after%20an%20injury%20and%20repair%20muscle%20tissue%20after%20exercise.%20This%20helps%20to%20build%20muscle%20mass%2C%20boost%20metabolism%2C%20and%20burn%20fat.) мышцы после нагрузок и травм. Нехватка этого гормона [приводит](https://academic.oup.com/jcem/article/83/2/382/2865179?login=false#:~:text=1.%20Lean%20Body%20Mass%20(LBM).%20Reduced%20LBM%20is%20an%20important%20feature%20of%20AO%20GH%20deficiency.%20Initial%20studies%20demonstrated%20a%20mean%20reduction%20in%20LBM%20of%207%E2%80%938%25%2C%20corresponding%20to%20approximately%204%20kg%20lean%20tissue%20(6).%20Subsequent%20studies%20have%20confirmed%20these%20results%20(12%2C%2014%E2%80%9316).) к тому, что мышцы атрофируются. Также сон помогает нормализовать артериальное давление.
|
||||||
|
|
||||||
**Сон нужен иммунной системе.** Во сне наше дыхание замедляется, а мышцы почти неподвижны, поэтому энергия в организме может [пойти](https://www.sleepfoundation.org/physical-health/how-sleep-affects-immunity#:~:text=During%20sleep%2C%20breathing%20and%20muscle%20activity%20slows%20down%2C%20freeing%20up%20energy%20for%20the%20immune%20system%20to%20perform%20these%20critical%20tasks.) на важные иммунные задачи. Например, [активируются](https://www.sleepfoundation.org/physical-health/how-sleep-affects-immunity#:~:text=Sleep%20is%20an,off%20an%20infection.) воспалительные процессы, помогающие заживлять раны и бороться с инфекциями. [[../../../../knowledge/health/болезни/Недосып|Недосып]] же имеет обратный эффект: те, кто спят меньше семи часов, [простужаются](https://pubmed.ncbi.nlm.nih.gov/19139325/#:~:text=There%20was%20a%20graded%20association%20with%20average%20sleep%20duration%3A%20participants%20with%20less%20than%207%20hours%20of%20sleep%20were%202.94%20times%20(95%25%20confidence%20interval%20%5BCI%5D%2C%201.18%2D7.30)%20more%20likely%20to%20develop%20a%20cold%20than%20those%20with%208%20hours%20or%20more%20of%20sleep.) почти в три раза чаще, чем спящие по восемь часов.
|
**Сон нужен иммунной системе.** Во сне наше дыхание замедляется, а мышцы почти неподвижны, поэтому энергия в организме может [пойти](https://www.sleepfoundation.org/physical-health/how-sleep-affects-immunity#:~:text=During%20sleep%2C%20breathing%20and%20muscle%20activity%20slows%20down%2C%20freeing%20up%20energy%20for%20the%20immune%20system%20to%20perform%20these%20critical%20tasks.) на важные иммунные задачи. Например, [активируются](https://www.sleepfoundation.org/physical-health/how-sleep-affects-immunity#:~:text=Sleep%20is%20an,off%20an%20infection.) воспалительные процессы, помогающие заживлять раны и бороться с инфекциями. [[../../../../knowledge/health/болезни/Недосып|Недосып]] же имеет обратный эффект: те, кто спят меньше семи часов, [простужаются](https://pubmed.ncbi.nlm.nih.gov/19139325/#:~:text=There%20was%20a%20graded%20association%20with%20average%20sleep%20duration%3A%20participants%20with%20less%20than%207%20hours%20of%20sleep%20were%202.94%20times%20(95%25%20confidence%20interval%20%5BCI%5D%2C%201.18%2D7.30)%20more%20likely%20to%20develop%20a%20cold%20than%20those%20with%208%20hours%20or%20more%20of%20sleep.) почти в три раза чаще, чем спящие по восемь часов.
|
||||||
|
|
||||||
**Сон [формирует](https://www.pnas.org/doi/10.1073/pnas.2201795119) и закрепляет воспоминания**. Этот процесс называется [консолидация памяти](Консолидация%20памяти.md). Это подтверждается экспериментами: одна группа людей училась утром, а другая вечером. Контрольный тест показал, что чем ближе обучение ко сну, тем лучше усваивается информация.
|
**Сон [формирует](https://www.pnas.org/doi/10.1073/pnas.2201795119) и закрепляет воспоминания**. Этот процесс называется [консолидация памяти](Консолидация%20памяти.md). Это подтверждается экспериментами: одна группа людей училась утром, а другая вечером. Контрольный тест показал, что чем ближе обучение ко сну, тем лучше усваивается информация.
|
||||||
|
|
||||||
Еще во сне мы [продолжаем](https://now.tufts.edu/2021/02/18/new-theory-why-we-dream#:~:text=In%20essence%2C%20that%E2%80%99s,need%20of%20disruption.) искать решение проблем, которые волновали нас днем.
|
Еще во сне мы [продолжаем](https://now.tufts.edu/2021/02/18/new-theory-why-we-dream#:~:text=In%20essence%2C%20that%E2%80%99s,need%20of%20disruption.) искать решение проблем, которые волновали нас днем.
|
||||||
## Как возникает сон
|
## Как возникает сон
|
||||||
![](Циркадные%20ритмы.md#^a1a364)
|
![](Циркадные%20ритмы.md#^a1a364)
|
||||||
![](Мелатонин.md#^381eb3)
|
![](Мелатонин.md#^381eb3)
|
||||||
|
Loading…
Reference in New Issue
Block a user