Skip to content

Instantly share code, notes, and snippets.

@latestalexey
Forked from pavlov200912/highload.md
Created June 9, 2022 15:23
Show Gist options
  • Select an option

  • Save latestalexey/adf8e2c0e65a8db34b894f8d88f3ff6a to your computer and use it in GitHub Desktop.

Select an option

Save latestalexey/adf8e2c0e65a8db34b894f8d88f3ff6a to your computer and use it in GitHub Desktop.
Конспект Проектирование Высоконагруженных систем 2021

package main

// Билеты по Проектированию Высоконагруженных систем

/*

1. Высоконагруженная система

Высокая нагрузка это что? Простой метод посчитать RPS - request per second 10 RPS много или мало? 1000 RPS много или мало? Ответ: "Это зависит"

High load наступает, когда мы не справляемся с нагрузкой. (это сильно зависит от требований пользователя и задачи)

TODO: ?? А что тут надо еще

2. Проактивные действия разработчика ВС

Как готовиться к High Load?

  • Хорошо понимать задачу
  • Дизайн (архитекутра) - система должна масштабироваться
  • Мониторинг - система должна быть наблюдаема
  • Знать свои технологии / инструменты (+ алгосы и структуры данных)

Как не готовиться?

  • Преждевременные оптимизации (Возможно тратим время просто так, часто портят архитектуру, оптимизированный код иногда выглядит ужасно)

TODO: ??? Добавить еще

3. Пользовательские истории

Требования к системе. Короткими и ясными фразами. На естественном языке.

A user story is an informal, general explanation of a software feature written from the perspective of the end user. Its purpose is to articulate how a software feature will provide value to the customer.

  • Stories keep the focus on the user. (a collection of stories keeps the team focused on solving problems for real users.)
  • Stories enable collaboration. (With the end goal defined, the team can work together to decide how best to serve the user)
  • Stories drive creative solutions.
  • Stories create momentum. (With each passing story the development team enjoys a small challenges and a small win)

“As a [persona], I [want to], [so that].”

4. API. Виды API

API - Application Programming Interface Хотим сделать взаимодействие между различными частями. Нужен протокол/интерфейс. Нам нужна абстракция, например мы не хотим знать детали монитора, но хотим уметь с ним взаимодействовавать Кроме этого, разграничиваем части системы, создав интерфейс.

Wiki: "It defines the kinds of calls or requests that can be made, how to make them, the data formats that should be used, the conventions to follow, etc. It can also provide extension mechanisms so that users can extend existing functionality in various ways and to varying degrees"

Виды API:

  • Библиотеки, фреймворки
  • Application Binary Interface (в такой-то кусок памяти положи то то)
  • Remote (RPC, REST, JSON-API, взаимодействие удаленных узлов)
  • Таблицы, структуры данных
  • Очереди, шины

5. Remote Procedure Call. JSON-RPC, gRPC

Remote Procedure Call - вызов процедуры.

Remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in a different address space (commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction.

RPC is a request–response protocol. An RPC is initiated by the client, which sends a request message to a known remote server to execute a specified procedure with supplied parameters. The remote server sends a response to the client, and the application continues its process.

Адресуем методы. Не говорим про объекты, структуры, сущности.

Какие бывают?

  • SOAP (сообщения в формате XML, объекты которые мы передаем в рамках протокола должны соотв. схеме)
  • JSON-RPC, XML-RPC (простые схемы)
  • gRPC (google RPC)
  • очень много других

JSON-RPC:

  • использует любой транспорт
  • сообщения - JSON объекты с определенной схемой
  • использует систему типов JSON

Пример запроса

{
 "jsonrpc": "2.0", // версия протокола
 "method": "substract",
 "params": [42, 43],
 "id": 1 // id запроса, будет копирован в ответ
}

Пример ответа

{
 "jsonrpc": "2.0",
 "result": 19, // вместо result может быть error с кодом и сообщением ошибки
 "id": 1
}

Используется в очень примитивных ситуациях, плохая поддержка в Go

gRPC

  • Протокол
  • Фреймворк для разных языков и платформ (есть набор инструментов)
  • Бинарная сериализация
  • Транспорт: HTTP/2
  • Поддерживает двунаправленные потоки (можно не диалог, а монолог, просто стримить сообщения)
  1. Определяем протокол (*.proto file)
  2. Генерируем код клиента и сервера
  3. Реализуем сервер и клиент

Пример proto файла:

syntax = "proto3";

option go_package = "github.com/mp-hl-2021/grpc-example/ api";

package echo;

service Echo {
  rpc Do(EchoRequest) returns (EchoReply) {}
}

message EchoRequest {
  string line = 1;
  int32 num = 2;
}

message EchoReply {
  string echo_line = 1;
}

Генерируем код

 protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative api/echo.proto

Нам сгенерируют интерфейсы и методы заглушки, нужно их реализовать

6. REST API. REST API как набор ограничений. Недостатки.

Representational State Transfer

Архитектурный стиль, в котором клиент state machine, а сервер движок текстовых квестов (вы в такой-то комнате, у вас дверь на север, на юг, куда кликните? и т.д)

REST как набор ограничений:

  • Separation of Client and Server (имплементации сервера и клиента могут не знать о друг друге, пока каждая сторона понимает формат общения, они могут изменяться независимо)
  • Statelessness (Сервер не должен знать ничего о состоянии клиента и наоборот, таким образом клиент и сервер могут воспринимать любые получаемые сообщения, даже без истории взаимодействия до)
  • Cacheable (Данные в запросах и ответах могут быть помечены как кешируемые, стороны могут использовать те же данные при дальнейших запросах, не обновляя их)
  • Uniform interface (
    • Identification of resources; (for example with URLs)
    • manipulation of resources through representations; (имея ресурс representation of a resource клиенту хватает информации чтобы модифицировать или удалить его)
    • Self-descriptive messages (Каждое сообщение содержит достаточно информации, чтобы его обработать)
    • Hypermerdia as the engine of application state)
  • Layered system (Разделяем приложение на слои, ограничиваем каждую компоненту в взаимодействии: разрешаем только с компонентами ее слоя)

TODO: Недостатки REST? Он вообще ничего не сказал

7. HTTP и HTTPS: модель, методы и их семантика.

HTTP - HyperText Transfer Protocol (уровень общения application)

HyperText and HyperMedia - к какждому нашему медиа (текст, картинки) добавляем перекрестные ссылки, каждый ресурс получает идентификатор и мы можем использовать их внутри наших дкументов, чтобы ссылаться на другие ресурсы, ссылки могут быть нелинейные.

HTTP Model - все представляется в виде ресурсов, к каждому ресурсу можно получить доступ по URL (Uniform Resource Location)

Пример https://example.com:80/examples/1#test

Примерная грамматика URL: scheme://[userinfo@]host[:port]/path[?query][#fragment]

HTTP: Запрос

  • Метод (глагол)
  • Положение ресурса
  • Заголовки
  • Тело

Методы:

  • GET (получить предстваление ресурса)
  • HEAD - как GET но не возвращает тело (например метаданные взять из заголовка, когда ресурс обновился)
  • POST - передает серверу "нечто" в подчинение какому-то ресурсу (ресурсу по URL)
  • PUT - сохранить "нечто" с доступом по указанному URI
  • DELETE - удалить ресурс
  • etc

HTTP: ответ

  • Статус (некий код)
  • Заголовок
  • Тело

Статус коды:

Informational responses (100–199) Successful responses (200–299) Redirects (300–399) Client errors (400–499) Server errors (500–599)

HTTPS: HTTP over TLS (secured TCP), Алиса и Боб используют асимметричное шифрование (Открытый, приватный ключ у Алисы, но еще нужно подписывать сообщения у сторонних сервисов, которым все доверяют) Мы как владельцы домена приходим к Certification Authority, один раз валидируем свою личность, получаем подпись и кладем ее в конфиг сервера, теперь нам можно доверять (ну типа)

8. Аутентификация и авторизация.

Аутентификация - процесс, при котором система удостоверяется, что нечто является подлинным

  • ID соответствует пользователю
  • Сайт настоящий, а не поддельный

Авторизация - подтверждения права получить доступ к ресурсу. (и если есть доступ, то какой)

9. Аутентификация в Web. Basic HTTP Authentication. Form-based authentication. Cookies. JSON Web Token

Basic HTTP Authentication

(через HTTP заголовок) Клиент:

Authorization: Basic <credentials>
credentials := BASE64(id:password)
Authorization: Basic AkkBkerCdlaFASff6Adssf66a6f6jg891921bBbasdgvbadsC

Сервер (если не авторизован)

401 Unauthorized
WWW-Authenticate: Basic realm="User Visible Realm" // отвечает на что авторизация

Такой подход незащищенный, заголовки не шифруются, легко представится пользователем

Form-Based Authentication

  • Формочка, в нее записываем логин пароль
  • После этого например это в javascript записывается в json, отправляется POST запросом на сервер
  • Сервер валидирует данные этой формы, возвращает токен Надо как-то хранить токен, чтобы каждый раз не пришлось вводить логин-пароль Два варианта, про которые сказал Никита:
  • Cookies
  • Bearer Authentication

HTTP Cookie:

Механизм хранения состояния на стороне клиента

  • Аутентификация
  • Корзина товаров (так стараются не делать)
  • Персональные предпочтнения (темная тема)
  • Слежка за пользователями (third party cookies, я так понял это хотят забанить)

Чтобы выставить Cookies сервер возвращает заголовки

Set-Cookie: theme=light
Set-Cookie: sessionToken=6dasdgafasdsa; Expires=Wed, 09 Jun 2021 10:18:14 GMT

В следующий раз мы (client) уже в заголовке посылаем

Cookie: theme=light; sessionToken=6dasdgafasdsa

Виды HTTP Cookie:

  • Session (удаляются после закрытия браузера)
  • Persistent (удаляются с течением времени, хранятся внутри браузера)
  • Secure (работают только по HTTPS)
  • Same-site (Отправлять куки только в рамках домена, защищает от Cross Site Scripting) TODO: XSS
  • Third-party (Куки, установленные с других доменов)
  • HTTP-Only (Недоступно из клиентского JS)
  • ...

В Go для работы с куки есть http.Cookie

Cookie опасны! (XSS)

  • Требуйте HTTPS (secure cookies)
  • Помните, что на клиенте тоже могут подменить куки (сервер не должен всегда доверять содержимому куки, если мы хотим обезопасить себя, нужно хранить состояние клиента, в реальности корзину мы храним на сервере, session_id храним на сервере, и т.д в итоге от REST много где нам придется отказаться =((( )
  • Устанавливайте Domain

JSON Web Token

JWT, джот - кусок данных в формате JSON, использует подпись и/или шифрование Сервер вместе с джотом генерирует подпись, по которой может проверить, что JSON был сгенерирован им Обычно содержит информацию о правах доступа.

Обычно кодируют публичным и приватным ключом, приватный оставляют только у сервера. В Go это все делает либой rsa и с помощью openssl.

JWT не средство шифрования! Токен подписан, но любой сторонний сервис может узнать содержимое

10. Авторизация. Основная схема OAuth2.0.

Пример: Создать аккаунт с помощью Apple/Facebook/Google/Microsoft

  • Resource Owner (конечный пользователь, ресурс - мой акк в гугле)
  • Resource Server (хранит ресурсы, гугл)
  • Client (сторонее приложение, сокращатель ссылок)
  • Authorization Server - выдает клиенту токены, которые разрешают от имени RO получить доступ к ресурсам на RS

гугл = Resource Server

Client запрашивает разрешение у RO на авторизацию через гугл

RO выдает разрешение Client

Client показывает разрешение Authorization Server

Authorization Server выдает Client Access Token

Client показывает гугл Access Token

гугл выдает protected resource Client-у

Обновление токена:

Обычно вместе с Access Token выдается Refresh Token, Access Token работает какое-то время, используя Refresh Token Client может обновить Access Token

11. Работа с паролями.

  • Не храните пароли в открытом виде
  • Проверяйте сложность, валидируйте
  • Не изобретайте свои алгоритмы !!!
  • Защищайтесь от перебора
  • Подумайте о возможных уязвимостях (модель угроз)

Как хранить пароли?

  • В открытом виде (базу точно украдут и все пароли утекут)
  • Криптографические хеш функции (из байтов делаем мусор, функция необратима) (В базу сохраняем хэши паролей) (возможен перебор по таблицам паролей - хешей, радужные таблицы)
  • Добавляем соль к паролю (добавляем какую-то строку ко всем паролям и после считаем хеш) (сложно строить таблицы, но можно узнать соль)
  • Рандомизируем соль
  • Добавляем раунды хеширования
  • Не пишем ничего из этого, используем bcrypt

26. Зачем нужен язык Go

  • Стремительно набирает популярность в серверной разработке
  • Хорошо иметь еще один инструмент в запасе (кроме петона)
  • Го простой язык, легко перейти с Java/C++/C
  • Документация Go, число деталей, намного меньше, чем у тех же C++/Java
  • Go стремится к простоте и единообразию (хочется всего один способ сделать вещь правильно)
  • Компилируется в нативный код (лучше чем JavaScript)
  • Автоматическое управление памятью (лучше чем C/C++)
  • Удобная поддержка конкуретного программирования (на уровне синтаксиса, в отличие от C++/Java) (в питоне есть async/await, но во-первых, у него нет своего планировщика, во-вторых, заражает весь остальной код, короче неудобно)
  • Много инфраструктурного кода написано на Go (docker, kubernetes, etc)

The Why of Go?

go is not good:

  • too simple / lack of sugar
  • no generics
  • bad dependency management
  • stuck in 70/80s
  • error handling
  • no unused imports
  • too opinionated
  • too verbose
  • no ternary operator
  • no macros or templates

Go's 21st Century Characteristics

  • Concurrency (C++ at Google was awful with concurrency)
  • Distributed Systems
  • Garbage Collection
  • Memory Locality
  • Readability

27. Синтаксис Go. Система пакетов. Базовые типы.

Пакеты в Go - набор файликов, которые делят область видимости типов и переменных

package main - точка входа */

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment