mirror of https://github.com/tiangolo/fastapi.git
🌐 Update Russian translations for deployments docs (#11271)
This commit is contained in:
parent
247b58e0f5
commit
7ae1f9003f
|
|
@ -1,6 +1,6 @@
|
|||
# Концепции развёртывания
|
||||
|
||||
Существует несколько концепций, применяемых для развёртывания приложений **FastAPI**, равно как и для любых других типов веб-приложений, среди которых Вы можете выбрать **наиболее подходящий** способ.
|
||||
Существует несколько концепций, применяемых для развёртывания приложений **FastAPI**, равно как и для любых других типов веб-приложений, среди которых вы можете выбрать **наиболее подходящий** способ.
|
||||
|
||||
Самые важные из них:
|
||||
|
||||
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
Рассмотрим ниже влияние каждого из них на процесс **развёртывания**.
|
||||
|
||||
Наша конечная цель - **обслуживать клиентов Вашего API безопасно** и **бесперебойно**, с максимально эффективным использованием **вычислительных ресурсов** (например, удалённых серверов/виртуальных машин). 🚀
|
||||
Наша конечная цель - **обслуживать клиентов вашего API безопасно** и **бесперебойно**, с максимально эффективным использованием **вычислительных ресурсов** (например, удалённых серверов/виртуальных машин). 🚀
|
||||
|
||||
Здесь я немного расскажу Вам об этих **концепциях** и надеюсь, что у Вас сложится **интуитивное понимание**, какой способ выбрать при развертывании Вашего API в различных окружениях, возможно, даже **ещё не существующих**.
|
||||
Здесь я немного расскажу Вам об этих **концепциях** и надеюсь, что у вас сложится **интуитивное понимание**, какой способ выбрать при развертывании вашего API в различных окружениях, возможно, даже **ещё не существующих**.
|
||||
|
||||
Ознакомившись с этими концепциями, Вы сможете **оценить и выбрать** лучший способ развёртывании **Вашего API**.
|
||||
Ознакомившись с этими концепциями, вы сможете **оценить и выбрать** лучший способ развёртывании **Вашего API**.
|
||||
|
||||
В последующих главах я предоставлю Вам **конкретные рецепты** развёртывания приложения FastAPI.
|
||||
|
||||
|
|
@ -25,15 +25,15 @@
|
|||
|
||||
## Использование более безопасного протокола HTTPS
|
||||
|
||||
В [предыдущей главе об HTTPS](./https.md){.internal-link target=_blank} мы рассмотрели, как HTTPS обеспечивает шифрование для Вашего API.
|
||||
В [предыдущей главе об HTTPS](./https.md){.internal-link target=_blank} мы рассмотрели, как HTTPS обеспечивает шифрование для вашего API.
|
||||
|
||||
Также мы заметили, что обычно для работы с HTTPS Вашему приложению нужен **дополнительный** компонент - **прокси-сервер завершения работы TLS**.
|
||||
Также мы заметили, что обычно для работы с HTTPS вашему приложению нужен **дополнительный** компонент - **прокси-сервер завершения работы TLS**.
|
||||
|
||||
И если прокси-сервер не умеет сам **обновлять сертификаты HTTPS**, то нужен ещё один компонент для этого действия.
|
||||
|
||||
### Примеры инструментов для работы с HTTPS
|
||||
|
||||
Вот некоторые инструменты, которые Вы можете применять как прокси-серверы:
|
||||
Вот некоторые инструменты, которые вы можете применять как прокси-серверы:
|
||||
|
||||
* Traefik
|
||||
* С автоматическим обновлением сертификатов ✨
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
* С дополнительным компонентом типа cert-manager для обновления сертификатов
|
||||
* Использование услуг облачного провайдера (читайте ниже 👇)
|
||||
|
||||
В последнем варианте Вы можете воспользоваться услугами **облачного сервиса**, который сделает большую часть работы, включая настройку HTTPS. Это может наложить дополнительные ограничения или потребовать дополнительную плату и т.п. Зато Вам не понадобится самостоятельно заниматься настройками прокси-сервера.
|
||||
В последнем варианте вы можете воспользоваться услугами **облачного сервиса**, который сделает большую часть работы, включая настройку HTTPS. Это может наложить дополнительные ограничения или потребовать дополнительную плату и т.п. Зато Вам не понадобится самостоятельно заниматься настройками прокси-сервера.
|
||||
|
||||
В дальнейшем я покажу Вам некоторые конкретные примеры их применения.
|
||||
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
Термином **программа** обычно описывают множество вещей:
|
||||
|
||||
* **Код**, который Вы написали, в нашем случае **Python-файлы**.
|
||||
* **Код**, который вы написали, в нашем случае **Python-файлы**.
|
||||
* **Файл**, который может быть **исполнен** операционной системой, например `python`, `python.exe` или `uvicorn`.
|
||||
* Конкретная программа, **запущенная** операционной системой и использующая центральный процессор и память. В таком случае это также называется **процесс**.
|
||||
|
||||
|
|
@ -74,13 +74,13 @@
|
|||
* Конкретная программа, **запущенная** операционной системой.
|
||||
* Это не имеет отношения к какому-либо файлу или коду, но нечто **определённое**, управляемое и **выполняемое** операционной системой.
|
||||
* Любая программа, любой код, **могут делать что-то** только когда они **выполняются**. То есть, когда являются **работающим процессом**.
|
||||
* Процесс может быть **прерван** (или "убит") Вами или Вашей операционной системой. В результате чего он перестанет исполняться и **не будет продолжать делать что-либо**.
|
||||
* Каждое приложение, которое Вы запустили на своём компьютере, каждая программа, каждое "окно" запускает какой-то процесс. И обычно на включенном компьютере **одновременно** запущено множество процессов.
|
||||
* Процесс может быть **прерван** (или "убит") Вами или вашей операционной системой. В результате чего он перестанет исполняться и **не будет продолжать делать что-либо**.
|
||||
* Каждое приложение, которое вы запустили на своём компьютере, каждая программа, каждое "окно" запускает какой-то процесс. И обычно на включенном компьютере **одновременно** запущено множество процессов.
|
||||
* И **одна программа** может запустить **несколько параллельных процессов**.
|
||||
|
||||
Если Вы заглянете в "диспетчер задач" или "системный монитор" (или аналогичные инструменты) Вашей операционной системы, то увидите множество работающих процессов.
|
||||
Если вы заглянете в "диспетчер задач" или "системный монитор" (или аналогичные инструменты) вашей операционной системы, то увидите множество работающих процессов.
|
||||
|
||||
Вполне вероятно, что Вы увидите несколько процессов с одним и тем же названием браузерной программы (Firefox, Chrome, Edge и т. Д.). Обычно браузеры запускают один процесс на вкладку и вдобавок некоторые дополнительные процессы.
|
||||
Вполне вероятно, что вы увидите несколько процессов с одним и тем же названием браузерной программы (Firefox, Chrome, Edge и т. Д.). Обычно браузеры запускают один процесс на вкладку и вдобавок некоторые дополнительные процессы.
|
||||
|
||||
<img class="shadow" src="/img/deployment/concepts/image01.png">
|
||||
|
||||
|
|
@ -90,21 +90,21 @@
|
|||
|
||||
## Настройки запуска приложения
|
||||
|
||||
В большинстве случаев когда Вы создаёте веб-приложение, то желаете, чтоб оно **работало постоянно** и непрерывно, предоставляя клиентам доступ в любое время. Хотя иногда у Вас могут быть причины, чтоб оно запускалось только при определённых условиях.
|
||||
В большинстве случаев когда вы создаёте веб-приложение, то желаете, чтоб оно **работало постоянно** и непрерывно, предоставляя клиентам доступ в любое время. Хотя иногда у вас могут быть причины, чтоб оно запускалось только при определённых условиях.
|
||||
|
||||
### Удалённый сервер
|
||||
|
||||
Когда Вы настраиваете удалённый сервер (облачный сервер, виртуальную машину и т.п.), самое простое, что можно сделать, запустить Uvicorn (или его аналог) вручную, как Вы делаете при локальной разработке.
|
||||
Когда вы настраиваете удалённый сервер (облачный сервер, виртуальную машину и т.п.), самое простое, что можно сделать, запустить Uvicorn (или его аналог) вручную, как вы делаете при локальной разработке.
|
||||
|
||||
Это рабочий способ и он полезен **во время разработки**.
|
||||
|
||||
Но если Вы потеряете соединение с сервером, то не сможете отслеживать - работает ли всё ещё **запущенный Вами процесс**.
|
||||
Но если вы потеряете соединение с сервером, то не сможете отслеживать - работает ли всё ещё **запущенный Вами процесс**.
|
||||
|
||||
И если сервер перезагрузится (например, после обновления или каких-то действий облачного провайдера), Вы скорее всего **этого не заметите**, чтобы снова запустить процесс вручную. Вследствие этого Ваш API останется мёртвым. 😱
|
||||
И если сервер перезагрузится (например, после обновления или каких-то действий облачного провайдера), вы скорее всего **этого не заметите**, чтобы снова запустить процесс вручную. Вследствие этого Ваш API останется мёртвым. 😱
|
||||
|
||||
### Автоматический запуск программ
|
||||
|
||||
Вероятно Вы пожелаете, чтоб Ваша серверная программа (такая как Uvicorn) стартовала автоматически при включении сервера, без **человеческого вмешательства** и всегда могла управлять Вашим API (так как Uvicorn запускает приложение FastAPI).
|
||||
Вероятно вы захотите, чтоб Ваша серверная программа (такая, как Uvicorn) стартовала автоматически при включении сервера, без **человеческого вмешательства** и всегда могла управлять Вашим API (так как Uvicorn запускает приложение FastAPI).
|
||||
|
||||
### Отдельная программа
|
||||
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
|
||||
## Перезапуск
|
||||
|
||||
Вы, вероятно, также пожелаете, чтоб Ваше приложение **перезапускалось**, если в нём произошёл сбой.
|
||||
Вы, вероятно, также захотите, чтоб ваше приложение **перезапускалось**, если в нём произошёл сбой.
|
||||
|
||||
### Мы ошибаемся
|
||||
|
||||
|
|
@ -137,7 +137,7 @@
|
|||
|
||||
### Небольшие ошибки обрабатываются автоматически
|
||||
|
||||
Когда Вы создаёте свои API на основе FastAPI и допускаете в коде ошибку, то FastAPI обычно остановит её распространение внутри одного запроса, при обработке которого она возникла. 🛡
|
||||
Когда вы создаёте свои API на основе FastAPI и допускаете в коде ошибку, то FastAPI обычно остановит её распространение внутри одного запроса, при обработке которого она возникла. 🛡
|
||||
|
||||
Клиент получит ошибку **500 Internal Server Error** в ответ на свой запрос, но приложение не сломается и будет продолжать работать с последующими запросами.
|
||||
|
||||
|
|
@ -152,11 +152,11 @@
|
|||
Для случаев, когда ошибки приводят к сбою в запущенном **процессе**, Вам понадобится добавить компонент, который **перезапустит** процесс хотя бы пару раз...
|
||||
|
||||
!!! tip "Заметка"
|
||||
... Если приложение падает сразу же после запуска, вероятно бесполезно его бесконечно перезапускать. Но полагаю, Вы заметите такое поведение во время разработки или, по крайней мере, сразу после развёртывания.
|
||||
... Если приложение падает сразу же после запуска, вероятно бесполезно его бесконечно перезапускать. Но полагаю, вы заметите такое поведение во время разработки или, по крайней мере, сразу после развёртывания.
|
||||
|
||||
Так что давайте сосредоточимся на конкретных случаях, когда приложение может полностью выйти из строя, но всё ещё есть смысл его запустить заново.
|
||||
|
||||
Возможно Вы захотите, чтоб был некий **внешний компонент**, ответственный за перезапуск Вашего приложения даже если уже не работает Uvicorn или Python. То есть ничего из того, что написано в Вашем коде внутри приложения, не может быть выполнено в принципе.
|
||||
Возможно вы захотите, чтоб был некий **внешний компонент**, ответственный за перезапуск вашего приложения даже если уже не работает Uvicorn или Python. То есть ничего из того, что написано в вашем коде внутри приложения, не может быть выполнено в принципе.
|
||||
|
||||
### Примеры инструментов для автоматического перезапуска
|
||||
|
||||
|
|
@ -181,7 +181,7 @@
|
|||
|
||||
### Множество процессов - Воркеры (Workers)
|
||||
|
||||
Если количество Ваших клиентов больше, чем может обслужить один процесс (допустим, что виртуальная машина не слишком мощная), но при этом Вам доступно **несколько ядер процессора**, то Вы можете запустить **несколько процессов** одного и того же приложения параллельно и распределить запросы между этими процессами.
|
||||
Если количество Ваших клиентов больше, чем может обслужить один процесс (допустим, что виртуальная машина не слишком мощная), но при этом Вам доступно **несколько ядер процессора**, то вы можете запустить **несколько процессов** одного и того же приложения параллельно и распределить запросы между этими процессами.
|
||||
|
||||
**Несколько запущенных процессов** одной и той же API-программы часто называют **воркерами**.
|
||||
|
||||
|
|
@ -197,11 +197,11 @@
|
|||
|
||||
Работающая программа загружает в память данные, необходимые для её работы, например, переменные содержащие модели машинного обучения или большие файлы. Каждая переменная **потребляет некоторое количество оперативной памяти (RAM)** сервера.
|
||||
|
||||
Обычно процессы **не делятся памятью друг с другом**. Сие означает, что каждый работающий процесс имеет свои данные, переменные и свой кусок памяти. И если для выполнения Вашего кода процессу нужно много памяти, то **каждый такой же процесс** запущенный дополнительно, потребует такого же количества памяти.
|
||||
Обычно процессы **не делятся памятью друг с другом**. Сие означает, что каждый работающий процесс имеет свои данные, переменные и свой кусок памяти. И если для выполнения вашего кода процессу нужно много памяти, то **каждый такой же процесс** запущенный дополнительно, потребует такого же количества памяти.
|
||||
|
||||
### Память сервера
|
||||
|
||||
Допустим, что Ваш код загружает модель машинного обучения **размером 1 ГБ**. Когда Вы запустите своё API как один процесс, он займёт в оперативной памяти не менее 1 ГБ. А если Вы запустите **4 таких же процесса** (4 воркера), то каждый из них займёт 1 ГБ оперативной памяти. В результате Вашему API потребуется **4 ГБ оперативной памяти (RAM)**.
|
||||
Допустим, что Ваш код загружает модель машинного обучения **размером 1 ГБ**. Когда вы запустите своё API как один процесс, он займёт в оперативной памяти не менее 1 ГБ. А если вы запустите **4 таких же процесса** (4 воркера), то каждый из них займёт 1 ГБ оперативной памяти. В результате вашему API потребуется **4 ГБ оперативной памяти (RAM)**.
|
||||
|
||||
И если Ваш удалённый сервер или виртуальная машина располагает только 3 ГБ памяти, то попытка загрузить в неё 4 ГБ данных вызовет проблемы. 🚨
|
||||
|
||||
|
|
@ -211,15 +211,15 @@
|
|||
|
||||
Менеджер процессов будет слушать определённый **сокет** (IP:порт) и передавать данные работающим процессам.
|
||||
|
||||
Каждый из этих процессов будет запускать Ваше приложение для обработки полученного **запроса** и возвращения вычисленного **ответа** и они будут использовать оперативную память.
|
||||
Каждый из этих процессов будет запускать ваше приложение для обработки полученного **запроса** и возвращения вычисленного **ответа** и они будут использовать оперативную память.
|
||||
|
||||
<img src="/img/deployment/concepts/process-ram.svg">
|
||||
|
||||
Безусловно, на этом же сервере будут работать и **другие процессы**, которые не относятся к Вашему приложению.
|
||||
Безусловно, на этом же сервере будут работать и **другие процессы**, которые не относятся к вашему приложению.
|
||||
|
||||
Интересная деталь - обычно в течение времени процент **использования центрального процессора (CPU)** каждым процессом может очень сильно **изменяться**, но объём занимаемой **оперативной памяти (RAM)** остаётся относительно **стабильным**.
|
||||
Интересная деталь заключается в том, что процент **использования центрального процессора (CPU)** каждым процессом может сильно меняться с течением времени, но объём занимаемой **оперативной памяти (RAM)** остаётся относительно **стабильным**.
|
||||
|
||||
Если у Вас есть API, который каждый раз выполняет сопоставимый объем вычислений, и у Вас много клиентов, то **загрузка процессора**, вероятно, *также будет стабильной* (вместо того, чтобы постоянно быстро увеличиваться и уменьшаться).
|
||||
Если у вас есть API, который каждый раз выполняет сопоставимый объем вычислений, и у вас много клиентов, то **загрузка процессора**, вероятно, *также будет стабильной* (вместо того, чтобы постоянно быстро увеличиваться и уменьшаться).
|
||||
|
||||
### Примеры стратегий и инструментов для запуска нескольких экземпляров приложения
|
||||
|
||||
|
|
@ -236,10 +236,10 @@
|
|||
* **Kubernetes** и аналогичные **контейнерные системы**
|
||||
* Какой-то компонент в **Kubernetes** будет слушать **IP:port**. Необходимое количество запущенных экземпляров приложения будет осуществляться посредством запуска **нескольких контейнеров**, в каждом из которых работает **один процесс Uvicorn**.
|
||||
* **Облачные сервисы**, которые позаботятся обо всём за Вас
|
||||
* Возможно, что облачный сервис умеет **управлять запуском дополнительных экземпляров приложения**. Вероятно, он потребует, чтоб Вы указали - какой **процесс** или **образ** следует клонировать. Скорее всего, Вы укажете **один процесс Uvicorn** и облачный сервис будет запускать его копии при необходимости.
|
||||
* Возможно, что облачный сервис умеет **управлять запуском дополнительных экземпляров приложения**. Вероятно, он потребует, чтоб вы указали - какой **процесс** или **образ** следует клонировать. Скорее всего, вы укажете **один процесс Uvicorn** и облачный сервис будет запускать его копии при необходимости.
|
||||
|
||||
!!! tip "Заметка"
|
||||
Если Вы не знаете, что такое **контейнеры**, Docker или Kubernetes, не переживайте.
|
||||
Если вы не знаете, что такое **контейнеры**, Docker или Kubernetes, не переживайте.
|
||||
|
||||
Я поведаю Вам о контейнерах, образах, Docker, Kubernetes и т.п. в главе: [FastAPI внутри контейнеров - Docker](./docker.md){.internal-link target=_blank}.
|
||||
|
||||
|
|
@ -253,18 +253,18 @@
|
|||
|
||||
Поэтому Вам нужен будет **один процесс**, выполняющий эти **подготовительные шаги** до запуска приложения.
|
||||
|
||||
Также Вам нужно будет убедиться, что этот процесс выполнил подготовительные шаги *даже* если впоследствии Вы запустите **несколько процессов** (несколько воркеров) самого приложения. Если бы эти шаги выполнялись в каждом **клонированном процессе**, они бы **дублировали** работу, пытаясь выполнить её **параллельно**. И если бы эта работа была бы чем-то деликатным, вроде миграции базы данных, то это может вызвать конфликты между ними.
|
||||
Также Вам нужно будет убедиться, что этот процесс выполнил подготовительные шаги *даже* если впоследствии вы запустите **несколько процессов** (несколько воркеров) самого приложения. Если бы эти шаги выполнялись в каждом **клонированном процессе**, они бы **дублировали** работу, пытаясь выполнить её **параллельно**. И если бы эта работа была бы чем-то деликатным, вроде миграции базы данных, то это может вызвать конфликты между ними.
|
||||
|
||||
Безусловно, возможны случаи, когда нет проблем при выполнении предварительной подготовки параллельно или несколько раз. Тогда Вам повезло, работать с ними намного проще.
|
||||
|
||||
!!! tip "Заметка"
|
||||
Имейте в виду, что в некоторых случаях запуск Вашего приложения **может не требовать каких-либо предварительных шагов вовсе**.
|
||||
Имейте в виду, что в некоторых случаях запуск вашего приложения **может не требовать каких-либо предварительных шагов вовсе**.
|
||||
|
||||
Что ж, тогда Вам не нужно беспокоиться об этом. 🤷
|
||||
|
||||
### Примеры стратегий запуска предварительных шагов
|
||||
|
||||
Существует **сильная зависимость** от того, как Вы **развёртываете свою систему**, запускаете программы, обрабатываете перезапуски и т.д.
|
||||
Существует **сильная зависимость** от того, как вы **развёртываете свою систему**, запускаете программы, обрабатываете перезапуски и т.д.
|
||||
|
||||
Вот некоторые возможные идеи:
|
||||
|
||||
|
|
@ -279,19 +279,19 @@
|
|||
|
||||
Ваш сервер располагает ресурсами, которые Ваши программы могут потреблять или **утилизировать**, а именно - время работы центрального процессора и объём оперативной памяти.
|
||||
|
||||
Как много системных ресурсов Вы предполагаете потребить/утилизировать? Если не задумываться, то можно ответить - "немного", но на самом деле Вы, вероятно, пожелаете использовать **максимально возможное количество**.
|
||||
Как много системных ресурсов вы предполагаете потребить/утилизировать? Если не задумываться, то можно ответить - "немного", но на самом деле Вы, вероятно, захотите использовать **максимально возможное количество**.
|
||||
|
||||
Если Вы платите за содержание трёх серверов, но используете лишь малую часть системных ресурсов каждого из них, то Вы **выбрасываете деньги на ветер**, а также **впустую тратите электроэнергию** и т.п.
|
||||
Если вы платите за содержание трёх серверов, но используете лишь малую часть системных ресурсов каждого из них, то вы **выбрасываете деньги на ветер**, а также **впустую тратите электроэнергию** и т.п.
|
||||
|
||||
В таком случае было бы лучше обойтись двумя серверами, но более полно утилизировать их ресурсы (центральный процессор, оперативную память, жёсткий диск, сети передачи данных и т.д).
|
||||
|
||||
С другой стороны, если Вы располагаете только двумя серверами и используете **на 100% их процессоры и память**, но какой-либо процесс запросит дополнительную память, то операционная система сервера будет использовать жёсткий диск для расширения оперативной памяти (а диск работает в тысячи раз медленнее), а то вовсе **упадёт**. Или если какому-то процессу понадобится произвести вычисления, то ему придётся подождать, пока процессор освободится.
|
||||
С другой стороны, если вы располагаете только двумя серверами и используете **на 100% их процессоры и память**, но какой-либо процесс запросит дополнительную память, то операционная система сервера будет использовать жёсткий диск для расширения оперативной памяти (а диск работает в тысячи раз медленнее), а то вовсе **упадёт**. Или если какому-то процессу понадобится произвести вычисления, то ему придётся подождать, пока процессор освободится.
|
||||
|
||||
В такой ситуации лучше подключить **ещё один сервер** и перераспределить процессы между серверами, чтоб всем **хватало памяти и процессорного времени**.
|
||||
|
||||
Также есть вероятность, что по какой-то причине возник **всплеск** запросов к Вашему API. Возможно, это был вирус, боты или другие сервисы начали пользоваться им. И для таких происшествий Вы можете захотеть иметь дополнительные ресурсы.
|
||||
Также есть вероятность, что по какой-то причине возник **всплеск** запросов к вашему API. Возможно, это был вирус, боты или другие сервисы начали пользоваться им. И для таких происшествий вы можете захотеть иметь дополнительные ресурсы.
|
||||
|
||||
При настройке логики развёртываний, Вы можете указать **целевое значение** утилизации ресурсов, допустим, **от 50% до 90%**. Обычно эти метрики и используют.
|
||||
При настройке логики развёртываний, вы можете указать **целевое значение** утилизации ресурсов, допустим, **от 50% до 90%**. Обычно эти метрики и используют.
|
||||
|
||||
Вы можете использовать простые инструменты, такие как `htop`, для отслеживания загрузки центрального процессора и оперативной памяти сервера, в том числе каждым процессом. Или более сложные системы мониторинга нескольких серверов.
|
||||
|
||||
|
|
@ -308,4 +308,4 @@
|
|||
|
||||
Осознание этих идей и того, как их применять, должно дать Вам интуитивное понимание, необходимое для принятия решений при настройке развертываний. 🤓
|
||||
|
||||
В следующих разделах я приведу более конкретные примеры возможных стратегий, которым Вы можете следовать. 🚀
|
||||
В следующих разделах я приведу более конкретные примеры возможных стратегий, которым вы можете следовать. 🚀
|
||||
|
|
|
|||
|
|
@ -70,19 +70,19 @@ Docker является одним оз основных инструменто
|
|||
|
||||
и т.п.
|
||||
|
||||
Использование подготовленных образов значительно упрощает **комбинирование** и использование разных инструментов. Например, Вы можете попытаться использовать новую базу данных. В большинстве случаев можно использовать **официальный образ** и всего лишь указать переменные окружения.
|
||||
Использование подготовленных образов значительно упрощает **комбинирование** и использование разных инструментов. Например, вы можете попытаться использовать новую базу данных. В большинстве случаев можно использовать **официальный образ** и всего лишь указать переменные окружения.
|
||||
|
||||
Таким образом, Вы можете изучить, что такое контейнеризация и Docker, и использовать полученные знания с разными инструментами и компонентами.
|
||||
Таким образом, вы можете изучить, что такое контейнеризация и Docker, и использовать полученные знания с разными инструментами и компонентами.
|
||||
|
||||
Так, Вы можете запустить одновременно **множество контейнеров** с базой данных, Python-приложением, веб-сервером, React-приложением и соединить их вместе через внутреннюю сеть.
|
||||
Так, вы можете запустить одновременно **множество контейнеров** с базой данных, Python-приложением, веб-сервером, React-приложением и соединить их вместе через внутреннюю сеть.
|
||||
|
||||
Все системы управления контейнерами (такие, как Docker или Kubernetes) имеют встроенные возможности для организации такого сетевого взаимодействия.
|
||||
|
||||
## Контейнеры и процессы
|
||||
|
||||
Обычно **образ контейнера** содержит метаданные предустановленной программы или команду, которую следует выполнить при запуске **контейнера**. Также он может содержать параметры, передаваемые предустановленной программе. Похоже на то, как если бы Вы запускали такую программу через терминал.
|
||||
Обычно **образ контейнера** содержит метаданные предустановленной программы или команду, которую следует выполнить при запуске **контейнера**. Также он может содержать параметры, передаваемые предустановленной программе. Похоже на то, как если бы вы запускали такую программу через терминал.
|
||||
|
||||
Когда **контейнер** запущен, он будет выполнять прописанные в нём команды и программы. Но Вы можете изменить его так, чтоб он выполнял другие команды и программы.
|
||||
Когда **контейнер** запущен, он будет выполнять прописанные в нём команды и программы. Но вы можете изменить его так, чтоб он выполнял другие команды и программы.
|
||||
|
||||
Контейнер буде работать до тех пор, пока выполняется его **главный процесс** (команда или программа).
|
||||
|
||||
|
|
@ -100,11 +100,11 @@ Docker является одним оз основных инструменто
|
|||
|
||||
* Использование с **Kubernetes** или аналогичным инструментом
|
||||
* Запуск в **Raspberry Pi**
|
||||
* Использование в облачных сервисах, запускающих образы контейнеров для Вас и т.п.
|
||||
* Использование в облачных сервисах, запускающих образы контейнеров для вас и т.п.
|
||||
|
||||
### Установить зависимости
|
||||
|
||||
Обычно Вашему приложению необходимы **дополнительные библиотеки**, список которых находится в отдельном файле.
|
||||
Обычно вашему приложению необходимы **дополнительные библиотеки**, список которых находится в отдельном файле.
|
||||
|
||||
На название и содержание такого файла влияет выбранный Вами инструмент **установки** этих библиотек (зависимостей).
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ Successfully installed fastapi pydantic uvicorn
|
|||
!!! info "Информация"
|
||||
Существуют и другие инструменты управления зависимостями.
|
||||
|
||||
В этом же разделе, но позже, я покажу Вам пример использования Poetry. 👇
|
||||
В этом же разделе, но позже, я покажу вам пример использования Poetry. 👇
|
||||
|
||||
### Создать приложение **FastAPI**
|
||||
|
||||
|
|
@ -195,7 +195,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
Сначала копируйте **только** файл с зависимостями.
|
||||
|
||||
Этот файл **изменяется довольно редко**, Docker ищет изменения при постройке образа и если не находит, то использует **кэш**, в котором хранятся предыдущии версии сборки образа.
|
||||
Этот файл **изменяется довольно редко**, Docker ищет изменения при постройке образа и если не находит, то использует **кэш**, в котором хранятся предыдущие версии сборки образа.
|
||||
|
||||
4. Установите библиотеки перечисленные в файле с зависимостями.
|
||||
|
||||
|
|
@ -208,7 +208,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
Ка и в предыдущем шаге с копированием файла, этот шаг также будет использовать **кэш Docker** в случае отсутствия изменений.
|
||||
|
||||
Использрвание кэша, особенно на этом шаге, позволит Вам **сэкономить** кучу времени при повторной сборке образа, так как зависимости будут сохранены в кеше, а не **загружаться и устанавливаться каждый раз**.
|
||||
Использование кэша, особенно на этом шаге, позволит вам **сэкономить** кучу времени при повторной сборке образа, так как зависимости будут сохранены в кеше, а не **загружаться и устанавливаться каждый раз**.
|
||||
|
||||
5. Скопируйте директорию `./app` внутрь директории `/code` (в контейнере).
|
||||
|
||||
|
|
@ -216,11 +216,11 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
6. Укажите **команду**, запускающую сервер `uvicorn`.
|
||||
|
||||
`CMD` принимает список строк, разделённых запятыми, но при выполнении объединит их через пробел, собрав из них одну команду, которую Вы могли бы написать в терминале.
|
||||
`CMD` принимает список строк, разделённых запятыми, но при выполнении объединит их через пробел, собрав из них одну команду, которую вы могли бы написать в терминале.
|
||||
|
||||
Эта команда будет выполнена в **текущей рабочей директории**, а именно в директории `/code`, котоая указана командой `WORKDIR /code`.
|
||||
Эта команда будет выполнена в **текущей рабочей директории**, а именно в директории `/code`, которая указана в команде `WORKDIR /code`.
|
||||
|
||||
Так как команда выполняется внутрии директории `/code`, в которую мы поместили папку `./app` с приложением, то **Uvicorn** сможет найти и **импортировать** объект `app` из файла `app.main`.
|
||||
Так как команда выполняется внутри директории `/code`, в которую мы поместили папку `./app` с приложением, то **Uvicorn** сможет найти и **импортировать** объект `app` из файла `app.main`.
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Если ткнёте на кружок с плюсом, то увидите пояснения. 👆
|
||||
|
|
@ -238,7 +238,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
#### Использование прокси-сервера
|
||||
|
||||
Если Вы запускаете контейнер за прокси-сервером завершения TLS (балансирующего нагрузку), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`, которая укажет Uvicorn, что он работает позади прокси-сервера и может доверять заголовкам отправляемым им.
|
||||
Если вы запускаете контейнер за прокси-сервером завершения TLS (балансирующего нагрузку), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`, которая укажет Uvicorn, что он работает позади прокси-сервера и может доверять заголовкам отправляемым им.
|
||||
|
||||
```Dockerfile
|
||||
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
|
@ -269,7 +269,7 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
|||
|
||||
Для загрузки и установки необходимых библиотек **может понадобиться несколько минут**, но использование **кэша** занимает несколько **секунд** максимум.
|
||||
|
||||
И так как во время разработки Вы будете часто пересобирать контейнер для проверки работоспособности внесённых изменений, то сэкономленные минуты сложатся в часы, а то и дни.
|
||||
И так как во время разработки вы будете часто пересобирать контейнер для проверки работоспособности внесённых изменений, то сэкономленные минуты сложатся в часы, а то и дни.
|
||||
|
||||
Так как папка с кодом приложения **изменяется чаще всего**, то мы расположили её в конце `Dockerfile`, ведь после внесённых в код изменений кэш не будет использован на этом и следующих шагах.
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ $ docker build -t myimage .
|
|||
|
||||
### Запуск Docker-контейнера
|
||||
|
||||
* Запустите контейнер, основанный на Вашем образе:
|
||||
* Запустите контейнер, основанный на вашем образе:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -315,7 +315,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage
|
|||
|
||||
Вы можете проверить, что Ваш Docker-контейнер работает перейдя по ссылке: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> или <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (или похожей, которую использует Ваш Docker-хост).
|
||||
|
||||
Там Вы увидите:
|
||||
Там вы увидите:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
|
|
@ -325,21 +325,21 @@ $ docker run -d --name mycontainer -p 80:80 myimage
|
|||
|
||||
Теперь перейдите по ссылке <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> или <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (или похожей, которую использует Ваш Docker-хост).
|
||||
|
||||
Здесь Вы увидите автоматическую интерактивную документацию API (предоставляемую <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
Здесь вы увидите автоматическую интерактивную документацию API (предоставляемую <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
## Альтернативная документация API
|
||||
|
||||
Также Вы можете перейти по ссылке <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> or <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (или похожей, которую использует Ваш Docker-хост).
|
||||
Также вы можете перейти по ссылке <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> or <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (или похожей, которую использует Ваш Docker-хост).
|
||||
|
||||
Здесь Вы увидите альтернативную автоматическую документацию API (предоставляемую <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
Здесь вы увидите альтернативную автоматическую документацию API (предоставляемую <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Создание Docker-образа на основе однофайлового приложения FastAPI
|
||||
|
||||
Если Ваше приложение FastAPI помещено в один файл, например, `main.py` и структура Ваших файлов похожа на эту:
|
||||
Если ваше приложение FastAPI помещено в один файл, например, `main.py` и структура Ваших файлов похожа на эту:
|
||||
|
||||
```
|
||||
.
|
||||
|
|
@ -376,7 +376,7 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
Давайте вспомним о [Концепциях развёртывания](./concepts.md){.internal-link target=_blank} и применим их к контейнерам.
|
||||
|
||||
Контейнеры - это, в основном, инструмент упрощающий **сборку и развёртывание** приложения и они не обязыают к применению какой-то определённой **концепции развёртывания**, а значит мы можем выбирать нужную стратегию.
|
||||
Контейнеры - это, в основном, инструмент упрощающий **сборку и развёртывание** приложения и они не обязывают к применению какой-то определённой **концепции развёртывания**, а значит мы можем выбирать нужную стратегию.
|
||||
|
||||
**Хорошая новость** в том, что независимо от выбранной стратегии, мы всё равно можем покрыть все концепции развёртывания. 🎉
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
## Запуск нескольких экземпляров приложения - Указание количества процессов
|
||||
|
||||
Если у Вас есть <abbr title="Несколько серверов настроенных для совместной работы.">кластер</abbr> машин под управлением **Kubernetes**, Docker Swarm Mode, Nomad или аналогичной сложной системой оркестрации контейнеров, скорее всего, вместо использования менеджера процессов (типа Gunicorn и его воркеры) в каждом контейнере, Вы захотите **управлять количеством запущенных экземпляров приложения** на **уровне кластера**.
|
||||
Если у вас есть <abbr title="Несколько серверов настроенных для совместной работы.">кластер</abbr> машин под управлением **Kubernetes**, Docker Swarm Mode, Nomad или аналогичной сложной системой оркестрации контейнеров, скорее всего, вместо использования менеджера процессов (типа Gunicorn и его воркеры) в каждом контейнере, вы захотите **управлять количеством запущенных экземпляров приложения** на **уровне кластера**.
|
||||
|
||||
В любую из этих систем управления контейнерами обычно встроен способ управления **количеством запущенных контейнеров** для распределения **нагрузки** от входящих запросов на **уровне кластера**.
|
||||
|
||||
|
|
@ -427,17 +427,17 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
!!! tip "Подсказка"
|
||||
**Прокси-сервер завершения работы TLS** одновременно может быть **балансировщиком нагрузки**.
|
||||
|
||||
Система оркестрации, которую Вы используете для запуска и управления контейнерами, имеет встроенный инструмент **сетевого взаимодействия** (например, для передачи HTTP-запросов) между контейнерами с Вашими приложениями и **балансировщиком нагрузки** (который также может быть **прокси-сервером**).
|
||||
Система оркестрации, которую вы используете для запуска и управления контейнерами, имеет встроенный инструмент **сетевого взаимодействия** (например, для передачи HTTP-запросов) между контейнерами с Вашими приложениями и **балансировщиком нагрузки** (который также может быть **прокси-сервером**).
|
||||
|
||||
### Один балансировщик - Множество контейнеров
|
||||
|
||||
При работе с **Kubernetes** или аналогичными системами оркестрации использование их внутреннней сети позволяет иметь один **балансировщик нагрузки**, который прослушивает **главный** порт и передаёт запросы **множеству запущенных контейнеров** с Вашими приложениями.
|
||||
При работе с **Kubernetes** или аналогичными системами оркестрации использование их внутренней сети позволяет иметь один **балансировщик нагрузки**, который прослушивает **главный** порт и передаёт запросы **множеству запущенных контейнеров** с Вашими приложениями.
|
||||
|
||||
В каждом из контейнеров обычно работает **только один процесс** (например, процесс Uvicorn управляющий Вашим приложением FastAPI). Контейнеры могут быть **идентичными**, запущенными на основе одного и того же образа, но у каждого будут свои отдельные процесс, память и т.п. Таким образом мы получаем преимущества **распараллеливания** работы по **разным ядрам** процессора или даже **разным машинам**.
|
||||
|
||||
Система управления контейнерами с **балансировщиком нагрузки** будет **распределять запросы** к контейнерам с приложениями **по очереди**. То есть каждый запрос будет обработан одним из множества **одинаковых контейнеров** с одним и тем же приложением.
|
||||
|
||||
**Балансировщик нагрузки** может обрабатывать запросы к *разным* приложениям, расположенным в Вашем кластере (например, если у них разные домены или префиксы пути) и передавать запросы нужному контейнеру с требуемым приложением.
|
||||
**Балансировщик нагрузки** может обрабатывать запросы к *разным* приложениям, расположенным в вашем кластере (например, если у них разные домены или префиксы пути) и передавать запросы нужному контейнеру с требуемым приложением.
|
||||
|
||||
### Один процесс на контейнер
|
||||
|
||||
|
|
@ -449,35 +449,35 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
### <a name="special-cases"></a>Множество процессов внутри контейнера для особых случаев</a>
|
||||
|
||||
Безусловно, бывают **особые случаи**, когда может понадобится внутри контейнера запускать **менеджер процессов Gunicorn**, управляющий несколькими **процессами Uvicorn**.
|
||||
Безусловно, бывают **особые случаи**, когда может понадобиться внутри контейнера запускать **менеджер процессов Gunicorn**, управляющий несколькими **процессами Uvicorn**.
|
||||
|
||||
Для таких случаев Вы можете использовать **официальный Docker-образ** (прим. пер: - *здесь и далее на этой странице, если Вы встретите сочетание "официальный Docker-образ" без уточнений, то автор имеет в виду именно предоставляемый им образ*), где в качестве менеджера процессов используется **Gunicorn**, запускающий несколько **процессов Uvicorn** и некоторые настройки по умолчанию, автоматически устанавливающие количество запущенных процессов в зависимости от количества ядер Вашего процессора. Я расскажу Вам об этом подробнее тут: [Официальный Docker-образ со встроенными Gunicorn и Uvicorn](#docker-gunicorn-uvicorn).
|
||||
Для таких случаев вы можете использовать **официальный Docker-образ** (прим. пер: - *здесь и далее на этой странице, если вы встретите сочетание "официальный Docker-образ" без уточнений, то автор имеет в виду именно предоставляемый им образ*), где в качестве менеджера процессов используется **Gunicorn**, запускающий несколько **процессов Uvicorn** и некоторые настройки по умолчанию, автоматически устанавливающие количество запущенных процессов в зависимости от количества ядер вашего процессора. Я расскажу вам об этом подробнее тут: [Официальный Docker-образ со встроенными Gunicorn и Uvicorn](#docker-gunicorn-uvicorn).
|
||||
|
||||
Некоторые примеры подобных случаев:
|
||||
|
||||
#### Простое приложение
|
||||
|
||||
Вы можете использовать менеджер процессов внутри контейнера, если Ваше приложение **настолько простое**, что у Вас нет необходимости (по крайней мере, пока нет) в тщательных настройках количества процессов и Вам достаточно имеющихся настроек по умолчанию (если используется официальный Docker-образ) для запуска приложения **только на одном сервере**, а не в кластере.
|
||||
Вы можете использовать менеджер процессов внутри контейнера, если ваше приложение **настолько простое**, что у вас нет необходимости (по крайней мере, пока нет) в тщательных настройках количества процессов и вам достаточно имеющихся настроек по умолчанию (если используется официальный Docker-образ) для запуска приложения **только на одном сервере**, а не в кластере.
|
||||
|
||||
#### Docker Compose
|
||||
|
||||
С помощью **Docker Compose** можно разворачивать несколько контейнеров на **одном сервере** (не кластере), но при это у Вас не будет простого способа управления количеством запущенных контейнеров с одновременным сохранением общей сети и **балансировки нагрузки**.
|
||||
С помощью **Docker Compose** можно разворачивать несколько контейнеров на **одном сервере** (не кластере), но при это у вас не будет простого способа управления количеством запущенных контейнеров с одновременным сохранением общей сети и **балансировки нагрузки**.
|
||||
|
||||
В этом случае можно использовать **менеджер процессов**, управляющий **несколькими процессами**, внутри **одного контейнера**.
|
||||
|
||||
#### Prometheus и прочие причины
|
||||
|
||||
У Вас могут быть и **другие причины**, когда использование **множества процессов** внутри **одного контейнера** будет проще, нежели запуск **нескольких контейнеров** с **единственным процессом** в каждом из них.
|
||||
У вас могут быть и **другие причины**, когда использование **множества процессов** внутри **одного контейнера** будет проще, нежели запуск **нескольких контейнеров** с **единственным процессом** в каждом из них.
|
||||
|
||||
Например (в зависимости от конфигурации), у Вас могут быть инструменты подобные экспортёру Prometheus, которые должны иметь доступ к **каждому запросу** приходящему в контейнер.
|
||||
Например (в зависимости от конфигурации), у вас могут быть инструменты подобные экспортёру Prometheus, которые должны иметь доступ к **каждому запросу** приходящему в контейнер.
|
||||
|
||||
Если у Вас будет **несколько контейнеров**, то Prometheus, по умолчанию, **при сборе метрик** получит их **только с одного контейнера**, который обрабатывает конкретный запрос, вместо **сбора метрик** со всех работающих контейнеров.
|
||||
Если у вас будет **несколько контейнеров**, то Prometheus, по умолчанию, **при сборе метрик** получит их **только с одного контейнера**, который обрабатывает конкретный запрос, вместо **сбора метрик** со всех работающих контейнеров.
|
||||
|
||||
В таком случае может быть проще иметь **один контейнер** со **множеством процессов**, с нужным инструментом (таким как экспортёр Prometheus) в этом же контейнере и собирающем метрики со всех внутренних процессов этого контейнера.
|
||||
|
||||
---
|
||||
|
||||
Самое главное - **ни одно** из перечисленных правил не является **высеченным в камне** и Вы не обязаны слепо их повторять. Вы можете использовать эти идеи при **рассмотрении Вашего конкретного случая** и самостоятельно решать, какая из концепции подходит лучше:
|
||||
Самое главное - **ни одно** из перечисленных правил не является **высеченным на камне** и вы не обязаны слепо их повторять. вы можете использовать эти идеи при **рассмотрении вашего конкретного случая** и самостоятельно решать, какая из концепции подходит лучше:
|
||||
|
||||
* Использование более безопасного протокола HTTPS
|
||||
* Настройки запуска приложения
|
||||
|
|
@ -488,41 +488,41 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
## Управление памятью
|
||||
|
||||
При **запуске одного процесса на контейнер** Вы получаете относительно понятный, стабильный и ограниченный объём памяти, потребляемый одним контейнером.
|
||||
При **запуске одного процесса на контейнер** вы получаете относительно понятный, стабильный и ограниченный объём памяти, потребляемый одним контейнером.
|
||||
|
||||
Вы можете установить аналогичные ограничения по памяти при конфигурировании своей системы управления контейнерами (например, **Kubernetes**). Таким образом система сможет **изменять количество контейнеров** на **доступных ей машинах** приводя в соответствие количество памяти нужной контейнерам с количеством памяти доступной в кластере (наборе доступных машин).
|
||||
|
||||
Если у Вас **простенькое** приложение, вероятно у Вас не будет **необходимости** устанавливать жёсткие ограничения на выделяемую ему память. Но если приложение **использует много памяти** (например, оно использует модели **машинного обучения**), Вам следует проверить, как много памяти ему требуется и отрегулировать **количество контейнеров** запущенных на **каждой машине** (может быть даже добавить машин в кластер).
|
||||
Если у вас **простенькое** приложение, вероятно у вас не будет **необходимости** устанавливать жёсткие ограничения на выделяемую ему память. Но если приложение **использует много памяти** (например, оно использует модели **машинного обучения**), вам следует проверить, как много памяти ему требуется и отрегулировать **количество контейнеров** запущенных на **каждой машине** (может быть даже добавить машин в кластер).
|
||||
|
||||
Если Вы запускаете **несколько процессов в контейнере**, то должны быть уверены, что эти процессы не **займут памяти больше**, чем доступно для контейнера.
|
||||
Если вы запускаете **несколько процессов в контейнере**, то должны быть уверены, что эти процессы не **займут памяти больше**, чем доступно для контейнера.
|
||||
|
||||
## Подготовительные шаги при запуске контейнеров
|
||||
|
||||
Есть два основных подхода, которые Вы можете использовать при запуске контейнеров (Docker, Kubernetes и т.п.).
|
||||
Есть два основных подхода, которые вы можете использовать при запуске контейнеров (Docker, Kubernetes и т.п.).
|
||||
|
||||
### Множество контейнеров
|
||||
|
||||
Когда Вы запускаете **множество контейнеров**, в каждом из которых работает **только один процесс** (например, в кластере **Kubernetes**), может возникнуть необходимость иметь **отдельный контейнер**, который осуществит **предварительные шаги перед запуском** остальных контейнеров (например, применяет миграции к базе данных).
|
||||
Когда вы запускаете **множество контейнеров**, в каждом из которых работает **только один процесс** (например, в кластере **Kubernetes**), может возникнуть необходимость иметь **отдельный контейнер**, который осуществит **предварительные шаги перед запуском** остальных контейнеров (например, применяет миграции к базе данных).
|
||||
|
||||
!!! info "Информация"
|
||||
При использовании Kubernetes, это может быть <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Инициализирующий контейнер</a>.
|
||||
|
||||
При отсутствии такой необходимости (допустим, не нужно применять миграции к базе данных, а только проверить, что она готова принимать соединения), Вы можете проводить такую проверку в каждом контейнере перед запуском его основного процесса и запускать все контейнеры **одновременно**.
|
||||
При отсутствии такой необходимости (допустим, не нужно применять миграции к базе данных, а только проверить, что она готова принимать соединения), вы можете проводить такую проверку в каждом контейнере перед запуском его основного процесса и запускать все контейнеры **одновременно**.
|
||||
|
||||
### Только один контейнер
|
||||
|
||||
Если у Вас несложное приложение для работы которого достаточно **одного контейнера**, но в котором работает **несколько процессов** (или один процесс), то прохождение предварительных шагов можно осуществить в этом же контейнере до запуска основного процесса. Официальный Docker-образ поддерживает такие действия.
|
||||
Если у вас несложное приложение для работы которого достаточно **одного контейнера**, но в котором работает **несколько процессов** (или один процесс), то прохождение предварительных шагов можно осуществить в этом же контейнере до запуска основного процесса. Официальный Docker-образ поддерживает такие действия.
|
||||
|
||||
## Официальный Docker-образ с Gunicorn и Uvicorn
|
||||
|
||||
Я подготовил для Вас Docker-образ, в который включён Gunicorn управляющий процессами (воркерами) Uvicorn, в соответствии с концепциями рассмотренными в предыдущей главе: [Рабочие процессы сервера (воркеры) - Gunicorn совместно с Uvicorn](./server-workers.md){.internal-link target=_blank}.
|
||||
Я подготовил для вас Docker-образ, в который включён Gunicorn управляющий процессами (воркерами) Uvicorn, в соответствии с концепциями рассмотренными в предыдущей главе: [Рабочие процессы сервера (воркеры) - Gunicorn совместно с Uvicorn](./server-workers.md){.internal-link target=_blank}.
|
||||
|
||||
Этот образ может быть полезен для ситуаций описанных тут: [Множество процессов внутри контейнера для особых случаев](#special-cases).
|
||||
|
||||
* <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
!!! warning "Предупреждение"
|
||||
Скорее всего у Вас **нет необходимости** в использовании этого образа или подобного ему и лучше создать свой образ с нуля как описано тут: [Создать Docker-образ для FastAPI](#docker-fastapi).
|
||||
Скорее всего у вас **нет необходимости** в использовании этого образа или подобного ему и лучше создать свой образ с нуля как описано тут: [Создать Docker-образ для FastAPI](#docker-fastapi).
|
||||
|
||||
В этом образе есть **автоматический** механизм подстройки для запуска **необходимого количества процессов** в соответствии с доступным количеством ядер процессора.
|
||||
|
||||
|
|
@ -539,11 +539,11 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
Это означает, что он будет пытаться **выжать** из процессора как можно больше **производительности**.
|
||||
|
||||
Но Вы можете изменять и обновлять конфигурацию с помощью **переменных окружения** и т.п.
|
||||
Но вы можете изменять и обновлять конфигурацию с помощью **переменных окружения** и т.п.
|
||||
|
||||
Поскольку количество процессов зависит от процессора, на котором работает контейнер, **объём потребляемой памяти** также будет зависеть от этого.
|
||||
|
||||
А значит, если Вашему приложению требуется много оперативной памяти (например, оно использует модели машинного обучения) и Ваш сервер имеет центральный процессор с большим количеством ядер, но **не слишком большим объёмом оперативной памяти**, то может дойти до того, что контейнер попытается занять памяти больше, чем доступно, из-за чего будет падение производительности (или сервер вовсе упадёт). 🚨
|
||||
А значит, если вашему приложению требуется много оперативной памяти (например, оно использует модели машинного обучения) и Ваш сервер имеет центральный процессор с большим количеством ядер, но **не слишком большим объёмом оперативной памяти**, то может дойти до того, что контейнер попытается занять памяти больше, чем доступно, из-за чего будет падение производительности (или сервер вовсе упадёт). 🚨
|
||||
|
||||
|
||||
### Написание `Dockerfile`
|
||||
|
|
@ -562,7 +562,7 @@ COPY ./app /app
|
|||
|
||||
### Большие приложения
|
||||
|
||||
Если Вы успели ознакомиться с разделом [Приложения содержащие много файлов](../tutorial/bigger-applications.md){.internal-link target=_blank}, состоящие из множества файлов, Ваш Dockerfile может выглядеть так:
|
||||
Если вы успели ознакомиться с разделом [Приложения содержащие много файлов](../tutorial/bigger-applications.md){.internal-link target=_blank}, состоящие из множества файлов, Ваш Dockerfile может выглядеть так:
|
||||
|
||||
```Dockerfile hl_lines="7"
|
||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
|
||||
|
|
@ -576,9 +576,9 @@ COPY ./app /app/app
|
|||
|
||||
### Как им пользоваться
|
||||
|
||||
Если Вы используете **Kubernetes** (или что-то вроде того), скорее всего Вам **не нужно** использовать официальный Docker-образ (или другой похожий) в качестве основы, так как управление **количеством запущенных контейнеров** должно быть настроено на уровне кластера. В таком случае лучше **создать образ с нуля**, как описано в разделе Создать [Docker-образ для FastAPI](#docker-fastapi).
|
||||
Если вы используете **Kubernetes** (или что-то вроде того), скорее всего вам **не нужно** использовать официальный Docker-образ (или другой похожий) в качестве основы, так как управление **количеством запущенных контейнеров** должно быть настроено на уровне кластера. В таком случае лучше **создать образ с нуля**, как описано в разделе Создать [Docker-образ для FastAPI](#docker-fastapi).
|
||||
|
||||
Официальный образ может быть полезен в отдельных случаях, описанных выше в разделе [Множество процессов внутри контейнера для особых случаев](#special-cases). Например, если Ваше приложение **достаточно простое**, не требует запуска в кластере и способно уместиться в один контейнер, то его настройки по умолчанию будут работать довольно хорошо. Или же Вы развертываете его с помощью **Docker Compose**, работаете на одном сервере и т. д
|
||||
Официальный образ может быть полезен в отдельных случаях, описанных выше в разделе [Множество процессов внутри контейнера для особых случаев](#special-cases). Например, если ваше приложение **достаточно простое**, не требует запуска в кластере и способно уместиться в один контейнер, то его настройки по умолчанию будут работать довольно хорошо. Или же вы развертываете его с помощью **Docker Compose**, работаете на одном сервере и т. д
|
||||
|
||||
## Развёртывание образа контейнера
|
||||
|
||||
|
|
@ -590,11 +590,11 @@ COPY ./app /app/app
|
|||
* С использованием **Kubernetes** в кластере
|
||||
* С использованием режима Docker Swarm в кластере
|
||||
* С использованием других инструментов, таких как Nomad
|
||||
* С использованием облачного сервиса, который будет управлять разворачиванием Вашего контейнера
|
||||
* С использованием облачного сервиса, который будет управлять разворачиванием вашего контейнера
|
||||
|
||||
## Docker-образ и Poetry
|
||||
|
||||
Если Вы пользуетесь <a href="https://python-poetry.org/" class="external-link" target="_blank">Poetry</a> для управления зависимостями Вашего проекта, то можете использовать многоэтапную сборку образа:
|
||||
Если вы пользуетесь <a href="https://python-poetry.org/" class="external-link" target="_blank">Poetry</a> для управления зависимостями вашего проекта, то можете использовать многоэтапную сборку образа:
|
||||
|
||||
```{ .dockerfile .annotate }
|
||||
# (1)
|
||||
|
|
@ -664,19 +664,19 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
**Этапы сборки Docker-образа** являются частью `Dockerfile` и работают как **временные образы контейнеров**. Они нужны только для создания файлов, используемых в дальнейших этапах.
|
||||
|
||||
Первый этап был нужен только для **установки Poetry** и **создания файла `requirements.txt`**, в которым прописаны зависимости Вашего проекта, взятые из файла `pyproject.toml`.
|
||||
Первый этап был нужен только для **установки Poetry** и **создания файла `requirements.txt`**, в которым прописаны зависимости вашего проекта, взятые из файла `pyproject.toml`.
|
||||
|
||||
На **следующем этапе** `pip` будет использовать файл `requirements.txt`.
|
||||
|
||||
В итоговом образе будет содержаться **только последний этап сборки**, предыдущие этапы будут отброшены.
|
||||
|
||||
При использовании Poetry, имеет смысл использовать **многоэтапную сборку Docker-образа**, потому что на самом деле Вам не нужен Poetry и его зависимости в окончательном образе контейнера, Вам **нужен только** сгенерированный файл `requirements.txt` для установки зависимостей Вашего проекта.
|
||||
При использовании Poetry, имеет смысл использовать **многоэтапную сборку Docker-образа**, потому что на самом деле вам не нужен Poetry и его зависимости в окончательном образе контейнера, вам **нужен только** сгенерированный файл `requirements.txt` для установки зависимостей вашего проекта.
|
||||
|
||||
А на последнем этапе, придерживаясь описанных ранее правил, создаётся итоговый образ
|
||||
|
||||
### Использование прокси-сервера завершения TLS и Poetry
|
||||
|
||||
И снова повторюсь, если используете прокси-сервер (балансировщик нагрузки), такой, как Nginx или Traefik, добавьте в команду запуска опцию `--proxy-headers`:
|
||||
И снова повторюсь, если используете прокси-сервер (балансировщик нагрузки), такой как Nginx или Traefik, добавьте в команду запуска опцию `--proxy-headers`:
|
||||
|
||||
```Dockerfile
|
||||
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
|
@ -695,6 +695,6 @@ CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port"
|
|||
|
||||
В большинстве случаев Вам, вероятно, не нужно использовать какой-либо базовый образ, **лучше создать образ контейнера с нуля** на основе официального Docker-образа Python.
|
||||
|
||||
Позаботившись о **порядке написания** инструкций в `Dockerfile`, Вы сможете использовать **кэш Docker'а**, **минимизировав время сборки**, максимально повысив свою производительность (и избежать скуки). 😎
|
||||
Позаботившись о **порядке написания** инструкций в `Dockerfile`, вы сможете использовать **кэш Docker'а**, **минимизировав время сборки**, максимально повысив свою производительность (и не заскучать). 😎
|
||||
|
||||
В некоторых особых случаях вы можете использовать официальный образ Docker для FastAPI. 🤓
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# Об HTTPS
|
||||
|
||||
Обычно представляется, что HTTPS это некая опция, которая либо "включена", либо нет.
|
||||
Обычно представляется, что HTTPS это некая опция, которая либо "включена", либо нет.
|
||||
|
||||
Но всё несколько сложнее.
|
||||
|
||||
!!! tip "Заметка"
|
||||
Если Вы торопитесь или Вам не интересно, можете перейти на следующую страницу этого пошагового руководства по размещению приложений на серверах с использованием различных технологий.
|
||||
Если вы торопитесь или вам не интересно, можете перейти на следующую страницу этого пошагового руководства по размещению приложений на серверах с использованием различных технологий.
|
||||
|
||||
Чтобы **изучить основы HTTPS** для клиента, перейдите по ссылке <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>.
|
||||
|
||||
|
|
@ -22,8 +22,8 @@
|
|||
* **TCP не знает о "доменах"**, но знает об IP-адресах.
|
||||
* Информация о **запрашиваемом домене** извлекается из запроса **на уровне HTTP**.
|
||||
* **Сертификаты HTTPS** "сертифицируют" **конкретный домен**, но проверка сертификатов и шифрование данных происходит на уровне протокола TCP, то есть **до того**, как станет известен домен-получатель данных.
|
||||
* **По умолчанию** это означает, что у Вас может быть **только один сертификат HTTPS на один IP-адрес**.
|
||||
* Не важно, насколько большой у Вас сервер и насколько маленькие приложения на нём могут быть.
|
||||
* **По умолчанию** это означает, что у вас может быть **только один сертификат HTTPS на один IP-адрес**.
|
||||
* Не важно, насколько большой у вас сервер и насколько маленькие приложения на нём могут быть.
|
||||
* Однако, у этой проблемы есть **решение**.
|
||||
* Существует **расширение** протокола **TLS** (который работает на уровне TCP, то есть до HTTP) называемое **<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Указание имени сервера">SNI</abbr></a>**.
|
||||
* Расширение SNI позволяет одному серверу (с **одним IP-адресом**) иметь **несколько сертификатов HTTPS** и обслуживать **множество HTTPS-доменов/приложений**.
|
||||
|
|
@ -35,12 +35,12 @@
|
|||
|
||||
* получение **зашифрованных HTTPS-запросов**
|
||||
* отправка **расшифрованных HTTP запросов** в соответствующее HTTP-приложение, работающее на том же сервере (в нашем случае, это приложение **FastAPI**)
|
||||
* получние **HTTP-ответа** от приложения
|
||||
* получение **HTTP-ответа** от приложения
|
||||
* **шифрование ответа** используя подходящий **сертификат HTTPS**
|
||||
* отправка зашифрованного **HTTPS-ответа клиенту**.
|
||||
Такой сервер часто называют **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Прокси-сервер завершения работы TLS</a>** или просто "прокси-сервер".
|
||||
|
||||
Вот некоторые варианты, которые Вы можете использовать в качестве такого прокси-сервера:
|
||||
Вот некоторые варианты, которые вы можете использовать в качестве такого прокси-сервера:
|
||||
|
||||
* Traefik (может обновлять сертификаты)
|
||||
* Caddy (может обновлять сертификаты)
|
||||
|
|
@ -67,11 +67,11 @@
|
|||
|
||||
### Имя домена
|
||||
|
||||
Чаще всего, всё начинается с **приобретения имени домена**. Затем нужно настроить DNS-сервер (вероятно у того же провайдера, который выдал Вам домен).
|
||||
Чаще всего, всё начинается с **приобретения имени домена**. Затем нужно настроить DNS-сервер (вероятно у того же провайдера, который выдал вам домен).
|
||||
|
||||
Далее, возможно, Вы получаете "облачный" сервер (виртуальную машину) или что-то типа этого, у которого есть <abbr title="Не изменяемый">постоянный</abbr> **публичный IP-адрес**.
|
||||
Далее, возможно, вы получаете "облачный" сервер (виртуальную машину) или что-то типа этого, у которого есть <abbr title="Не изменяемый">постоянный</abbr> **публичный IP-адрес**.
|
||||
|
||||
На DNS-сервере (серверах) Вам следует настроить соответствующую ресурсную запись ("`запись A`"), указав, что **Ваш домен** связан с публичным **IP-адресом Вашего сервера**.
|
||||
На DNS-сервере (серверах) вам следует настроить соответствующую ресурсную запись ("`запись A`"), указав, что **Ваш домен** связан с публичным **IP-адресом вашего сервера**.
|
||||
|
||||
Обычно эту запись достаточно указать один раз, при первоначальной настройке всего сервера.
|
||||
|
||||
|
|
@ -82,9 +82,9 @@
|
|||
|
||||
Теперь давайте сфокусируемся на работе с HTTPS.
|
||||
|
||||
Всё начинается с того, что браузер спрашивает у **DNS-серверов**, какой **IP-адрес связан с доменом**, для примера возьмём домен `someapp.example.com`.
|
||||
Всё начинается с того, что браузер спрашивает у **DNS-серверов**, какой **IP-адрес связан с доменом**, для примера возьмём домен `someapp.example.com`.
|
||||
|
||||
DNS-сервера присылают браузеру определённый **IP-адрес**, тот самый публичный IP-адрес Вашего сервера, который Вы указали в ресурсной "записи А" при настройке.
|
||||
DNS-сервера присылают браузеру определённый **IP-адрес**, тот самый публичный IP-адрес вашего сервера, который вы указали в ресурсной "записи А" при настройке.
|
||||
|
||||
<img src="/img/deployment/https/https01.svg">
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ DNS-сервера присылают браузеру определённый
|
|||
|
||||
<img src="/img/deployment/https/https02.svg">
|
||||
|
||||
Эта часть клиент-серверного взаимодействия устанавливает TLS-соединение и называется **TLS-рукопожатием**.
|
||||
Эта часть клиент-серверного взаимодействия устанавливает TLS-соединение и называется **TLS-рукопожатием**.
|
||||
|
||||
### TLS с расширением SNI
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ DNS-сервера присылают браузеру определённый
|
|||
* **Запуск в качестве программы-сервера** (как минимум, на время обновления сертификатов) на публичном IP-адресе домена.
|
||||
* Как уже не раз упоминалось, только один процесс может прослушивать определённый порт определённого IP-адреса.
|
||||
* Это одна из причин использования прокси-сервера ещё и в качестве программы обновления сертификатов.
|
||||
* В случае, если обновлением сертификатов занимается другая программа, Вам понадобится остановить прокси-сервер, запустить программу обновления сертификатов на сокете, предназначенном для прокси-сервера, настроить прокси-сервер на работу с новыми сертификатами и перезапустить его. Эта схема далека от идеальной, так как Ваши приложения будут недоступны на время отключения прокси-сервера.
|
||||
* В случае, если обновлением сертификатов занимается другая программа, вам понадобится остановить прокси-сервер, запустить программу обновления сертификатов на сокете, предназначенном для прокси-сервера, настроить прокси-сервер на работу с новыми сертификатами и перезапустить его. Эта схема далека от идеальной, так как Ваши приложения будут недоступны на время отключения прокси-сервера.
|
||||
|
||||
Весь этот процесс обновления, одновременный с обслуживанием запросов, является одной из основных причин, по которой желательно иметь **отдельную систему для работы с HTTPS** в виде прокси-сервера завершения TLS, а не просто использовать сертификаты TLS непосредственно с сервером приложений (например, Uvicorn).
|
||||
|
||||
|
|
@ -193,6 +193,6 @@ DNS-сервера присылают браузеру определённый
|
|||
|
||||
Наличие **HTTPS** очень важно и довольно **критично** в большинстве случаев. Однако, Вам, как разработчику, не нужно тратить много сил на это, достаточно **понимать эти концепции** и принципы их работы.
|
||||
|
||||
Но узнав базовые основы **HTTPS** Вы можете легко совмещать разные инструменты, которые помогут Вам в дальнейшей разработке.
|
||||
Но узнав базовые основы **HTTPS** вы можете легко совмещать разные инструменты, которые помогут вам в дальнейшей разработке.
|
||||
|
||||
В следующих главах я покажу Вам несколько примеров, как настраивать **HTTPS** для приложений **FastAPI**. 🔒
|
||||
В следующих главах я покажу вам несколько примеров, как настраивать **HTTPS** для приложений **FastAPI**. 🔒
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
Обычно **веб-приложения** размещают на удалённом компьютере с серверной программой, которая обеспечивает хорошую производительность, стабильность и т. д., Чтобы ваши пользователи могли эффективно, беспрерывно и беспроблемно обращаться к приложению.
|
||||
|
||||
Это отличется от **разработки**, когда вы постоянно меняете код, делаете в нём намеренные ошибки и исправляете их, останавливаете и перезапускаете сервер разработки и т. д.
|
||||
Это отличается от **разработки**, когда вы постоянно меняете код, делаете в нём намеренные ошибки и исправляете их, останавливаете и перезапускаете сервер разработки и т. д.
|
||||
|
||||
## Стратегии развёртывания
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Запуск сервера вручную - Uvicorn
|
||||
|
||||
Для запуска приложения **FastAPI** на удалённой серверной машине Вам необходим программный сервер, поддерживающий протокол ASGI, такой как **Uvicorn**.
|
||||
Для запуска приложения **FastAPI** на удалённой серверной машине вам необходим программный сервер, поддерживающий протокол ASGI, такой как **Uvicorn**.
|
||||
|
||||
Существует три наиболее распространённые альтернативы:
|
||||
|
||||
|
|
@ -10,16 +10,16 @@
|
|||
|
||||
## Сервер как машина и сервер как программа
|
||||
|
||||
В этих терминах есть некоторые различия и Вам следует запомнить их. 💡
|
||||
В этих терминах есть некоторые различия и вам следует запомнить их. 💡
|
||||
|
||||
Слово "**сервер**" чаще всего используется в двух контекстах:
|
||||
|
||||
- удалённый или расположенный в "облаке" компьютер (физическая или виртуальная машина).
|
||||
- программа, запущенная на таком компьютере (например, Uvicorn).
|
||||
|
||||
Просто запомните, если Вам встретился термин "сервер", то обычно он подразумевает что-то из этих двух смыслов.
|
||||
Просто запомните, если вам встретился термин "сервер", то обычно он подразумевает что-то из этих двух смыслов.
|
||||
|
||||
Когда имеют в виду именно удалённый компьютер, часто говорят просто **сервер**, но ещё его называют **машина**, **ВМ** (виртуальная машина), **нода**. Все эти термины обозначают одно и то же - удалённый компьютер, обычно под управлением Linux, на котором Вы запускаете программы.
|
||||
Когда имеют в виду именно удалённый компьютер, часто говорят просто **сервер**, но ещё его называют **машина**, **ВМ** (виртуальная машина), **нода**. Все эти термины обозначают одно и то же - удалённый компьютер, обычно под управлением Linux, на котором вы запускаете программы.
|
||||
|
||||
## Установка программного сервера
|
||||
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
=== "Uvicorn"
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, молниесный ASGI сервер, основанный на библиотеках uvloop и httptools.
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, очень быстрый ASGI сервер, основанный на библиотеках uvloop и httptools.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
</div>
|
||||
|
||||
!!! tip "Подсказка"
|
||||
С опцией `standard`, Uvicorn будет установливаться и использоваться с некоторыми дополнительными рекомендованными зависимостями.
|
||||
С опцией `standard`, Uvicorn будет устанавливаться и использоваться с некоторыми дополнительными рекомендованными зависимостями.
|
||||
|
||||
В них входит `uvloop`, высокопроизводительная замена `asyncio`, которая значительно ускоряет работу асинхронных программ.
|
||||
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
|
||||
## Запуск серверной программы
|
||||
|
||||
Затем запустите Ваше приложение так же, как было указано в руководстве ранее, но без опции `--reload`:
|
||||
Затем запустите ваше приложение так же, как было указано в руководстве ранее, но без опции `--reload`:
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
|
|
@ -103,11 +103,11 @@ Starlette и **FastAPI** основаны на <a href="https://anyio.readthedoc
|
|||
|
||||
Тем не менее Uvicorn совместим только с asyncio и обычно используется совместно с <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a>, высокопроизводительной заменой `asyncio`.
|
||||
|
||||
Но если Вы хотите использовать **Trio** напрямую, то можете воспользоваться **Hypercorn**, так как они совместимы. ✨
|
||||
Но если вы хотите использовать **Trio** напрямую, то можете воспользоваться **Hypercorn**, так как они совместимы. ✨
|
||||
|
||||
### Установка Hypercorn с Trio
|
||||
|
||||
Для начала, Вам нужно установить Hypercorn с поддержкой Trio:
|
||||
Для начала, вам нужно установить Hypercorn с поддержкой Trio:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -130,15 +130,15 @@ $ hypercorn main:app --worker-class trio
|
|||
|
||||
</div>
|
||||
|
||||
Hypercorn, в свою очередь, запустит Ваше приложение использующее Trio.
|
||||
Hypercorn, в свою очередь, запустит ваше приложение использующее Trio.
|
||||
|
||||
Таким образом, Вы сможете использовать Trio в своём приложении. Но лучше использовать AnyIO, для сохранения совместимости и с Trio, и с asyncio. 🎉
|
||||
Таким образом, вы сможете использовать Trio в своём приложении. Но лучше использовать AnyIO, для сохранения совместимости и с Trio, и с asyncio. 🎉
|
||||
|
||||
## Концепции развёртывания
|
||||
|
||||
В вышеприведённых примерах серверные программы (например Uvicorn) запускали только **один процесс**, принимающий входящие запросы с любого IP (на это указывал аргумент `0.0.0.0`) на определённый порт (в примерах мы указывали порт `80`).
|
||||
|
||||
Это основная идея. Но возможно, Вы озаботитесь добавлением дополнительных возможностей, таких как:
|
||||
Это основная идея. Но возможно, вы озаботитесь добавлением дополнительных возможностей, таких как:
|
||||
|
||||
* Использование более безопасного протокола HTTPS
|
||||
* Настройки запуска приложения
|
||||
|
|
@ -147,4 +147,4 @@ Hypercorn, в свою очередь, запустит Ваше приложе
|
|||
* Управление памятью
|
||||
* Использование перечисленных функций перед запуском приложения.
|
||||
|
||||
Я поведаю Вам больше о каждой из этих концепций в следующих главах, с конкретными примерами стратегий работы с ними. 🚀
|
||||
Я расскажу вам больше о каждой из этих концепций в следующих главах, с конкретными примерами стратегий работы с ними. 🚀
|
||||
|
|
|
|||
Loading…
Reference in New Issue