首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

OpenFaaS的无状态微服务介绍

本文作者Alex将带我们了解了OpenFaaS的最新改进,也就是对无状态微服务的完整支持,并给出了一个用Ruby和Sinatra编写的留言簿示例。

目前,我们已经在OpenFaaS 0.9.0中合并并发布了对无状态微服务的支持。这意味着工程师现在可以利用OpenFaaS中简单而强大的开发人员体验,打造出管理你所有FaaS函数和微服务的单一平台。整套体验的内容从CLI到Prometheus度量,再到内置的自动扩展都包括在内。甚至缩放到零都得到了支持。本文中,我将引领大家部署一个用Ruby和Sinatra编写的留言簿示例,这个留言簿由MySQL支持,使用Kubernetes部署到OpenFaaS上。

为什么要这样做?

现代的云原生微服务和FaaS函数之间有很多重叠部分,我将在下一部分中具体说明。OpenFaaS一直支持在Windows上运行任何容器或进程,无论是FaaS函数、AWS CLI、ImageMagick甚至是PowerShell都可以。社区在短时间内提出了两个要求,这两个要求成为了我们的故事进一步发展的催化剂。

我们在Wireline.io的一位新用户提出了一项功能请求,希望增强函数的HTTP路由功能。Wireline希望编写出无需任何额外更改,就可以同时运行在AWS Lambda和OpenFaaS上的函数。大约在同一时间,GitLab的首席执行官Sid Sijbrandi联系了我们,希望了解更多关于无服务器的信息,并想知道如何在GitLab上利用它。Sid问我,OpenFaaS能否同时用来管理FaaS函数,和他的团队更熟悉的一些微服务(例如Sinatra应用)。他对在空闲时缩放到零的能力表现出了特别的兴趣。

在开始研究示例,展示如何将Sid的请求付诸实践之前,我们先来看一些背景知识。

什么是函数?

在了解什么是“无状态微服务”之前,我们先来看"FaaS函数"的定义。我在2017年1月发表的博客文章:函数即服务(FaaS)中给出了具体定义。

函数往往会:

  • 调用短期函数(Lambda有默认的1秒超时设置)
  • 不发布TCP服务——经常访问第三方服务或资源
  • 往往是临时的/事件驱动的,例如响应Webhooks
  • 应该平稳地应对流量高峰
  • 不管是什么名称,都会运行在由流动的、非确定性的基础架构支持的服务器上
  • 正常工作时会简化复杂的事物
  • 有几个相关的主题:基础架构管理、批处理、访问控制、定义、扩展和依赖关系

从第一篇文章发表以来,我拓展了自己最初的观察,将函数的定义重写为一系列属性。

函数是:

  • 无状态的
  • 短暂的
  • 自动扩展的
  • 单一用途的

函数是无状态的,因为它们不依赖内部存储器、状态机、存储的文件或挂载的卷。根据外部服务,对函数的每次调用应导致相同的最终结果。函数不必严格幂等,但在严格幂等时更易管理。

函数是短暂的,因为在任何时候都可以用相同的副本替换它们,而不会影响行为。这一属性意味着我们可以用相同的方式管理所有函数——检查函数的运行状况、查看它们的生命周期、日志记录,乃至监控工作等都可以用同一种方法来处理。

函数能自动从最小副本数扩展到最大副本数,甚至自动降到零并再次扩展上来,以匹配需求或节省资源。

函数是单一用途的,但必须以常识为准。我们用不着每次在代码中编写 function x() {} 或 def x: 时都创建一个新的FaaS函数。函数的单一用途可能是“一条员工记录的CRUD”“格式化此IBAN”或“使用机器学习模型识别此图像的内容”。

只要你编写了至少一个无服务器函数,那么你就会意识到入口点往往已经从你那里抽象出来了。你只需编写一个处理程序——然后所有依赖项都以一种通用格式表示,例如Node.js的package.json或Python的requirements.txt文件。

下面是一个Node.js函数的示例:

"use strict"

module.exports = (context, callback) => {
    callback(undefined, {status: "done"});
}

作为开发人员,你用不着了解用于引导处理程序的机制——这是无聊的重复性细节,你可以让FaaS框架或工具包来操心这些事情。 我们看到了类似的抽象模式,也看到了诸如Sinatra、Django和Express.js之类的微服务框架中隐藏无聊细节的现象。一种尺寸很少能满足所有需求,因此每种语言或运行时都有多种选择。

什么是无状态微服务?

无状态微服务是一种微服务,它可以像FaaS函数一样进行部署,并可以通过FaaS框架或OpenFaaS这样的平台来管理。因此,在OpenFaaS CLI、Gateway API或UI中不需要特殊的路由(route)、标志(flag)或过滤器(filter)。

就OpenFaaS组件而言,函数可以用任何语言编写并打包在Docker映像中。它必须通过8080端口上的HTTP提供内容,并将锁定文件写入/tmp/.lock。如果你的函数或服务检测出自身的异常,那么你可以删除锁定文件,OpenFaaS将重新启动/重新安排你的函数。

OpenFaaS有一个Ruby语言模板,可用于创建Ruby FaaS函数。Ruby无状态微服务是使用https://rubyonrails.org/](https://rubyonrails.org/">Ruby on Rails(、Sinatra或其他Ruby微服务框架创建的Ruby微服务。其中的主要区别在于,与FaaS函数相比你要做的工作更多了。现在,你必须管理自己的Dockerfile、状况检查和路由。

Sinatra是Ruby的DSL或框架,用于快速构建微服务。

下面是官方网站上的hello-world示例:

require 'sinatra'

get '/frank-says' do
  'Put this in your pipe & smoke it!'
end

如果我们将该文件另存为main.rb并运行gem install sinatra,然后运行ruby main.rb,则将在默认端口5678上启动一个Web服务器,然后可以跳转至URL:http://127.0.0.1:5678/frank-says上。

OpenFaaS CLI可以模板化、构建和部署这个微服务。然后,OpenFaaS平台将跟踪这个微服务的调用指标,并将其自动放大、缩小甚至降为零并再次放大。

创建Sinatra无状态微服务

下面我们来使用Sinatra创建一个无状态微服务。

你首先需要准备一些工具:

  • 适用于Mac/Linux/Windows的Docker
  • 一个Docker Hub帐户,或其他Docker仓库的帐户
  • OpenFaaS和CLI——可选Kubernetes或Swarm

创建一个Hello World服务

首先创建一个新文件夹并生成一个dockerfile函数。其中dockerfile模板会告诉OpenFaaS CLI,在不应用其他任何脚手架或模板的情况下运行Docker构建,你必须提供自己的Dockerfile。

$ mkdir -p sinatra-for-openfaas/ \
  && cd sinatra-for-openfaas/

$ faas-cli new --prefix=alexellis2 --lang dockerfile frank-says

用你的Docker Hub帐户或另一个Docker仓库替换alexellis2。一个Docker映像将被推送到这里,这是build/faas-cli up命令的一部分。

这将创建两个文件,就像你用faas-cli new上列出的一种语言创建函数时一样:

./frank-says/Dockerfile
./frank-says.yml

创建一个Gemfile和main.rb文件: ./frank-says/main.rb:

require 'sinatra'

set :port, 8080
set :bind, '0.0.0.0'

open('/tmp/.lock', 'w') { |f|
  f.puts "Service started"
}

get '/' do
  'Frank has entered the building'
end

get '/logout' do
  'Frank has left the building'
end

有关OpenFaaS负载的注意事项:

  • 它们必须绑定到TCP端口8080
  • 准备接收流量时,它们必须写一个文件/tmp/.lock。

./frank-says/Gemfile:

source 'https://rubygems.org'
gem "sinatra"

可以在此文件中添加任意gems列表。 现在将./frank-says/Dockerfile替换为:

FROM ruby:2.4-alpine3.6
WORKDIR /home/app
COPY    .   .
RUN bundle install
RUN addgroup -S app \
  && adduser app -S -G app
RUN chown app:app -R /home/app
WORKDIR /home/app

HEALTHCHECK --interval=5s CMD [ -e /tmp/.lock ] || exit 1

USER app
CMD ["ruby", "main.rb"]

Dockerfile执行以下操作:

  • 添加非root用户
  • 添加Ruby源代码和Gemfile,然后安装sinatra gem
  • 添加一个间隔为5秒的健康检查
  • 设置启动命令

部署示例

现在你已经做好了准备,可以使用OpenFaaS CLI构建和部署示例了。

  • 使用你的帐户详细信息登录
$ docker login
  • 运行up命令,该命令是build、push和deploy的别名。
$ faas-cli up --yaml frank-says.yml

Deploying: frank-says.

Deployed. 200 OK.
URL: http://127.0.0.1:8080/function/frank-says

使用curl调用你的微服务,或在Web浏览器中查看它:

$ curl http://127.0.0.1:8080/function/frank-says/
Frank has entered the building.

你也可以尝试自定义路径:

$ curl http://127.0.0.1:8080/function/frank-says/logout
Frank has left the building.

你可以尝试更新消息或添加其他路由,然后再次运行faas-cli以重新部署微服务。 现在检查faas-cli list,能看到每次访问微服务时调用计数会随之增加。

$ faas-cli list
Function                        Invocations     Replicas
frank-says                      5               1

触发自动扩展

现在,我们可以使用简单的bash for循环来触发自动扩展:

$ for i in {1..10000}
do
  sleep 0.01 \
  && curl http://127.0.0.1:8080/function/frank-says \
  && echo
done

在另一个窗口中输入:watch faas-cli list或者定期运行faas-cli list 。自动扩展生效后,你应该能看到Invocations的值增加,并且Replicas值也会增加。

Function                        Invocations     Replicas
frank-says                      702             4

当bash for循环完成或使用Ctrl + C取消它时,你会看到副本数减少到1。 你也可以在以下网址使用OpenFaaS UI监视和调用微服务:http://127.0.0.1:8080

阅读有关自动扩展的更多信息,包括如何配置最小、最大和零副本缩放参数

部署带有MySQL的Sinatra留言簿

$ git clone https://github.com/openfaas-incubator/openfaas-sinatra-guestbook \
  && cd openfaas-sinatra-guestbook

在./sql.yml中配置你的MySQL数据库细节。如果你还没有MySQL,那么只需花几分钟使用Kubernetes上的helm或docker run,以及官方Docker映像就能部署完毕。

$ cp sql.example.yml sql.yml

最后部署留言簿:

$ faas-cli up

http://127.0.0.1:8080/function/guestbook

使用上面命令提供的URL来访问微服务。 在UI中登录留言簿,完成后,你可以随时发布到/function/guestbook/reset来重置MySQL表。

留言簿代码的状态存储在MySQL表单中,这意味着它可以随时重新启动而不会丢失数据。这是FaaS函数和无状态微服务的一个关键属性。如果OpenFaaS添加了我们代码的其他副本——每个副本都将具有相同的环境视图,因为它依赖于外部数据库来获取其数据。

启用零缩放

要启用缩放到零的功能,只需按照文档说明启用faas-idler。

然后在你的stack.yml文件中添加一个标签,以告知OpenFaaS你的函数可以进行零缩放:

    labels:
      com.openfaas.scale.zero: true

最后,通过faas-cli up重新部署留言簿。一旦检测到空闲状态,faas-idler现在会将你的函数缩放到零副本。默认的空闲时间设置为5分钟,可以在部署时配置。 回到Sid最初的问题,我们已经部署了一个用Ruby编写的无状态微服务,该服务将在空闲时缩放到零,还能及时扩展以服务流量。管理它的方式与我们现有的FaaS函数完全相同,这意味着你可以专注于构建重要的内容,而不必操心Kubernetes或Docker Swarm的内部细节。

总结

现在,我们已经使用MySQL、ebs视图、Bootstrap和Sinatra部署了一个简单的hello-world Sinatra服务和一个更完整的留言簿示例。接下来你就可以开始使用OpenFaaS简化开发人员工作流程了——你可以使用FaaS函数,或者简化微服务的管理工作。

作者介绍: Alex Ellis(alex@openfaas.com)是@openfaas的创始人。

原文链接https://www.openfaas.com/blog/stateless-microservices/

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/KLwjOKWLEfgqytd6DNzz
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券