Автор: Цзян Ханг
Github: github.com/nodejh
В последнее время много говорят о Serverless. Бессерверные технологии, которые, кажется, имеют мало общего с интерфейсом, на самом деле связаны с интерфейсом и окажут преобразующее влияние на модель разработки интерфейса. В этой статье в основном обсуждается модель фронтенд-разработки в Serverless, начиная с эволюции модели фронтенда, примеров бессерверной фронтенд-разработки и лучших практик бессерверной разработки, основанных на личном понимании и резюме. Я также имел честь поделиться этой темой на QCon2019.
Эволюция модели фронтенд-разработки
Прежде всего, чтобы рассмотреть эволюцию модели разработки интерфейса, я думаю, что в основном есть четыре этапа.
- Отображение динамических страниц на основе шаблонов
- Разделение интерфейса и сервера на основе AJAX
- Фронтенд-инжиниринг на основе Node.js
- Разработка полного стека на основе Node.js
Отображение динамических страниц на основе шаблонов
В раннюю эпоху Интернета наши веб-страницы были очень простыми, просто статическими или динамическими страницами, основной целью которых было отображение и распространение информации. В настоящее время также очень легко разработать веб-страницу.Главное - написать несколько динамических шаблонов через JSP, PHP и другие технологии, а затем разобрать шаблоны в HTML-файлы через веб-сервер. Браузер несет ответственность только за для рендеринга этих файлов HTML. На этом этапе нет разделения труда между фронтендом и бэкендом, обычно фронтенд-страницы пишут бэкенд-инженеры.
Разделение интерфейса и сервера на основе AJAX
Официальное внедрение технологии AJAX в 2005 году открыло новую главу в веб-разработке. Основываясь на AJAX, мы можем разделить Интернет на интерфейс и серверную часть, фронтенд отвечает за интерфейс и взаимодействие, а серверная часть отвечает за обработку бизнес-логики. Front-end и back-end обмениваются данными через интерфейс. Нам также больше не нужно писать неподдерживаемый HTML на различных языках бэкенда. Сложность веб-страниц также переместилась с внутреннего веб-сервера на JavaScript на стороне браузера. Из-за этого началась должность фронтенд-инженера.
Фронтенд-инжиниринг на основе Node.js
Появление Node.js в 2009 году также стало историческим моментом для фронтенд-инженеров. Вместе с Node.js появилась спецификация CommonJS и механизм управления пакетами npm. Затем появился ряд инструментов для разработки и создания интерфейса на основе Node.js, таких как Grunt, Gulp и Webpack.
Примерно в 2013 году три фронтенд-фреймворка React.js/Angular/Vue.js выпустили свои первые версии одна за другой. Мы можем перейти от предыдущей разработки, основанной на одной странице, к разработке, основанной на компонентах. После завершения разработки используйте такие инструменты, как webpack, для упаковки и сборки, а также публикуйте результаты сборки в Интернете с помощью инструментов командной строки на основе Node.js. Фронтенд-разработка стала стандартизированной, стандартизированной и спроектированной.
Разработка полного стека на основе Node.js
Важное значение Node.js для внешнего интерфейса заключается в том, что JavaScript, который раньше работал только в браузере, также может работать на сервере.Фронтенд-инженеры могут использовать язык, с которым они наиболее знакомы, для написания серверного кода. . Поэтому фронтенд-инженеры начали использовать Node.js для разработки полного стека и начали переходить от фронтенд-инженеров к разработчикам полного стека. Это интерфейс, который берет на себя инициативу, чтобы выйти за собственные границы.
С другой стороны, передняя часть развивается, и задняя часть также развивается. Практически в момент рождения Node.js бэкенд вообще начал меняться от модели монолитного приложения к микросервисной архитектуре. Это также приводило к различиям в разделении труда между передним и задним концами в прошлом. С появлением микросервисной архитектуры внутренний интерфейс постепенно становится атомарным, а интерфейс микросервиса больше не ориентирован непосредственно на страницу, а внешний вызов усложняется. В результате возникла архитектура BFF (Backend For Frontend): между микросервисами и фронтендом был добавлен слой BFF, а интерфейсы агрегировались и обрезались BFF, а затем выводились во фронтенд. Уровень BFF не является основной работой серверной части, он наиболее близок к интерфейсу и имеет наибольшую связь с интерфейсом, поэтому разработчики интерфейса, естественно, выбрали Node.js для реализации. Это также наиболее широко используемое приложение Node.js на стороне сервера.
Модель фронтенд-разработки следующего поколения
Можно видеть, что каждое изменение в модели разработки интерфейса связано с преобразующей технологией. Сначала AJAX, потом Node.js. Итак, какова следующая преобразующая технология? Само собой разумеется, что это Serverless.
Интерфейсные решения в бессерверных сервисах
Введение в бессерверные технологии
Бессерверные, как определено CNCF, относятся к концепции создания и запуска приложений, не требующих управления сервером. (serverless-overview)
Serverless computing refers to the concept of building and running applications that do not require server management. --- CNCF
На самом деле Serverless уже подключен к фронтенду, но мы можем его не воспринимать. Например, в CDN, после того как мы публикуем статические ресурсы в CDN, нам не нужно заботиться о том, сколько узлов имеет CDN, как они распределяются или как он выполняет балансировку нагрузки и ускорение сети, поэтому CDN является бессерверным для передний конец. Другим примером является объектное хранилище. Как и CDN, нам нужно только загружать файлы в объектное хранилище, и мы можем использовать его напрямую. Нам не нужно заботиться о том, как оно обращается к файлам и как управлять разрешениями. Поэтому объектное хранилище является бессерверным. для фронтенд-инженеров. Даже некоторые сторонние API-сервисы бессерверны, потому что, когда мы их используем, нам не нужно заботиться о сервере.
Конечно, иметь соматосенсорику недостаточно, нужно еще более точное определение. С технической точки зрения Serverless представляет собой комбинацию FaaS и BaaS.
Бессерверные решения = FaaS + BaaS.
Проще говоря, FaaS (функция как услуга) — это платформа для запуска функций, таких как функциональные вычисления Alibaba Cloud, Lambda AWS и т. д.
BaaS (Backend as a Service) — это некоторые серверные облачные сервисы, такие как облачные базы данных, хранилище объектов, очереди сообщений и т. д. Использование BaaS может значительно упростить разработку нашего приложения.
Бессерверные можно понимать как функции, работающие в FaaS и использующие BaaS.
Основные особенности бессерверной версии:
- управляемый событиями
- В платформе FaaS функции должны управлять выполнением функций посредством ряда событий.
- нет статуса
- Поскольку выполнение каждой функции может использовать другой контейнер, совместное использование памяти или данных невозможно. Если вы хотите поделиться данными, вы можете использовать только сторонние сервисы, такие как Redis и т. д.
- Без эксплуатации и обслуживания
- С Serverless нам не нужно заботиться о серверах, и нам не нужно заботиться об эксплуатации и обслуживании. Это также является ядром идеи Serverless.
- бюджетный
- Использование Serverless дешево, потому что мы платим только за каждый запуск функции. Если функция не запускается, она не стоит денег и не тратит ресурсы сервера
Схема архитектуры интерфейсного решения в бессерверном сервисе
На приведенном выше рисунке показаны некоторые из текущих основных бессерверных служб и соответствующие интерфейсные решения.
Снизу вверх, инфраструктура и инструменты разработки.
Инфраструктура в основном предоставляется некоторыми поставщиками облачных вычислений, включая платформы облачных вычислений и различные услуги BaaS, а также платформы FaaS, которые выполняют функции.
Внешний интерфейс — это в основном бессерверный пользователь, поэтому для внешнего интерфейса, наиболее важного уровня инструментов разработки, нам нужно полагаться на инструменты разработки для бессерверной разработки, отладки и развертывания.
Фреймворк
Сегодня не существует единого бессерверного стандарта, и бессерверные службы, предоставляемые разными платформами облачных вычислений, скорее всего, будут разными, что делает невозможным плавную миграцию нашего кода. Одной из основных функций бессерверной инфраструктуры является упрощение процесса бессерверной разработки и развертывания, а другой основной функцией является скрытие различий между различными бессерверными службами, чтобы наши функции можно было использовать в других бессерверных службах без изменения или только с изменением. небольшая часть из них тоже работает.
Общие бессерверные фреймворкиServerless Framework,ZEIT Now,ApexЖдать. Однако этим в основном занимаются иностранные компании, а в Китае такой площадки нет.
Web IDE
Веб-IDE, тесно связанные с Serverless, в основном представляют собой веб-IDE для различных платформ облачных вычислений. Используя Web IDE, мы можем легко разрабатывать и отлаживать функции в облаке, а также развертывать их непосредственно на соответствующей платформе FaaS. Преимущество этого заключается в том, чтобы избежать установки различных инструментов разработки и локальной настройки различных сред. Общие веб-среды IDE включают Cloud9 от AWS, Web IDE для функциональных вычислений Alibaba Cloud и Cloud Studio от Tencent Cloud. С точки зрения опыта AWS Cloud9 является лучшим.
инструмент командной строки
Конечно, наиболее важным методом развития в настоящее время является локальное развитие. Поэтому также важно разрабатывать бессерверные инструменты командной строки локально.
Существует два основных типа инструментов командной строки, один из которых предоставляется платформой облачных вычислений, такой как AWS.aws
, Лазурьaz
, Облако Алибабаfun
; Существует еще одна категория, предоставляемая бессерверной структурой, напримерserverless
,now
.
Большинство инструментов, таких какserverless
,fun
И т. д., все реализовано в Node.js.
Ниже приведены несколько примеров инструментов командной строки.
Создайте
# serverless
$ serverless create --template aws-nodejs --path myService
# fun
$ fun init -n qcondemo helloworld-nodejs8
развертывать
# serverless
$ serverless deploy
# fun
$ fun deploy
отладка
# serverless
$ serverless invoke [local] --function functionName
# fun
$ fun local invoke functionName
Сценарии применения
Одним уровнем выше инструментов разработки являются некоторые вертикальные сценарии приложений Serverless. В дополнение к использованию традиционной разработки на стороне сервера в настоящее время ведется разработка небольших программ с использованием бессерверной технологии, и в будущем может быть разработана область Интернета вещей (IoT).
Сравнение различных бессерверных сервисов
На приведенном выше рисунке сравниваются различные бессерверные службы с точки зрения поддерживаемых языков, триггеров, цен и т. д., и можно обнаружить, что существуют различия и общие черты.
Например, почти все бессерверные сервисы поддерживают такие языки, как Node.js/Python/Java.
С точки зрения поддерживаемых триггеров почти все службы также поддерживают такие триггеры, как HTTP, хранилище объектов, запланированные задачи и очереди сообщений. Конечно, эти триггеры также связаны с внутренними сервисами платформы.Например, триггеры объектного хранилища Alibaba Cloud запускаются такими событиями, как доступ к продуктам OSS Alibaba Cloud, в то время как триггеры объектного хранилища AWS запускаются на основе таких событий, как доступ к продуктам OSS от Alibaba Cloud.Инициируется событие AWS S3, и эти две платформы не являются универсальными. Это также проблема, с которой в настоящее время сталкивается Serverless, то есть стандарты не являются едиными.
С точки зрения выставления счетов плата за каждую платформу в основном одинакова. Как упоминалось ранее, Serverless оплачивается по количеству вызовов. На каждый бессерверный сервер приходится 1 миллион бесплатных вызовов в месяц, а затем почти 1,3 йены за миллион, а также 400 000 ГБ бесплатного времени выполнения, а затем 0,0001108 йен за 1 ГБ-с. Поэтому, когда объем приложения невелик, использование Serverless очень выгодно с точки зрения затрат.
Бессерверная модель фронтенд-разработки
В этой главе используется несколько случаев, чтобы проиллюстрировать режим фронтенд-разработки на основе Serverless и его отличия от предыдущей фронтенд-разработки.
Прежде чем приступить к конкретному делу, давайте взглянем на традиционный процесс разработки.
В традиционном процессе разработки нам нужны фронтенд-инженеры для написания страниц и бэкэнд-инженеры для написания интерфейсов. После того, как серверная часть написала интерфейс, интерфейс развертывается, а затем выполняется совместная отладка клиентской и серверной частей. После того, как совместная отладка будет завершена, она будет протестирована и запущена. После подключения к сети инженеры по эксплуатации и техническому обслуживанию также должны обслуживать систему. Весь процесс включает в себя множество разных ролей, связь длинная, а общение и координация также представляют собой проблему.
На основе Serverless серверная часть становится очень простой. Предыдущие серверные приложения были разделены на функции. Вам нужно только написать функции и развернуть их в службе Serverless, и вам не нужно заботиться об эксплуатации и обслуживании. любого сервера в будущем. Порог для back-end разработки был значительно снижен. Поэтому всю работу по разработке может выполнять только один фронтенд-инженер.
Конечно, фронтенд-инженерам для написания бэкенда на базе Serverless лучше всего иметь определенные знания бэкенда. Включая сложные серверные системы или сценарии, где бессерверная разработка неприменима, по-прежнему требуется внутренняя разработка, и серверная часть становится более отсталой.
Бессерверный BFF
С одной стороны, разные устройства должны использовать разные API, с другой стороны, из-за сложности вызовов фронтенд-интерфейса из-за микросервисов фронтенд-инженеры стали использовать метод BFF для агрегирования и адаптации интерфейсов для получения интерфейсы, подходящие для front-end.
Ниже представлена общая архитектура BFF.
BFF @ SoundCloud
Нижний уровень — это различные серверные микросервисы, а верхний — различные интерфейсные приложения. До микросервисов и приложений это был BFF, обычно разрабатываемый фронтенд-инженерами.
Такая архитектура решает проблему согласования интерфейсов, но также приносит некоторые новые проблемы.
Например, разработка приложения BFF для каждого устройства также столкнется с некоторыми проблемами повторной разработки. В прошлом интерфейсу требовалось только разрабатывать страницы и сосредоточиться на рендеринге на стороне браузера, но теперь необходимо поддерживать различные приложения BFF. В прошлом интерфейсу не нужно было заботиться о параллелизме, но теперь давление параллелизма сосредоточено на BFF. Как правило, стоимость эксплуатации и обслуживания очень высока, и, как правило, внешний интерфейс не очень хорош в эксплуатации и обслуживании.
Serverless может помочь нам очень хорошо решить эти проблемы. На основе Serverless мы можем использовать одну функцию для реализации агрегации и адаптации каждого интерфейса. Запрос, инициированный внешним интерфейсом к BFF, эквивалентен HTTP-триггеру FaaS, который инициирует выполнение функции.Эта функция реализует бизнес-логику запроса, например вызов нескольких микросервисов для получения данных, а затем возвращает результат обработки. результат. на передний конец. Таким образом, нагрузка по эксплуатации и обслуживанию переместилась с предыдущего сервера BFF на службу FaaS, и клиентскому интерфейсу больше не нужно заботиться о сервере.
На картинке выше показана архитектура BFF, основанная на Serverless. Чтобы лучше управлять различными API, мы также можем добавить уровень шлюза для управления всеми API (например, шлюзом Alibaba Cloud) через шлюз, например, для группировки и подсреды API. На основе шлюза API внешний интерфейс не выполняет функции напрямую через триггеры HTTP, а отправляет запросы шлюзу, а затем шлюз инициирует выполнение определенных функций.
Бессерверный серверный рендеринг
Основываясь на трех самых популярных интерфейсных фреймворках (React.js/Anguler/Vue.js), большинство текущих методов рендеринга — это рендеринг на стороне клиента. Когда страница инициализируется, загружаются только простой HTML и соответствующий файл JS, а затем JS отображает страницы одну за другой. Основная проблема с этим подходом — время белого экрана и SEO.
Чтобы решить эту проблему, передняя часть снова начала пробовать рендеринг на стороне сервера. Основная идея на самом деле такая же, как и в самом раннем рендеринге шаблона. Внешний интерфейс инициирует запрос, внутренний сервер анализирует документ HTML, а затем возвращает его в браузер. Просто раньше это был шаблон для серверных языков, таких как JSP и PHP, а теперь это изоморфное приложение на основе React, Vue и т. д., что также является преимуществом сегодняшних серверных решений для рендеринга .
Но рендеринг на стороне сервера создает перед интерфейсом некоторые дополнительные проблемы: затраты на эксплуатацию и обслуживание, а интерфейс должен поддерживать сервер для рендеринга.
Самым большим преимуществом безсерверных технологий является то, что они могут помочь нам сократить эксплуатацию и техническое обслуживание.Можно ли использовать безсерверные технологии для рендеринга на стороне сервера? Конечно, это также возможно.
При традиционном рендеринге на стороне сервера путь каждого запроса соответствует каждому маршруту на стороне сервера, а маршрут реализует рендеринг HTML-документа, соответствующего пути. Серверные программы, используемые для рендеринга, представляют собой приложения, которые интегрируют эти маршруты.
Использование Serverless для рендеринга на стороне сервера заключается в том, чтобы разбить каждый из предыдущих маршрутов на функции, а затем развернуть соответствующие функции на FaaS. Таким образом, путь, запрошенный пользователем, соответствует каждой отдельной функции. Таким образом, операции эксплуатации и обслуживания переносятся на платформу FaaS, а внешний интерфейс выполняет рендеринг на стороне сервера, поэтому нет необходимости заботиться об эксплуатации и обслуживании серверной программы.
ZEITизNext.jsОн сделал хорошую реализацию рендеринга на стороне сервера на основе Serverless. Ниже приведен простой пример.
Структура кода следующая:
.
├── next.config.js
├── now.json
├── package.json
└── pages
├── about.js
└── index.js
// next.config.js
module.exports = {
target: 'serverless'
}
вpages/about.js
а такжеpages/index.js
две страницы, вnext.config.js
Настроен для использования бессерверных служб, предоставляемых Zeit.
затем используйтеnow
С помощью этой команды код можно развернуть без сервера. Во время развертыванияpages/about.js
а такжеpages/index.js
Он преобразуется в две функции соответственно, отвечающие за отрисовку соответствующей страницы.
Разработка небольшой программы на основе serverless
В настоящее время сценарием, при котором бессерверные системы чаще используются в Китае, может быть развитие Xiaocheng. Конкретной реализацией является разработка облака апплетов.Как апплет Alipay, так и апплет WeChat предоставляют функции облачной разработки.
При традиционной разработке апплетов нам нужны фронтенд-инженеры для разработки апплета, а бэкенд-инженеры — для серверной части. Бэкенд-разработка небольших программ, по сути, такая же, как и разработка других бэкэнд-приложений.Он должен быть связан с серией операций развертывания, эксплуатации и обслуживания, таких как балансировка нагрузки приложений, резервирование резервных копий, мониторинг и оповещение. Если команда разработчиков небольшая, для реализации сервера могут также потребоваться инженеры по интерфейсу.
Однако, основываясь на облачной разработке, разработчикам нужно сосредоточиться только на реализации бизнеса, а фронтенд-инженер может выполнить интерфейсную и внутреннюю разработку всего приложения. Поскольку облачная разработка инкапсулирует серверную часть в качестве службы BaaS и предоставляет разработчикам соответствующий пакет SDK, разработчики могут использовать различные серверные службы так же, как вызов функций. Эксплуатация и обслуживание приложений также переданы поставщикам услуг, обеспечивающим облачную разработку.
Используются следующиеAlipay Девелопмент (ПОДВАЛ)Некоторыми примерами функций являются функции, определенные в службе FaaS.
Работа с базой данных
// `basement` 是一个全局变量
// 操作数据库
basement.db.collection('users')
.insertOne({
name: 'node',
age: 18,
})
.then(() => {
resolve({ success: true });
})
.catch(err => {
reject({ success: false });
});
загрузить изображение
// 上传图片
basement.file
.uploadFile(options)
.then((image) => {
this.setData({
iconUrl: image.fileUrl,
});
})
.catch(console.error);
Функции вызова
// 调用函数
basement.function
.invoke('getUserInfo')
.then((res) => {
this.setData({
user: res.result
});
})
.catch(console.error}
Общая бессерверная архитектура
Основываясь на приведенных выше примерах бессерверной разработки, можно обобщить общую бессерверную архитектуру.
Нижний уровень — это внутренний микросервис (Backend), реализующий сложный бизнес. Затем уровень FaaS реализует бизнес-логику с помощью ряда функций и предоставляет услуги непосредственно интерфейсу. Для фронтенд-разработчиков интерфейс может реализовывать логику на стороне сервера путем написания функций. Для бэкенд-разработчиков бэкенд стал более отсталым. Если бизнес относительно легкий, можно реализовать уровень FaaS, а уровень микросервисов даже не нужен.
В то же время, будь то серверная часть, FaaS или внешний интерфейс, мы можем назвать услугу BaaS, предоставляемую платформой облачных вычислений, что значительно снижает сложность и стоимость разработки. Разработка небольших облачных программ — это пример вызова услуг BaaS непосредственно во внешнем интерфейсе.
Лучшие практики бессерверной разработки
Самая большая разница между моделью бессерверной разработки и традиционной моделью разработки заключается в том, что в традиционной разработке мы основываемся на разработке приложений. После завершения разработки нам необходимо провести модульное тестирование и интегрировать приложение. На основе Serverless функции разрабатываются одна за другой, так как же нам тестировать Serverless функции? В чем разница между тестированием бессерверных функций и обычным модульным тестированием?
Еще один очень важный момент: какова производительность приложений, разработанных на основе Serverless? Как повысить производительность бессерверных приложений?
В этой главе в основном представлены передовые методы бессерверного тестирования функций и производительности функций.
функциональный тест
Хотя мы можем использовать Serverless для легкого развития бизнеса, его характеристики также создают некоторые трудности для нашего тестирования. В основном это следующие аспекты.
Бессерверные функции распределены, мы не знаем и не должны знать, на какой машине функция развернута или запущена, поэтому нам нужно провести модульное тестирование каждой функции. Бессерверные приложения состоят из набора функций, которые могут зависеть от некоторых других серверных служб (BaaS), поэтому нам также необходимо выполнить интеграционные тесты для бессерверных приложений.
Рабочие функции FaaS и BaaS также трудно эмулировать локально. Кроме того, среды FaaS, предоставляемые разными платформами, могут быть несогласованными, и SDK или интерфейсы BaaS-сервисов, предоставляемые разными платформами, также могут быть несогласованными, что не только создает некоторые проблемы для нашего тестирования, но и увеличивает стоимость миграции приложений.
Выполнение функций управляется событиями, а события, управляющие выполнением функций, трудно смоделировать локально.
Итак, как решить эти проблемы?
согласно сMike CohnПредложенныйтестовая пирамида, модульное тестирование имеет самую низкую стоимость и самую высокую эффективность; тестирование пользовательского интерфейса (интеграционное) тестирование имеет самую высокую стоимость и самую низкую эффективность, поэтому мы должны проводить как можно больше модульных тестов, чтобы сократить интеграционное тестирование. То же самое относится и к бессерверному функциональному тестированию.
Источник изображения:Martin Fowler.com/B оставить i/test P…
Чтобы упростить модульное тестирование функций, все, что нам нужно сделать, этоРазделите бизнес-логику и функциональные зависимости FaaS (например, вычисление функций) и BaaS (например, облачная база данных).. Когда FaaS и BaaS разделены, мы можем тестировать бизнес-логику функций точно так же, как при написании традиционных модульных тестов. Затем напишите интеграционные тесты, чтобы убедиться, что интеграция функций и других сервисов работает правильно.
плохой пример
Ниже приведен пример функции, реализованной с помощью Node.js. Эта функция сначала сохраняет информацию о пользователе в базе данных, а затем отправляет электронное письмо пользователю.
const db = require('db').connect();
const mailer = require('mailer');
module.exports.saveUser = (event, context, callback) => {
const user = {
email: event.email,
created_at: Date.now()
}
db.saveUser(user, function (err) {
if (err) {
callback(err);
} else {
mailer.sendWelcomeEmail(event.email);
callback();
}
});
};
В этом примере есть две основные проблемы:
- Бизнес-логика и FaaS связаны друг с другом. В основном бизнес-логика
saveUser
в этой функции иsaveUser
параметрическийevent
а такжеconent
Объект, предоставляемый платформой FaaS. - Бизнес-логика и BaaS связаны друг с другом. В частности, он используется внутри функции
db
а такжеmailer
Эти две серверные службы, от которых должна зависеть тестовая функцияdb
а такжеmailer
.
Пишите тестируемые функции
на основеРазделение бизнес-логики и функциональных зависимостей FaaS и BaaSПринцип рефакторинга приведенного выше кода.
class Users {
constructor(db, mailer) {
this.db = db;
this.mailer = mailer;
}
save(email, callback) {
const user = {
email: email,
created_at: Date.now()
}
this.db.saveUser(user, function (err) {
if (err) {
callback(err);
} else {
this.mailer.sendWelcomeEmail(email);
callback();
}
});
}
}
module.exports = Users;
const db = require('db').connect();
const mailer = require('mailer');
const Users = require('users');
let users = new Users(db, mailer);
module.exports.saveUser = (event, context, callback) => {
users.save(event.email, callback);
};
В рефакторинге кода мы поместили всю бизнес-логику вUsers
В этом классеUsers
Не зависит ни от каких внешних сервисов. При тестировании мы тоже можем не пройти в реалеdb
илиmailer
, но переходите в издевательский сервис.
Ниже представлена симуляцияmailer
пример.
// 模拟 mailer
const mailer = {
sendWelcomeEmail: (email) => {
console.log(`Send email to ${email} success!`);
},
};
Так что в самый разUsers
При адекватном модульном тестировании вы можете убедиться, что ваш бизнес-код работает должным образом.
Тогда переходи в реалdb
а такжеmailer
, Простое интеграционное тестирование, сможет ли вся функция работать должным образом.
Еще одним преимуществом рефакторинга кода является то, что он облегчает миграцию функций. Когда мы хотим перенести функции с одной платформы на другую, нам нужно только изменить параметры, предоставляемые разными платформами.Users
Можно использовать метод вызова, и нет необходимости изменять бизнес-логику.
резюме
Таким образом, при тестировании функций вам необходимо помнить о принципе пирамиды и следовать следующим принципам:
- Разделение бизнес-логики и функциональных зависимостей FaaS и BaaS
- Адекватное модульное тестирование бизнес-логики
- Интеграционное тестирование функции, чтобы убедиться, что код работает
производительность функции
При использовании Serverless для разработки еще одна проблема, которая беспокоит всех, — это производительность функции.
Для традиционных приложений после запуска наша программа находится в памяти; это не относится к бессерверным функциям.
Когда приходит событие выполнения функции драйвера, сначала нужно загрузить код, затем запустить контейнер, запустить в контейнере работающую среду и, наконец, выполнить код. Первые шаги в совокупности называются «холодным стартом». Традиционные приложения не имеют процесса холодного запуска.
Ниже представлена схематическая диаграмма жизненного цикла функции:
Источник изображения:woohoo.YouTube.com/watch?V=Oh Q F…
Продолжительность времени холодного пуска является ключевым фактором эффективности функции. Чтобы оптимизировать производительность функции, необходимо оптимизировать различные этапы жизненного цикла функции.
Влияние разных языков программирования на время холодного запуска
До этого многие тестировали влияние разных языков программирования на время холодного старта, например:
- Compare coldstart time with different languages, memory and code sizes -by Yan Cui
- Cold start / Warm start with AWS Lambda - by Erwan Alliaume
- Serverless: Cold Start War - by Mikhail Shilkov
Источник изображения:Cold start / Warm start with AWS Lambda
Из этих тестов можно сделать некоторые обобщающие выводы:
- Увеличение памяти функции может сократить время холодного запуска.
- Время запуска таких языков программирования, как C# и Java, примерно в 100 раз больше, чем у Node.js и Python.
Основываясь на приведенных выше выводах, если вы хотите, чтобы время холодного запуска Java было таким же маленьким, как у Node.js, вы можете выделить больше памяти для Java. Но больше памяти означает больше затрат.
Когда холодный запуск функции
Разработчики, которые плохо знакомы с Serverless, могут неправильно понимать, что каждый раз, когда выполняется функция, требуется холодный запуск. Не так.
При поступлении первого запроса (события, управляющего выполнением функции), после успешного запуска среды выполнения и выполнения функции среда выполнения будет зарезервирована на некоторое время для следующего выполнения функции. Это уменьшает количество холодных пусков и тем самым сокращает время работы функции. Когда запрос достигает предела одной операционной среды, платформа FaaS автоматически расширяет следующую операционную среду.
В случае AWS Lambda после выполнения функции Lambda поддерживает контекст выполнения в течение периода времени, ожидаемого для другого вызова функции Lambda. В результате сервис замораживает контекст выполнения после завершения функции Lambda и размораживает контекст для повторного использования, если AWS Lambda решит повторно использовать контекст при повторном вызове функции Lambda.
Вот два небольших теста, чтобы проиллюстрировать вышесказанное.
Я использовал вычисление функций Alibaba Cloud для реализации бессерверной функции, которая управляется событиями HTTP. Затем сделайте 100 запросов к функции с разным количеством параллелизма.
Первый - параллельный случай:
Видно, что время первого запроса составляет 302 мс, а время других запросов в основном составляет около 50 мс. В основном можно определить, что функция, соответствующая первому запросу, является холодным запуском, а все остальные 99 запросов являются горячим запуском, который непосредственно повторно использует рабочую среду первого запроса.
Далее идет случай, когда параллелизм равен 10:
Можно обнаружить, что первые 10 запросов занимают около 200 мс-300 мс, а остальные запросы занимают около 50 мс. Таким образом, можно сделать вывод, что все первые 10 одновременных запросов являются холодными запусками, и одновременно запускаются 10 операционных сред; все следующие 90 запросов являются горячими запусками.
Это также подтверждает предыдущий вывод о том, что функция не запускается каждый раз в холодном состоянии, а повторно использует предыдущую рабочую среду в течение определенного периода времени.
повторное использование контекста выполнения
Как приведенный выше вывод помогает нам улучшить производительность функции? Конечно, есть. Поскольку среда выполнения может быть сохранена, это означает, что мы можем повторно использовать контекст выполнения в среде выполнения.
Давайте посмотрим пример:
const mysql = require('mysql');
module.exports.saveUser = (event, context, callback) => {
// 初始化数据库连接
const connection = mysql.createConnection({ /* ... */ });
connection.connect();
connection.query('...');
};
Функция, реализованная в приведенном выше примере,saveUser
Функция для инициализации соединения с базой данных. Проблема в том, что каждый раз, когда функция выполняется, соединение с базой данных будет повторно инициализироваться, а соединение с базой данных является трудоемкой операцией. Очевидно, что это не очень хорошо для выполнения функции.
Теперь, когда контекст выполнения функции можно повторно использовать в течение короткого периода времени, мы можем поместить соединение с базой данных вне функции:
const mysql = require('mysql');
// 初始化数据库连接
const connection = mysql.createConnection({ /* ... */ });
connection.connect();
module.exports.saveUser = (event, context, callback) => {
connection.query('...');
};
Таким образом, соединение с базой данных будет инициализировано только при первом запуске среды выполнения. Когда последующие запросы приходят и выполняют функции, вы можете напрямую использоватьconnection
, тем самым повышая производительность последующих высоких функций.
В большинстве случаев вполне допустимо пожертвовать производительностью одного запроса в обмен на производительность большинства запросов.
Разогрейте функцию
Поскольку рабочая среда функции будет сохраняться в течение определенного периода времени, мы также можем запустить холодную среду через некоторое время, активно вызывая функцию, чтобы другие обычные запросы могли быть запущены в горячем режиме, что позволяет избежать холодного запуска. время Влияние на производительность функции.
Это самый эффективный способ на данный момент, но есть некоторые предостережения:
- Не вызывайте функцию слишком часто, по крайней мере, более 5 минут
- Функции вызова напрямую, а не косвенно через шлюзы и т. д.
- Создайте функцию, которая специально обрабатывает этот предварительный вызов вместо обычной бизнес-функции.
Это решение является только эффективным и относительно черным технологическим решением на данный момент, и его можно использовать, но если ваш бизнес позволяет «пожертвовать производительностью первого запроса в обмен на большую часть производительности», то вам не нужно использовать это решение вообще.
резюме
В общем, оптимизация производительности функции связана с оптимизацией времени холодного запуска. Все вышеперечисленные решения являются оптимизацией разработчиков, и, конечно же, в основном это оптимизация производительности платформы FaaS.
Подводя итог вышеизложенным решениям, основные моменты заключаются в следующем:
- Выберите язык программирования с коротким временем холодного старта, например Node.js/Python.
- Выделите правильную оперативную память для функции
- повторное использование контекста выполнения
- разогреть функцию
Суммировать
Как фронтенд-инженеры, мы всегда обсуждаем, каковы границы фронтенда. Текущая фронтенд-разработка уже не является предыдущей фронтенд-разработкой, фронтендом может быть не только веб-страница, но и небольшая программа, приложение, десктопная программа и даже сервер. Причина, по которой фронтенд постоянно расширяет свои границы и исследует новые области, заключается в том, что он надеется создать большую ценность. Лучше всего создавать ценность с помощью знакомых нам инструментов и привычными способами.
Рождение бессерверной архитектуры может помочь фронтенд-инженерам в максимальной степени достичь своих идеалов. С Serverless нам не нужно уделять слишком много внимания эксплуатации и обслуживанию сервера, и нам не нужно заботиться о областях, с которыми мы не знакомы. Нам нужно только сосредоточиться на развитии бизнеса и внедрении продукта. . Есть меньше вещей, о которых нам нужно заботиться, но больше вещей, которые мы можем сделать.
Serverless также внесет огромные изменения в модель фронтенд-разработки, а функции фронтенд-инженеров вернутся к функциям инженеров-приложений.
Если бы мне нужно было подытожить Serverless одним предложением, это было бы «Меньше значит больше».