Фото Isaac Maffeis на Unsplash
Хто сказав, що тільки GET-запити можуть користуватися перевагами кешування? Хоча розробники часто вважають POST-запити некешованими за замовчуванням, є одна таємниця: вони можуть бути такими ж швидкими та ефективними, як і GET-запити. Використовуючи FastAPI та Redis, ви можете реалізувати потужне кешування POST-запитів, яке змусить вас переосмислити все, що ви знали про шаблони кешування HTTP. Давайте розглянемо, як вийти за межі цих обмежень і значно покращити продуктивність вашого API.
Початок роботи
Перед тим як заглибитися у магію, підготуйте наше FastAPI-додаток і переконайтеся, що Docker встановлений на вашому комп'ютері.
Слідуйте інструкціям для Docker та Docker Compose.
Весь код доступний тут:
[
GitHub - anotherbuginthecode/medium-fastapi-redis: Посібник по використанню FastAPI та Redis для кешування POST-запитів
Посібник по використанню FastAPI та Redis для кешування POST-запитів - anotherbuginthecode/medium-fastapi-redis
github.com
](https://github.com/anotherbuginthecode/medium-fastapi-redis?source=post_page-----0219c7fa454f--------------------------------)
Створення Dockerized FastAPI та Redis налаштувань
Dockerfile для FastAPI: створіть Dockerfile
для вашого FastAPI додатку:
# Використовувати офіційний базовий образ Python
FROM --platform=linux/x86_64 python:3.11-slim-buster
ENV PYTHONBUFFERED=1 \
TZ=Europe/Rome \
LOG_LEVEL=INFO
RUN apt-get update -y
RUN apt-get install -y gcc g++ build-essential unzip dos2unix
RUN apt-get install -y libpq-dev
RUN apt-get update && apt-get install -y libcurl4-openssl-dev libssl-dev
RUN pip install --upgrade pip
# Встановлюємо робочий каталог всередині контейнера
WORKDIR /app
# Копіюємо файл вимог до робочого каталогу
COPY requirements.txt .
# Встановлюємо залежності додатку
RUN pip install wheel pybind11
RUN pip install --no-cache-dir -r requirements.txt
# Копіюємо код додатку до робочого каталогу
COPY . .
# Відкриваємо порт, на якому буде працювати FastAPI
EXPOSE 8000
# Встановлюємо команду для запуску додатку
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
requirements.txt: переконайтеся, що у вашому файлі requirements.txt
є FastAPI та Redis
fastapi
uvicorn
redis
pydantic
sqlalchemy
psycopg2-binary
jinja2==3.0.3
jinjasql==0.1.8
Docker Compose файл: створіть файл docker-compose.yml
для налаштування контейнерів FastAPI та Redis:
version: "3.8"
services:
redis:
container_name: redis
image: redis:7.0
redis-ui: # для наявності візуального UI для керування кешем redis
container_name: redis-ui
image: redislabs/redisinsight:1.14.0
ports:
- 8001:8001
depends_on:
- redis
db:
image: postgres
container_name: db
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
api:
build: .
command: "uvicorn src.app:app --host 0.0.0.0 --port 8000 --reload"
ports:
- "8000:8000"
volumes:
- ./src:/app/src
depends_on:
- redis
- db
Щоб запустити контейнери, виконайте команду:
docker-compose up -d --build
#if you are using the last version of docker
docker compose up -d --build
Розуміння кешування POST-запитів
Кешування POST-запитів може здатися контрінтуїтивним, оскільки POST-запити зазвичай змінюють стан сервера. Однак для ідемпотентних POST-запитів — тих, що дають однаковий результат за однаковим вхідним даним — кешування може значно покращити продуктивність.
Ідея виникла під час розробки інформаційної панелі з динамічними фільтрами для обробки даних, що вимагають важкої обробки. Для оптимізації продуктивності нам потрібно було кешувати фільтри, надіслані через POST-запит. Так, я знаю — використання GET-запиту з параметрами запиту було б «правильним» і простішим вибором.
Фото Isaac Maffeis на Unsplash
Хто сказав, що тільки GET-запити можуть користуватися перевагами кешування? Хоча розробники часто вважають POST-запити некешованими за замовчуванням, є одна таємниця: вони можуть бути такими ж швидкими та ефективними, як і GET-запити. Використовуючи FastAPI та Redis, ви можете реалізувати потужне кешування POST-запитів, яке змусить вас переосмислити все, що ви знали про шаблони кешування HTTP. Давайте розглянемо, як вийти за межі цих обмежень і значно покращити продуктивність вашого API.
Початок роботи
Перед тим як заглибитися у магію, підготуйте наше FastAPI-додаток і переконайтеся, що Docker встановлений на вашому комп'ютері.
Слідуйте інструкціям для Docker та Docker Compose.
Весь код доступний тут:
[
GitHub - anotherbuginthecode/medium-fastapi-redis: Посібник по використанню FastAPI та Redis для кешування POST-запитів
Посібник по використанню FastAPI та Redis для кешування POST-запитів - anotherbuginthecode/medium-fastapi-redis
github.com
](https://github.com/anotherbuginthecode/medium-fastapi-redis?source=post_page-----0219c7fa454f--------------------------------)
Створення Dockerized FastAPI та Redis налаштувань
Dockerfile для FastAPI: створіть Dockerfile
для вашого FastAPI додатку:
# Використовувати офіційний базовий образ Python
FROM --platform=linux/x86_64 python:3.11-slim-buster
ENV PYTHONBUFFERED=1 \
TZ=Europe/Rome \
LOG_LEVEL=INFO
RUN apt-get update -y
RUN apt-get install -y gcc g++ build-essential unzip dos2unix
RUN apt-get install -y libpq-dev
RUN apt-get update && apt-get install -y libcurl4-openssl-dev libssl-dev
RUN pip install --upgrade pip
# Встановлюємо робочий каталог всередині контейнера
WORKDIR /app
# Копіюємо файл вимог до робочого каталогу
COPY requirements.txt .
# Встановлюємо залежності додатку
RUN pip install wheel pybind11
RUN pip install --no-cache-dir -r requirements.txt
# Копіюємо код додатку до робочого каталогу
COPY . .
# Відкриваємо порт, на якому буде працювати FastAPI
EXPOSE 8000
# Встановлюємо команду для запуску додатку
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
requirements.txt: переконайтеся, що у вашому файлі requirements.txt
є FastAPI та Redis
fastapi
uvicorn
redis
pydantic
sqlalchemy
psycopg2-binary
jinja2==3.0.3
jinjasql==0.1.8
Docker Compose файл: створіть файл docker-compose.yml
для налаштування контейнерів FastAPI та Redis:
version: "3.8"
services:
redis:
container_name: redis
image: redis:7.0
redis-ui: # для наявності візуального UI для керування кешем redis
container_name: redis-ui
image: redislabs/redisinsight:1.14.0
ports:
- 8001:8001
depends_on:
- redis
db:
image: postgres
container_name: db
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
api:
build: .
command: "uvicorn src.app:app --host 0.0.0.0 --port 8000 --reload"
ports:
- "8000:8000"
volumes:
- ./src:/app/src
depends_on:
- redis
- db
Щоб запустити контейнери, виконайте команду:
docker-compose up -d --build
#if you are using the last version of docker
docker compose up -d --build
Розуміння кешування POST-запитів
Кешування POST-запитів може здатися контрінтуїтивним, оскільки POST-запити зазвичай змінюють стан сервера. Однак для ідемпотентних POST-запитів — тих, що дають однаковий результат за однаковим вхідним даним — кешування може значно покращити продуктивність.
Ідея виникла під час розробки інформаційної панелі з динамічними фільтрами для обробки даних, що вимагають важкої обробки. Для оптимізації продуктивності нам потрібно було кешувати фільтри, надіслані через POST-запит. Так, я знаю — використання GET-запиту з параметрами запиту було б «правильним» і простішим вибором.
Це корисно, якщо ви хочете мати більше контролю та аналізувати найбільш поширені комбінації, щоб надати стратегії для оптимізації застосунку.
// приклад payload
{
"start_date": "2022-06-04",
"end_date": "2023-06-04",
"typology": "arrival"
}
// не захешований ключ:/data?start_date=2022-06-04&end_date=2023-06-04&typology=arrival
Інтеграція Redis з нашим кінцевим пунктом
from fastapi import FastAPI, Request, Depends
from pydantic import BaseModel
import json
from .service import get_total_flights
from .database import RedisWrapper, get_db
from enum import Enum
app = FastAPI()
redis_wrapper = RedisWrapper()
class FlightTypology(str, Enum):
departure = "departure"
arrival = "arrival"
class BaseRequestSchema(BaseModel):
start_date: str
end_date: str
airport_codes: list[str] | None = None
typology: FlightTypology = FlightTypology.departure
class Config:
use_enum_values = True
@app.post("/data")
async def handle_post(data: BaseRequestSchema, db=Depends(get_db)):
cache_key = redis_wrapper.create_cache_key(data.model_dump())
not_hashed_cache_key = redis_wrapper.convert_payload_to_query_params(
endpoint="/data", payload=data.model_dump()
)
print("Не захешований ключ кешу: ", not_hashed_cache_key)
cached_response = redis_wrapper.get_from_cache(cache_key)
if cached_response:
return json.loads(cached_response)
response_data = get_total_flights(
db=db,
params=data.model_dump(),
)
redis_wrapper.store_in_cache(cache_key, json.dumps(response_data))
return response_data
Коли ми викликаємо наш POST-запит, метод handle_post
перевіряє, чи існує ключ, згенерований методом redis_wrapper.create_cache_key(data.model_dump())
, у Redis. Якщо так, він повертає кешований результат. В іншому випадку, він використовує згенерований ключ і вихідні дані з бази даних для збереження в Redis.
Давайте подивимося, як це працює
Не кешований результат зайняв 14 мс
Додаток зайняв 14 мс для повернення результату, і якщо ми виконаємо той самий запит знову, це займе 7 мс, тому що результат вже кешовано в Redis.
Кешований результат зайняв 7 мс
Перевірте Redis UI за адресою http://localhost:8001
, щоб побачити ваші кешовані результати — кожен захешований запит payload і відповідне обчислене значення.
Виведення, кешоване в Redis з використанням захешованого payload як ключа
Висновки
Вітаємо! Ви щойно розблокували потужний спосіб кешувати POST-запити — те, що багато розробників вважають неможливим. Тепер ви не тільки створили систему, яка робить ваш API швидшим і ефективнішим, але й навчилися мислити поза межами традиційних шаблонів кешування HTTP.
Експериментуйте з цим шаблоном у ваших проектах.
Чи то складна аналітика, важкі обчислення, чи операції з великими даними, тепер у вас є новий інструмент у вашому арсеналі для оптимізації.
Щасливого кешування!
Дякуємо, що стали частиною нашої спільноти
Перш ніж піти:
- Не забудьте поставити лайк і підписатися на автора ️👏️️
- Слідкуйте за нами: X | LinkedIn | YouTube | Newsletter | Podcast
- Перевірте CoFeed, розумний спосіб залишатися в курсі останніх новин у світі технологій 🧪
- Створіть свій безкоштовний блог, підживлюваний ШІ, на Differ 🚀
- Приєднуйтесь до нашої спільноти контент-креаторів на Discord 🧑🏻💻
- Для більшої кількості контенту відвідайте plainenglish.io + stackademic.com
Перекладено з: From Slow to Fast: Caching POST Requests in FastAPI Using Redis