在本系列中,我们将构建一个基于NodeJS微服务,并使用Docker Swarm集群进行部署。
以下是我们要使用的工具:
您提前应拥有的知识:
微服务是一个独立的单元,与其他许多单元一起构成一个大型应用程序。通过将您的应用分成小单元,它的每个部分都可独立部署和扩展,可以由不同的团队和不同的编程语言编写,并且可以单独进行测试。- Max Stoiber 微服务架构意味着您的应用程序由许多较小的独立应用程序组成,这些应用程序能够在自己的内存空间中运行,并在许多独立机器上彼此独立地进行扩展。- Eric Elliot
微电影服务示例
假设我们正在Cinépolis(一家墨西哥电影院)的IT部门工作,他们让我们把他们的门票和超市从一个单一的系统重组为一个微服务。
因此,对于“构建NodeJS微电影院服务”系列的第一部分,我们将只关注电影目录服务。
在这个架构中,我们看到我们有三种不同的使用微服务的设备,POS(销售点),手机/平板和计算机。
POS和移动/平板电脑安装了应用程序来运行微服务(以电子方式),计算机通过网络应用程序访问微服务(Web应用程序也被一些人认为也是微服务)。
好吧,让我们模拟一下如何在最喜爱的电影院预订电影首映票。
首先,我们想看看电影院目前有哪些电影可看。下图向我们展示了如何成为通过REST与微服务进行通讯。
我们的电影服务API将会遵循这样的规格:
如果你不知道什么是RAML,你可以查看这个教程
API项目的结构如下所示:
- api/ # api
- config/ # app配置文件
- mock/ # 数据示例(非必须)
- repository/ # 数据库概念模式
- server/ # 服务端代码
- package.json # 依赖文件
- index.js # app入口文件
让我们开始吧。首先看看对数据库进行查询的地方repository
。
正如你注意到的,我们暴露唯一的一个 connection
对象来作为连接的实例,“闭包”使得每个函数都可以获得db
对象和collection
对象。db
对象保持着数据库的连接。
这里我们抽象出我们连接的数据库的类型,数据库对象不知道数据库是何种类型(本文使用的是MongDB),即它不必知道它是单个数据库还是一个数据库副本集连接。尽管我们使用的是mongodb语法,但我们可以通过应用依赖倒置原则来抽象数据库功能,从mongo语法到转为其他的语法,通过调用数据库操作的接口(例如使用猫鼬模型)。
有一个测试这个模块的文件,我稍后会在文章中讨论,但是如果需要使用它,你可以在github repo branch step-1上找到它。repository/repository.spec.js
我们要看的下一个文件是server.js。
在这里,我们实例化一个express程序,验证我们是否提供存储库和服务器端口对象,然后我们将一些中间件应用到我们的应用程序,例如日志记录(morgan),安全性(helmet)和错误处理(error handling),最后我们导出主函数以启动服务器😎。
Helmet包含11个软件包,一些著名的对Web攻击有XSS跨站脚本, 脚本注入 clickjacking 以及各种非安全的请求等对Node.js的Web应用构成各种威胁,使用Helmet能帮助你的应用避免这些攻击。
如果你想固化微服务,你可以查看这篇文章。
因为我们的服务器正在使用我们的movieAPI,让我们继续查看 movies.js
我们在这里做的是为我们的API创建routes,并根据所侦听的route调用我们的repo函数,我们的repo在这里使用接口技术,在这里我们使用著名的“编码接口而不是实现“,因为route不知道是否有数据库对象,数据库查询逻辑等,它只调用处理所有数据库问题的回调函数。
我们所有的源码都有单元测试,让我们看看测试movies.js的结果 。
您可以将测试视为您正在构建的应用程序的保障。他们不仅可以在本地机器上运行,还可以在CI服务上运行,失败的版本不会被推送到生产系统。- RisingStack
要编写单元测试,所有的依赖关系都必须存在,这意味着我们假设依赖关系是完整的。让我们看看情况如何spec files.
正如您所看到的,我们正在为该服务器和服务器上的movies API
依赖项进行存根操作,并验证是否需要提供服务器端口和存储库对象。
您可以检查github repo中的所有测试文件。
让我们继续创建db connection
对象,现在定义每个微服务都有它自己的数据库,但对于我们的例子,我们将使用mongoDB副本集服务器,如果你现在不知道如何配置mongoDB replset服务器,你可以查阅这篇文章以获得更深入的理解。
这里是我们需要从NodeJS连接到MongoDB数据库的配置。
有其他的方式实现,但我们通过副本集连接到mongoDB。
正如你所看到的,我们正在传递一个options
对象,它拥有mongo连接所需的所有参数,当我们通过身份验证过程时它将传递event-mediator
对象。
注意*这里我使用的是一个event-emit对象,由于某种原因,一旦它通过身份验证时它不会返回数据库对象,那么程序将会出错。
现在,因为我们传递了一个参数的对象,所以下一个要查看的文件是optionsconfig.js。
这是我们的配置文件,大多数配置代码都是硬编码的,但正如你可以看到一些属性使用环境变量作为选项。环境变量被认为是最佳实践,因为这可以隐藏数据库凭证,服务器参数等。
最后编码API的最后一步是把所有东西放在index.js。
在这里,我们编写所有的电影API服务,含有有一些错误处理,然后我们加载配置,启动存储库并最终启动服务器。
所以到现在为止,我们已经完成了API开发所涉及的所有事情,您可以查看step-1分支处的repo 。
如果你转到github,你会看到有一些命令:
npm install # 安装node依赖
npm test # 单元测试
npm start # 启动服务
npm run node-debu # 调试模式启动
npm run chrome-debug # chromedebug模式启动
npm run lint # npm脚本
最后,得到了我们的第一个微服务,但不适用npm start命令启动,而是使用Docker。
现在是时候把它放在一个Docker容器中,就像我们在文章的标题中提到它一样。
首先我们要做的的是,从“用docker创建mongoDB副本集”的文章中有Docker环境,如果你没有,你将不得不做一些额外的修改步骤来设置一个数据库到我们的微服务,这里有些命令只是为了测试目的我们的电影服务。
所以首先让我们创建我们的Dockerfile来对我们的NodeJS微服务进行docker化。
# Node v7 as the base image to support ES6
FROM node:7.2.0
# Create a new user to our new container and avoid the root user
RUN useradd --user-group --create-home --shell /bin/false nupp && \
apt-get clean
ENV HOME=/home/nupp
COPY package.json npm-shrinkwrap.json $HOME/app/
COPY src/ $HOME/app/src
RUN chown -R nupp:nupp $HOME/* /usr/local/
WORKDIR $HOME/app
RUN npm cache clean && \
npm install --silent --progress=false --production
RUN chown -R nupp:nupp $HOME/*
USER nupp
EXPOSE 3000
CMD ["npm", "start"]
我们将NodeJS镜像作为Docker镜像的基础,然后创建一个用户来避免非root用户,然后将src复制到我们的镜像中,然后安装依赖,公开一个数字端口,最后实例化我们的电影服务。
接下来,我们必须使用以下命令来构建我们的Docker镜像:
$ docker build -t movies-service .
我们先看看构建命令。
docker build
我们想要去创建新的镜像。-t movies-service
用标签标记此镜像。我们可以从现在开始通过标记来引用镜像。.
使用当前目录进行dockerfile查找。在一些控制台输出后,我们用我们的NodeJS应用程序创建了我们的新镜像,所以现在我们需要做的是使用以下命令来运行我们的图像:
$ docker run --name movie-service -p 3000:3000 -e DB_SERVERS="192.168.99.100:27017 192.168.99.101:27017 192.168.99.100:27017" -d movies-service
在上面的命令中,我们传递了一个env变量,它是一个需要连接到mongoDB replset的服务器参数数组。这仅仅是一个例子,有更好的方法来做到这一点,比如读取一个env文件。
现在我们已经启动了容器,让我们检索我们的微服务IP,并且我们准备对我们的微服务进行集成测试,另一个测试选项是JMeter,它是模拟http请求的好工具。JMeter教程。
这是我的integration-test
集成API测试调用:D。
我们所做的…
我们只做了这个通信流程的第一部分,我们制作了电影服务来查询电影首映,我们在NodeJS中构建了电影服务API,首先我们用RAML规范设计api,然后开始构建我们的API,并进行相应的单元测试,最后我们编写其余部分以使我们的微服务完整,并能够启动我们的电影服务。
然后,我们将我们的微服务放入Docker容器中,以便能够进行一些集成测试。
我们在NodeJs中学到了许多,但这只是开始而已。我希望这个东西可以在您使用Docker和NodeJS时帮助你。
这篇文章是“ 构建NodeJS电影微服务并使用docker部署 ”系列的第一部分。