29
dev/architecture/API Gateway.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103020227.png|600]]
|
||||
|
||||
**Шаг 1**: Клиент отправляет [[../network/HTTP|HTTP]]-запрос на API-шлюз.
|
||||
**Шаг 2**: API-шлюз анализирует и проверяет атрибуты запроса.
|
||||
**Шаг 3**: API-шлюз выполняет проверки по спискам разрешений и запретов (allow-list/deny-list).
|
||||
**Шаг 4**: API-шлюз взаимодействует с поставщиком идентификаций для аутентификации и авторизации.
|
||||
**Шаг 5**: К запросу применяются правила ограничения скорости. Если превышен лимит, запрос отклоняется.
|
||||
**Шаги 6 и 7**: После прохождения базовых проверок API-шлюз ищет нужный сервис для маршрутизации, сопоставляя путь запроса.
|
||||
**Шаг 8**: API-шлюз преобразует запрос в нужный протокол и отправляет его на [[бэкенд]] микросервисов.
|
||||
**Шаги 9-12**: API-шлюз обрабатывает ошибки и справляется с длительными сбоями (circuit break). Также он может использовать стек ELK (Elastic-Logstash-Kibana) для логирования и мониторинга. Иногда данные кэшируются в самом API-шлюзе.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
@ -9,6 +9,8 @@ zero-link:
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103022605.png]]
|
||||
|
||||
CAP теорема — это принцип, описывающий фундаментальные ограничения, с которыми сталкиваются распределённые вычислительные системы в контексте обеспечения следующих трёх свойств:
|
||||
- **Согласованность (Consistency)**: Каждый раз, когда данные читаются, возвращается самое последнее записанное значение или ошибка. С другими словами, операции с данными выглядят так, будто выполняются в некоторой строгой последовательности, одна за другой
|
||||
- **Доступность (Availability)**: Каждый запрос на получение или запись данных получает ответ, независимо от состояния системы, даже если некоторые части системы вышли из строя.
|
||||
@ -16,6 +18,8 @@ CAP теорема — это принцип, описывающий фунда
|
||||
|
||||
==Согласно теореме CAP, в любой момент времени система может обеспечивать только два из этих трёх свойств.== Это означает, что при разработке системы приходится принимать компромисс между этими свойствами в зависимости от требований приложения и условий эксплуатации. Например, если для системы критически важна согласованность данных и её устойчивость к разделению, возможно придётся пожертвовать её доступностью в некоторых сценариях.
|
||||
|
||||
|
||||
|
||||
## Свободные заметки
|
||||
- Google заявляет, что их продукт Google Spanner якобы нарушает CAP теорему.
|
||||
***
|
||||
|
@ -2,6 +2,7 @@
|
||||
aliases:
|
||||
- событийного цикла
|
||||
- событийный цикл
|
||||
- single-threaded execution loop
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2023-10-26
|
||||
|
30
dev/architecture/highload/Балансировка нагрузки.md
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
aliases:
|
||||
- балансировку нагрузки
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-06-13
|
||||
---
|
||||
![[../../../meta/files/images/Pasted image 20241103021050.png]]
|
||||
|
||||
**Статические алгоритмы**
|
||||
- **Round robin**. Запросы от клиентов отправляются поочередно разным экземплярам сервиса. Как правило, сервисы должны быть stateless (не сохранять состояние между запросами).
|
||||
- **Sticky round-robin** Улучшенная версия алгоритма round robin. Если первый запрос от Алисы попал на сервис A, то и все последующие её запросы будут отправляться на этот же сервис A.
|
||||
- **Weighted round-robin** Администратор может задать вес для каждого сервиса. Сервисы с большим весом будут обрабатывать больше запросов, чем другие.
|
||||
- **Hash (Хеширование)** Этот алгоритм применяет хеш-функцию к IP-адресу или URL запроса. Запросы направляются на соответствующие экземпляры сервиса в зависимости от результата [[../../cryptography/Хеш-функция|хеш-функции]].
|
||||
|
||||
**Динамические алгоритмы**
|
||||
- **Least connections**. Новый запрос отправляется экземпляру сервиса с наименьшим числом текущих соединений.
|
||||
- **Least response time.** Новый запрос отправляется на экземпляр сервиса с самым быстрым временем отклика.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-13]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
@ -27,7 +27,7 @@ linked:
|
||||
|
||||
**Контракт API**: В контексте API контрактом является описание того, как клиент может взаимодействовать с API. Это включает в себя форматы запросов и ответов, методы HTTP, параметры, типы данных, кодировки и обработку ошибок.
|
||||
|
||||
Пример контракта REST API:
|
||||
Пример контракта [[../system-design/RESTful|REST]] API:
|
||||
- Метод: `POST /users`
|
||||
- Входные данные: JSON-объект с полями `name` и `email`
|
||||
- Ответ: код 201 (Created) и объект пользователя
|
||||
|
@ -26,15 +26,18 @@ linked:
|
||||
## Уровни кэширования
|
||||
![](../../meta/files/images/Pasted%20image%2020240617195054.png)
|
||||
|
||||
![](../../meta/files/images/Pasted%20image%2020240701115612.png)
|
||||
![[../../meta/files/images/Pasted image 20241103033544.png]]
|
||||
|
||||
Уровни кэширования:
|
||||
- [Кэширование в приложении](Кэширование%20в%20приложении.md)
|
||||
- [Кэширование на стороне браузера](highload/Кэширование%20на%20стороне%20браузера.md). Ответы HTTP могут кэшироваться браузером. При первом запросе данных по HTTP они возвращаются с политикой истечения срока действия в заголовке HTTP. При повторном запросе данных клиентское приложение сначала пытается получить их из кэша браузера.
|
||||
- [Кэширование на стороне Nginx](../devops/nginx/Кэширование%20на%20стороне%20Nginx.md)
|
||||
- [Кэширование на стороне браузера](highload/Кэширование%20на%20стороне%20браузера.md)
|
||||
- [Content Delivery Network](highload/Content%20Delivery%20Network.md)
|
||||
- [Content Delivery Network](highload/Content%20Delivery%20Network.md). CDN кэширует статические веб-ресурсы. Клиенты могут получать данные с ближайшего узла CDN.
|
||||
- **Балансировщик нагрузки**: Балансировщик также может кэшировать ресурсы.
|
||||
- [Кэширование в приложении](Кэширование%20в%20приложении.md). В сервисах есть несколько уровней кэша. Если данные не находятся в кэше процессора, сервис пытается получить их из памяти. Иногда в сервисе есть вторичный уровень кэша для хранения данных на диске.
|
||||
- **Распределённый кэш**: Распределённые кэши, такие как Redis, хранят пары ключ-значение в памяти для множества сервисов. Это обеспечивает значительно лучшую производительность чтения и записи по сравнению с базой данных.
|
||||
- **База данных**: Даже в базе данных есть различные уровни кэша
|
||||
|
||||
Виды кэширования:
|
||||
**Виды кэширования:**
|
||||
- Сквозное. Все запросы проходят через кэш. [Схема](../../meta/files/images/Pasted%20image%2020240617194731.png).
|
||||
- Кэширование на стороне сервиса. [Схема](../../meta/files/images/Pasted%20image%2020240617194759.png).
|
||||
- Опережающее. Кладем данные в кэш заранее. [Схема](../../meta/files/images/Pasted%20image%2020240617194938.png).
|
||||
@ -45,7 +48,9 @@ linked:
|
||||
|
||||
При желании результат кэширования можно сжать используя [[../algorithm/GZIP|GZIP]]. Однако, приходится использовать [[../other/Base64|Base64]], чтобы преобразовать байты полученные от gzip в строку, и уже в таком виде положить в Redis. Не смотря на то, что Base64 увеличивает размер строки на 33% все равно получается намного компактнее, чем просто JSON.
|
||||
|
||||
Рано или поздно исходные данные изменяются, и кэш перестает быть валидным. Часто важно, чтобы кэш сбрасывался сразу же за изменением. За это отвечает [[highload/Инвалидация кэша|Инвалидация кэша]]
|
||||
Рано или поздно исходные данные изменяются, и кэш перестает быть валидным. Часто важно, чтобы кэш сбрасывался сразу же за изменением. За это отвечает [[highload/Инвалидация кэша|Инвалидация кэша]].
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103035011.png]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
|
@ -12,7 +12,25 @@ linked:
|
||||
---
|
||||
- [[Dependency Injection]]
|
||||
- [[Порождающий паттерн проектирования]]
|
||||
- [[Builder Pattern|Builder Pattern]]
|
||||
|
||||
- Abstract Factory: создаёт группы связанных элементов.
|
||||
- [[Builder Pattern|Builder Pattern]]: строит объекты поэтапно, разделяя процесс создания и внешний вид.
|
||||
- Prototype: создаёт копии полностью подготовленных экземпляров.
|
||||
- Singleton: One and Only — особый класс, имеющий только один экземпляр.
|
||||
- Adapter: Universal Plug — соединяет объекты с разными интерфейсами.
|
||||
- Bridge: Function Connector — связывает, как объект работает, с тем, что он делает.
|
||||
- Composite: Tree Builder — формирует древовидные структуры из простых и сложных частей.
|
||||
- Decorator: Customizer — добавляет функции объектам, не меняя их основу.
|
||||
- Facade: One-Stop-Shop — представляет всю систему через один упрощённый интерфейс.
|
||||
- Flyweight: Space Saver — эффективно использует небольшие, многократно используемые элементы.
|
||||
- Proxy: Stand-In Actor — представляет другой объект, управляя доступом или действиями.
|
||||
- Chain of Responsibility: Request Relay — передаёт запрос по цепочке объектов до его обработки.
|
||||
- Command: Task Wrapper — превращает запрос в объект, готовый к выполнению.
|
||||
- Iterator: Collection Explorer — последовательно получает доступ к элементам коллекции.
|
||||
- Mediator: Communication Hub — упрощает взаимодействие между различными классами.
|
||||
- Memento: Time Capsule — сохраняет и восстанавливает состояние объекта.
|
||||
- Observer: News Broadcaster — уведомляет классы об изменениях в других объектах.
|
||||
- Visitor: Skillful Guest — добавляет новые операции классу, не изменяя его.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
|
@ -1,7 +1,6 @@
|
||||
---
|
||||
aliases:
|
||||
- хеш-функция
|
||||
- хеш-функцию
|
||||
- хеш функция
|
||||
- хеш функции
|
||||
- хеш-функции
|
||||
|
@ -5,7 +5,7 @@ tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-30
|
||||
---
|
||||
Блок `upstream` используется для указания списка серверов, между которыми nginx будет распределять входящие запросы, тем самым обеспечивая [[../../../../../_inbox/Балансировка нагрузки|балансировку нагрузки]]. В блоке `upstream` перечисляются серверы, между которыми будет распределяться нагрузка.
|
||||
Блок `upstream` используется для указания списка серверов, между которыми nginx будет распределять входящие запросы, тем самым обеспечивая [[../../architecture/highload/Балансировка нагрузки|балансировку нагрузки]]. В блоке `upstream` перечисляются серверы, между которыми будет распределяться нагрузка.
|
||||
|
||||
```nginx
|
||||
upstream myapp {
|
||||
|
@ -8,8 +8,11 @@ zero-link:
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
![[../../../meta/files/images/Pasted image 20241103022447.png]]
|
||||
|
||||
- [[Tree|Дерево]]
|
||||
- [[structure/Хеш-таблица|Хеш-таблица]]
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 Разработка|00 Разработка]]
|
||||
|
40
dev/network/HTTP.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-29
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103014445.png]]
|
||||
|
||||
**HTTP 1.0** был завершён и полностью задокументирован в 1996 году. Для каждого запроса к одному и тому же серверу требуется отдельное [[../../../../knowledge/dev/network/TCP|TCP]]-соединение.
|
||||
|
||||
**HTTP 1.1** был опубликован в 1997 году. [[../../../../knowledge/dev/network/TCP|TCP]]-соединение теперь можно оставить открытым для повторного использования (постоянное соединение), но проблема блокировки первой строки (Head-of-Line, HOL) не решена.
|
||||
|
||||
> [!NOTE] Head-of-Line, HOL
|
||||
> Ситуация, когда лимит параллельных запросов в браузере исчерпан, и последующие запросы вынуждены ждать завершения предыдущих.
|
||||
|
||||
**HTTP 2.0** был опубликован в 2015 году. Он решает проблему HOL на уровне приложения благодаря мультиплексированию запросов, устраняя блокировку HOL на этом уровне. Однако проблема остаётся на транспортном уровне ([[../../../../knowledge/dev/network/TCP|TCP]]).
|
||||
|
||||
Как показано на диаграмме, HTTP 2.0 ввёл концепцию HTTP “streams”: это абстракция, которая позволяет мультиплексировать различные HTTP-запросы в рамках одного [[../../../../knowledge/dev/network/TCP|TCP]]-соединения. Каждый поток может передаваться независимо от остальных.
|
||||
|
||||
**HTTP 3.0** впервые был опубликован в виде черновика в 2020 году. Он предложен как преемник HTTP 2.0. Вместо [[../../../../knowledge/dev/network/TCP|TCP]] для транспортного уровня используется протокол QUIC, что устраняет блокировку HOL на уровне транспорта.
|
||||
|
||||
**QUIC** основан на протоколе **UDP**. Он вводит потоки как полноценные сущности на уровне транспорта. Потоки QUIC используют одно и то же соединение QUIC, поэтому для создания новых потоков не требуется дополнительных рукопожатий и медленного старта. При этом потоки QUIC доставляются независимо друг от друга, что означает, что в большинстве случаев потеря пакетов, влияющая на один поток, не затрагивает остальные.
|
||||
|
||||
|
||||
![[../../meta/files/images/photo_2024-10-29 18.27.09.jpeg]]
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103035804.png]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Сети|00 Сети]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
@ -6,14 +6,20 @@ tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-01-11
|
||||
zero-link: []
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
|
||||
> [!WARNING]
|
||||
> Теоретическая модель, которая на практике не используется
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103020737.png]]
|
||||
- **Шаг 1**: Когда Устройство A отправляет данные на Устройство B по сети через протокол [[HTTP]], к данным сначала добавляется HTTP-заголовок на уровне приложения.
|
||||
- **Шаг 2**: Затем к данным добавляется заголовок [[../../../../knowledge/dev/network/TCP|TCP]] или [[../../../../knowledge/dev/network/UDP|UDP]]. На транспортном уровне данные инкапсулируются в TCP-сегменты, содержащие информацию о портах отправителя и получателя, а также номер последовательности.
|
||||
- **Шаг 3**: Сегменты инкапсулируются с IP-заголовком на сетевом уровне. IP-заголовок содержит IP-адреса отправителя и получателя.
|
||||
- **Шаг 4**: На канальном уровне к IP-датаграмме добавляется MAC-заголовок с MAC-адресами отправителя и получателя.
|
||||
- **Шаг 5**: Инкапсулированные кадры передаются на физический уровень и отправляются по сети в виде бинарных данных.
|
||||
- **Шаги 6-10**: Когда Устройство B получает биты из сети, оно выполняет процесс деинкапсуляции, то есть обратный процесс инкапсуляции. Заголовки удаляются слой за слоем, и в итоге Устройство B может прочитать полученные данные.
|
||||
|
||||
|
||||
| Уровень | DataUnit | Описание |
|
||||
| ---- | ---- | ---- |
|
||||
| Physical | Bit | Сигналы |
|
||||
|
24
dev/network/Uniform Resource Identifier.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
aliases:
|
||||
- URI
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
URI (Uniform Resource Identifier) — унифицированный идентификатор ресурса. Он определяет логический или физический ресурс в интернете. URL и URN являются подтипами URI: URL указывает расположение ресурса, а URN — его имя.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103021719.png]]
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Сети|00 Сети]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
25
dev/network/Uniform Resource Locator.md
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
aliases:
|
||||
- URL
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
URL (Uniform Resource Locator) — унифицированный указатель ресурса, ключевое понятие в [[HTTP|HTTP]]. URL представляет собой адрес уникального ресурса в интернете. URL также можно использовать с другими протоколами, такими как FTP и JDBC.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103021925.png]]
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Сети|00 Сети]]
|
||||
**Родитель**:: [[Uniform Resource Identifier|Uniform Resource Identifier]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
43
dev/snippet/Конфигурация gRPC соединения в Quarkus.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-04-03
|
||||
---
|
||||
```java
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
|
||||
@ApplicationScoped
|
||||
public class AppealSdkManager {
|
||||
|
||||
private final Vertx vertx;
|
||||
private final MutinyAppealGrpcApiGrpc.MutinyAppealGrpcApiStub grpcClient;
|
||||
|
||||
public AppealSdkManager(
|
||||
@ConfigProperty(name = "crm.service.appeal.grpc.host", defaultValue = "communication-appeal-service") String storageHost,
|
||||
@ConfigProperty(name = "crm.service.appeal.grpc.port", defaultValue = "8090") int storagePort,
|
||||
Vertx vertx
|
||||
) {
|
||||
this.vertx = vertx;
|
||||
final ManagedChannel channel = ManagedChannelBuilder.forAddress(storageHost, storagePort)
|
||||
.usePlaintext()
|
||||
.executor(MutinyHelper.executor(Vertx.currentContext()))
|
||||
.idleTimeout(5, TimeUnit.MINUTES)
|
||||
.build();
|
||||
this.grpcClient = MutinyAppealGrpcApiGrpc.newMutinyStub(channel);
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Quarkus|00 Quarkus]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-04-03]]
|
||||
### Дополнительные материалы
|
||||
- [[../system-design/gRPC|gRPC]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
29
dev/system-design/GraphQL.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103004648.png]]
|
||||
|
||||
- Предоставляет клиентам единую конечную точку для запроса именно тех данных, которые им нужны.
|
||||
- Клиенты указывают точные поля, требуемые во вложенных запросах, и сервер возвращает оптимизированный ответ, содержащую только эти поля.
|
||||
- Поддерживает модификации для изменения данных и подписки на уведомления в режиме реального времени.
|
||||
- Отлично подходит для объединения данных из нескольких источников и хорошо работает с быстро меняющимися требованиями к интерфейсу.
|
||||
- Однако это переносит сложность на сторону клиента и может допускать некорректные запросы, если они не защищены должным образом.
|
||||
- Стратегии кэширования могут быть более сложными, чем [[RESTful|REST]].
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 System Design|00 System Design]]
|
||||
**Родитель**:: [[Протоколы коммуникаций|Протоколы коммуникаций]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
29
dev/system-design/Long polling.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
**Long polling** — это метод опроса сервера, при котором клиент отправляет запрос и остается подключенным к серверу, ожидая ответа до тех пор, пока не появятся новые данные. Если серверу нечего отправить, он удерживает запрос открытым, пока не произойдет обновление, или пока не истечет тайм-аут. После получения ответа клиент сразу отправляет новый запрос для продолжения ожидания.
|
||||
|
||||
**Преимущества:**
|
||||
- Меньше нагрузка на сервер по сравнению с [[Short polling]], так как запросы отправляются реже, только когда есть новые данные.
|
||||
- Обеспечивает более оперативное получение обновлений, чем при обычном коротком опросе.
|
||||
|
||||
**Недостатки:**
|
||||
- Задержка может быть непредсказуемой, особенно если данные появляются нерегулярно.
|
||||
- Удержание открытого соединения может быть менее эффективным для серверов с ограниченными ресурсами, особенно при большом количестве клиентов.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 System Design|00 System Design]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Short polling]]
|
||||
- [[Webhook]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
29
dev/system-design/RESTful.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
- REST
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103004607.png]]
|
||||
|
||||
|
||||
- Использует стандартные HTTP-методы, такие как GET, POST, PUT, DELETE, для операций CRUD.
|
||||
- Хорошо работает, когда вам нужны простые, единообразные интерфейсы между отдельными сервисами / приложениями.
|
||||
- Стратегии кэширования просты в реализации.
|
||||
- Недостатком является то, что для сбора связанных данных из отдельных конечных точек может потребоваться несколько обходов.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103020635.png]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 System Design|00 System Design]]
|
||||
**Родитель**:: [[Протоколы коммуникаций|Протоколы коммуникаций]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
27
dev/system-design/Remote Procedure Call.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
aliases:
|
||||
- RPC
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
RPC (удалённый вызов процедур) — это **общая концепция и протокол**, позволяющая программе вызывать функции или методы, которые выполняются на удалённом сервере, так, как будто они выполняются локально. В RPC клиент запрашивает сервер, чтобы тот выполнил определённую функцию и вернул результат. Концепция RPC используется для создания распределённых систем, и её можно реализовать разными способами и технологиями.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103005803.png]]
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 System Design|00 System Design]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[gRPC]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
33
dev/system-design/Short polling.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
**Short polling** — это метод опроса сервера, при котором клиент периодически отправляет запросы для проверки обновлений или новых данных. В отличие от постоянного соединения, клиент инициирует запросы через заданные интервалы, например, каждую секунду или каждые несколько секунд.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103010806.png|600]]
|
||||
|
||||
**Преимущества:**
|
||||
- Простая реализация, подходит для приложений, где данные обновляются редко.
|
||||
|
||||
**Недостатки:**
|
||||
- Высокая нагрузка на сервер и сеть из-за частых запросов, даже если данные не изменились.
|
||||
- Может приводить к задержкам в получении данных, так как обновления видны только при очередном запросе.
|
||||
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**::
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Long polling]]
|
||||
- [[Webhook]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
31
dev/system-design/Webhook.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
**Webhook** — это метод взаимодействия между системами, при котором один сервер автоматически отправляет HTTP-запрос на другой сервер, когда происходит определенное событие. В отличие от [[Long polling|Long polling]] или [[Short polling|Short polling]], клиенту не нужно регулярно проверять наличие обновлений; вместо этого он получает уведомление от сервера в режиме реального времени.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103010806.png|600]]
|
||||
|
||||
**Преимущества:**
|
||||
- Мгновенная доставка данных при возникновении события.
|
||||
- Снижение нагрузки на сервер, так как нет необходимости в регулярных запросах.
|
||||
|
||||
**Недостатки:**
|
||||
- Требует настройки безопасности для предотвращения нежелательных вызовов (например, использование токенов или подписи).
|
||||
- Сложнее тестировать и отлаживать, так как вебхуки зависят от событий, происходящих на сервере.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 System Design|00 System Design]]
|
||||
**Родитель**:: [[Протоколы коммуникаций]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Short polling]]
|
||||
- [[Long polling]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
30
dev/system-design/gRPC.md
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-04-12
|
||||
---
|
||||
- Подходит для [[../../../../wiki/zero/Микросервисная архитектура|микросервисных архитектур]] для межсервисного общения.
|
||||
|
||||
## Как работает?
|
||||
![[../../meta/files/images/Pasted image 20241103005832.png]]
|
||||
|
||||
- **Шаг 1**: Клиент отправляет REST-запрос. Тело запроса обычно в формате JSON.
|
||||
- **Шаги 2 - 4**: Сервис заказов (gRPC-клиент) получает REST-запрос, преобразует запрос в компактный бинарный формат и передает его в транспортный слой
|
||||
- **Шаг 5**: gRPC отправляет пакеты по сети через HTTP/2. Благодаря бинарному кодированию и сетевым оптимизациям, gRPC считается в 5 раз быстрее, чем JSON.
|
||||
- **Шаги 6 - 8**: Сервис оплаты (gRPC-сервер) получает пакеты из сети, декодирует их и вызывает серверное приложение.
|
||||
- **Шаги 9 - 11**: Результат возвращается от серверного приложения, кодируется и передаётся на транспортный уровень.
|
||||
- **Шаги 12 - 14**: Сервис заказов получает пакеты, декодирует их и отправляет результат в клиентское приложение.
|
||||
## Проблемы
|
||||
**Балансировка нагрузки L7 vs L4**: Kubernetes обычно использует балансировку нагрузки на уровне 4 (L4), которая перенаправляет трафик на основе информации IP и порта. Однако gRPC полагается на HTTP/2, что требует балансировки на уровне 7 (L7) для эффективного распределения запросов. Это может потребовать дополнительных настроек или использования специализированных ингресс-контроллеров, поддерживающих HTTP/2.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 System Design|00 System Design]]
|
||||
**Родитель**:: [[Remote Procedure Call|RPC]], [[Протоколы коммуникаций]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-04-12]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
42
dev/system-design/Протоколы коммуникаций.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103004117.png]]
|
||||
|
||||
- [[../../../../_inbox/SOAP|SOAP]]
|
||||
- Основан на XML
|
||||
- [[RESTful]]
|
||||
- Популярный, легко реализуемый, методы HTTP
|
||||
- Идеален для веб-сервисов
|
||||
- [[GraphQL]]
|
||||
- Язык запросов, позволяет запрашивать конкретные данные
|
||||
- [[gRPC|gRPC]]
|
||||
- Современный, высокопроизводительный, использует Protocol Buffers
|
||||
- Подходит для микросервисных архитектур для межсервисного общения.
|
||||
- WebSocket
|
||||
- В режиме реального времени, двунаправленные, постоянные соединения
|
||||
- [[Webhook]]
|
||||
- Событийный, HTTP-обратные вызовы, асинхронный
|
||||
- Уведомляет системы при наступлении событий
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 System Design|00 System Design]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[RESTful]]
|
||||
- [[GraphQL]]
|
||||
- [[gRPC]]
|
||||
- [[Webhook]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
39
dev/Команды Redis-cli.md
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
[Commands | Docs](https://redis.io/docs/latest/commands/)
|
||||
|
||||
Положить данные в редис:
|
||||
```redis
|
||||
set test hello
|
||||
```
|
||||
|
||||
Прочитать
|
||||
```redis
|
||||
get test
|
||||
```
|
||||
|
||||
Удалить ключ
|
||||
```redis
|
||||
del test
|
||||
```
|
||||
|
||||
Keys - команда, которая ищет ключи по маске. Используется итератор для поиска, поэтому рекомендуется не использовать, так как сразу оказывает влияние на производительность.
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../wiki/zero/00 Redis|00 Redis]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
32
dev/Конфигурация Redis.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
- [Redis configuration file example | Docs](https://redis.io/docs/latest/operate/oss_and_stack/management/config-file/)
|
||||
|
||||
- `stop-writes-on-bg-save-error`. Если на snapshot возникает какая-то проблема, то Redis перестает работать. По умолчанию yes. Обычно рекомендуется отключать. Тогда могут возникнуть проблемы с персистентностью, но хотя бы память озу будет работать.
|
||||
- `rdbcompression`. Немного влияет негативно на производительность, но уменьшает размер хранимых данных.
|
||||
- `save <seconds> <changes>`. **Триггеры создания снапшотов** [[../../../_inbox/Redis Database Backup|RDB]]:
|
||||
- save 900 1 — сохранить снапшот, если в течение последних 900 секунд (15 минут) было выполнено хотя бы 1 изменение.
|
||||
- save 300 10 — сохранить снапшот, если за последние 300 секунд (5 минут) было выполнено 10 изменений.
|
||||
- save 60 10000 — сохранить снапшот, если за последние 60 секунд (1 минута) было выполнено 10 000 изменений.
|
||||
- [[../../../_inbox/Append-Only File|appendonly]]
|
||||
- Можно указать [[algorithm/Алгоритм вытеснения кэша|Алгоритмы вытеснения]] ключей
|
||||
- `oom-score-adj-values`
|
||||
- `disable-thp`. Лучше выключить. По умолчанию выключено.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../wiki/zero/00 Redis|00 Redis]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
Before Width: | Height: | Size: 1.6 MiB |
BIN
meta/files/images/Pasted image 20241103004117.png
Normal file
After Width: | Height: | Size: 263 KiB |
BIN
meta/files/images/Pasted image 20241103004607.png
Normal file
After Width: | Height: | Size: 331 KiB |
BIN
meta/files/images/Pasted image 20241103004648.png
Normal file
After Width: | Height: | Size: 556 KiB |
BIN
meta/files/images/Pasted image 20241103005803.png
Normal file
After Width: | Height: | Size: 391 KiB |
BIN
meta/files/images/Pasted image 20241103005832.png
Normal file
After Width: | Height: | Size: 943 KiB |
BIN
meta/files/images/Pasted image 20241103010806.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
meta/files/images/Pasted image 20241103014445.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
meta/files/images/Pasted image 20241103020227.png
Normal file
After Width: | Height: | Size: 873 KiB |
BIN
meta/files/images/Pasted image 20241103020635.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
meta/files/images/Pasted image 20241103020737.png
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
meta/files/images/Pasted image 20241103021050.png
Normal file
After Width: | Height: | Size: 3.4 MiB |
BIN
meta/files/images/Pasted image 20241103021719.png
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
meta/files/images/Pasted image 20241103021925.png
Normal file
After Width: | Height: | Size: 184 KiB |
BIN
meta/files/images/Pasted image 20241103022447.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
meta/files/images/Pasted image 20241103022605.png
Normal file
After Width: | Height: | Size: 942 KiB |
BIN
meta/files/images/Pasted image 20241103032953.png
Normal file
After Width: | Height: | Size: 550 KiB |
BIN
meta/files/images/Pasted image 20241103033345.png
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
meta/files/images/Pasted image 20241103033544.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
meta/files/images/Pasted image 20241103034136.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
meta/files/images/Pasted image 20241103035011.png
Normal file
After Width: | Height: | Size: 1012 KiB |
BIN
meta/files/images/Pasted image 20241103035418.png
Normal file
After Width: | Height: | Size: 748 KiB |
BIN
meta/files/images/Pasted image 20241103035804.png
Normal file
After Width: | Height: | Size: 905 KiB |
BIN
meta/files/images/comp/Pasted image 20241103004117.png
Normal file
After Width: | Height: | Size: 99 KiB |
@ -0,0 +1 @@
|
||||
f0f6cbe3b8f709babd75b3ba6e77d85f
|
BIN
meta/files/images/comp/Pasted image 20241103004607.png
Normal file
After Width: | Height: | Size: 107 KiB |
@ -0,0 +1 @@
|
||||
9f15418682d0d4ec4c8b8e1a31ad90db
|
BIN
meta/files/images/comp/Pasted image 20241103004648.png
Normal file
After Width: | Height: | Size: 168 KiB |
@ -0,0 +1 @@
|
||||
2b0e498563bfc68f771c1fde6f933483
|
BIN
meta/files/images/comp/Pasted image 20241103005803.png
Normal file
After Width: | Height: | Size: 111 KiB |
@ -0,0 +1 @@
|
||||
dacf4ed39756d973bb0ebc581334b772
|
BIN
meta/files/images/comp/Pasted image 20241103005832.png
Normal file
After Width: | Height: | Size: 248 KiB |
@ -0,0 +1 @@
|
||||
2ba70e473c0e94a3effb8fed01b98596
|
BIN
meta/files/images/comp/Pasted image 20241103010806.png
Normal file
After Width: | Height: | Size: 426 KiB |
@ -0,0 +1 @@
|
||||
7cf49819565b0d088320d13f63725a7b
|
BIN
meta/files/images/comp/Pasted image 20241103014445.png
Normal file
After Width: | Height: | Size: 423 KiB |
@ -0,0 +1 @@
|
||||
17fd1ca4a019007eec870ec48503a054
|
BIN
meta/files/images/comp/Pasted image 20241103020227.png
Normal file
After Width: | Height: | Size: 278 KiB |
@ -0,0 +1 @@
|
||||
490ce653ca2f724f1ac32b52f988ae7d
|
BIN
meta/files/images/comp/Pasted image 20241103020635.png
Normal file
After Width: | Height: | Size: 450 KiB |
@ -0,0 +1 @@
|
||||
ddef181237494255f3495d823536c250
|
BIN
meta/files/images/comp/Pasted image 20241103020737.png
Normal file
After Width: | Height: | Size: 530 KiB |
@ -0,0 +1 @@
|
||||
6fc9b4d7600da35cf0228e00df19ec91
|
BIN
meta/files/images/comp/Pasted image 20241103021050.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
@ -0,0 +1 @@
|
||||
5774711ed76b912999015e8606b37a43
|
BIN
meta/files/images/comp/Pasted image 20241103021719.png
Normal file
After Width: | Height: | Size: 47 KiB |
@ -0,0 +1 @@
|
||||
9ee7723896482ce9836ed0ec136dee50
|
BIN
meta/files/images/comp/Pasted image 20241103021925.png
Normal file
After Width: | Height: | Size: 46 KiB |
@ -0,0 +1 @@
|
||||
c1179cf5d896ca0df0c577398b8ba56e
|
BIN
meta/files/images/comp/Pasted image 20241103022447.png
Normal file
After Width: | Height: | Size: 493 KiB |
@ -0,0 +1 @@
|
||||
7d38aa5b4f6e4c4b429d674dfd73cc8a
|
BIN
meta/files/images/comp/Pasted image 20241103022605.png
Normal file
After Width: | Height: | Size: 318 KiB |
@ -0,0 +1 @@
|
||||
628bb9f12b3a5d04e3d0d7772b3884a6
|
BIN
meta/files/images/comp/Pasted image 20241103032953.png
Normal file
After Width: | Height: | Size: 183 KiB |
@ -0,0 +1 @@
|
||||
5c579fe1aa8254db723d6add4c9cd45e
|
BIN
meta/files/images/comp/Pasted image 20241103033345.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
@ -0,0 +1 @@
|
||||
49a8abac5981ad9429ad75992d32725e
|
BIN
meta/files/images/comp/Pasted image 20241103033544.png
Normal file
After Width: | Height: | Size: 417 KiB |
@ -0,0 +1 @@
|
||||
2b47d98d5d230a80798f967a4ca86ed1
|
BIN
meta/files/images/comp/Pasted image 20241103034136.png
Normal file
After Width: | Height: | Size: 416 KiB |
@ -0,0 +1 @@
|
||||
ecc48a35ac34b7be35071c8575ea3fe0
|
BIN
meta/files/images/comp/Pasted image 20241103035011.png
Normal file
After Width: | Height: | Size: 377 KiB |
@ -0,0 +1 @@
|
||||
d4619aeb0d0fdf329e7e0c3a5a54de19
|
BIN
meta/files/images/comp/Pasted image 20241103035418.png
Normal file
After Width: | Height: | Size: 214 KiB |
@ -0,0 +1 @@
|
||||
18f4cfc5915a6d3646d32eb88619d375
|
BIN
meta/files/images/comp/Pasted image 20241103035804.png
Normal file
After Width: | Height: | Size: 301 KiB |
@ -0,0 +1 @@
|
||||
58181b293155e28c8751ef2a41026fdb
|
BIN
meta/files/images/photo_2024-10-29 18.27.09.jpeg
Normal file
After Width: | Height: | Size: 129 KiB |
BIN
meta/files/images/webp/Pasted image 20241103004117.webp
Normal file
After Width: | Height: | Size: 140 KiB |
@ -0,0 +1 @@
|
||||
f0f6cbe3b8f709babd75b3ba6e77d85f
|
BIN
meta/files/images/webp/Pasted image 20241103004607.webp
Normal file
After Width: | Height: | Size: 58 KiB |
@ -0,0 +1 @@
|
||||
9f15418682d0d4ec4c8b8e1a31ad90db
|
BIN
meta/files/images/webp/Pasted image 20241103004648.webp
Normal file
After Width: | Height: | Size: 89 KiB |
@ -0,0 +1 @@
|
||||
2b0e498563bfc68f771c1fde6f933483
|
BIN
meta/files/images/webp/Pasted image 20241103005803.webp
Normal file
After Width: | Height: | Size: 62 KiB |