AWS Elastic Beanstalk
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

将具有集群功能的 Express 应用程序部署到 Elastic Beanstalk

本教程向您演示了如何使用 Elastic Beanstalk 命令行界面 (EB CLI) 将示例应用程序部署到 Elastic Beanstalk,然后更新该应用程序以使用 Express 框架、Amazon ElastiCache 和集群功能。集群功能增强了 Web 应用程序的高可用性、性能和安全性。要了解有关 Amazon ElastiCache 的更多信息,请转到 Amazon ElastiCache for Memcached User Guide中的什么是 Amazon ElastiCache for Memcached?

注意

本示例将创建 AWS 资源,您可能要为其付费。有关 AWS 定价的更多信息,请参阅 http://www.amazonaws.cn/pricing/。某些服务是 AWS 免费使用套餐的一部分。如果您是新客户,则可免费试用这些服务。参阅 http://www.amazonaws.cn/free/ 了解更多信息。

先决条件

本教程要求使用 Node.js 语言、其程序包管理器 NPM 以及 Express Web 应用程序框架。有关安装这些组件和设置本地开发环境的详细信息,请参阅 设置 Node.js 开发环境

注意

在本教程中,您不需要安装适用于 Node.js 的 AWS,这在 设置 Node.js 开发环境 中也有提到。

本教程还需要 Elastic Beanstalk 命令行界面 (EB CLI)。有关安装和配置 EB CLI 的详细说明,请参阅使用安装脚本安装 EB CLI配置 EB CLI

创建 Elastic Beanstalk 环境

为您的应用程序配置 EB CLI 存储库,并创建运行 Node.js 平台的 Elastic Beanstalk 环境。

  1. 使用 eb init 命令创建存储库。

    ~/node-express$ eb init --platform node.js --region us-west-2 Application node-express has been created.

    此命令在名为 .elasticbeanstalk 的文件夹中创建配置文件,该配置文件指定用于为您的应用程序创建环境的设置;并创建以当前文件夹命名的 Elastic Beanstalk 应用程序。

  2. 使用 eb create 命令创建运行示例应用程序的环境。

    ~/node-express$ eb create --sample node-express-env

    此命令使用 Node.js 平台的默认设置以及以下资源来创建负载均衡环境:

    • EC2 实例 – 配置来在您选择的平台上运行 Web 应用程序的 Amazon Elastic Compute Cloud (Amazon EC2) 虚拟机。

      各平台运行一组特定软件、配置文件和脚本以支持特定的语言版本、框架、Web 容器或其组合。大多数平台使用 Apache 或 nginx 作为 Web 应用程序前的反向代理,向其转发请求、提供静态资产以及生成访问和错误日志。

    • 实例安全组 – 配置 Amazon EC2 安全组以允许端口 80 上的入站流量。通过此资源,HTTP 流量可以从负载均衡器到达运行您的 Web 应用程序的 EC2 实例。默认情况下,其他端口不允许流量进入。

    • 负载均衡器 – 配置来向运行您的应用程序的实例分配请求的 Elastic Load Balancing 负载均衡器。负载均衡器还使您无需将实例直接公开在 Internet 上。

    • 负载均衡器安全组 – 配置 Amazon EC2 安全组以允许端口 80 上的入站流量。利用此资源,HTTP 流量可从 Internet 到达负载均衡器。默认情况下,其他端口不允许流量进入。

    • Auto Scaling 组 – 配置来在实例终止或不可用时替换实例的 Auto Scaling 组。

    • Amazon S3 存储桶 – 使用 Elastic Beanstalk 时创建的源代码、日志和其他项目的存储位置。

    • Amazon CloudWatch 警报 – 用于监控环境中的实例负载的两个 CloudWatch 警报,在负载过高或过低时触发。警报触发后,您的 Auto Scaling 组会扩展或收缩进行响应。

    • AWS CloudFormation 堆栈 – Elastic Beanstalk 使用 AWS CloudFormation 启动您的环境中的资源并传播配置更改。这些资源在您可通过 AWS CloudFormation 控制台查看的模板中定义。

    • 域名 – 一个域名,它以下面的形式路由到您的 Web 应用程序:subdomain.region.elasticbeanstalk.com

  3. 当环境创建完成后,使用 eb open 命令在默认浏览器中打开环境 URL。

    ~/node-express$ eb open

更新应用程序

更新 Elastic Beanstalk 环境中的示例应用程序以使用 Express 框架。

注意

先决条件开发环境设置可实现 node-express 文件夹中的 Express 项目结构。如果尚未生成 Express 项目,请运行以下命令。有关更多信息,请参阅安装 Express

~/node-express$ express && npm install

更新您的应用程序以使用 Express

  1. node-express/app.js 重命名为 node-express/express-app.js.

    node-express$ mv app.js express-app.js
  2. node-express/express-app.js 中的行 var app = express(); 更新为以下内容:

    var app = module.exports = express();
  3. 在本地计算机上,使用以下代码创建一个名为 node-express/app.js 的文件。

    var cluster = require('cluster'), app = require('./express-app'); var workers = {}, count = require('os').cpus().length; function spawn(){ var worker = cluster.fork(); workers[worker.pid] = worker; return worker; } if (cluster.isMaster) { for (var i = 0; i < count; i++) { spawn(); } cluster.on('death', function(worker) { console.log('worker ' + worker.pid + ' died. spawning a new process...'); delete workers[worker.pid]; spawn(); }); } else { app.listen(process.env.PORT || 5000); }
  4. 部署更新的应用程序。

    node-express$ eb deploy
  5. 您的环境将在几分钟后进行更新。在环境变为绿色并准备就绪后,刷新 URL 以验证环境是否工作。您应看到一个显示“欢迎使用 Express”的网页。

您可访问运行应用程序的 EC2 实例的日志。有关访问日志的说明,请参阅从 Elastic Beanstalk 环境中的 Amazon EC2 实例查看日志

接下来,让我们更新 Express 应用程序以使用 Amazon ElastiCache。

更新 Express 应用程序以使用 Amazon ElastiCache

  1. 在本地计算机上的源包顶级目录中,创建 .ebextensions 目录。在此示例中,我们使用的是 node-express/.ebextensions.

  2. 使用以下代码段创建配置文件 node-express/.ebextensions/elasticache-iam-with-script.config。有关配置文件的更多信息,请参阅Node.js 配置命名空间。此配置文件会创建一个 IAM 用户(该用户拥有发现 ElastiCache 节点所需的权限),只要缓存发生变化就向某个文件写入数据。您也可以从 https://elasticbeanstalk-samples-us-east-2.s3.amazonaws.com/nodejs-example-express-elasticache.zip 复制文件。有关 ElastiCache 属性的更多信息,请参阅“代码段示例:ElastiCache”。

    注意

    YAML 依赖一致的缩进。当替换示例配置文件中的内容时,应匹配缩进级别,并且确保您的文本编辑器使用空格而不是字符来进行缩进。

    Resources: MyCacheSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: "Lock cache down to webserver access only" SecurityGroupIngress: - IpProtocol: tcp FromPort: Fn::GetOptionSetting: OptionName: CachePort DefaultValue: 11211 ToPort: Fn::GetOptionSetting: OptionName: CachePort DefaultValue: 11211 SourceSecurityGroupName: Ref: AWSEBSecurityGroup MyElastiCache: Type: 'AWS::ElastiCache::CacheCluster' Properties: CacheNodeType: Fn::GetOptionSetting: OptionName: CacheNodeType DefaultValue: cache.t2.micro NumCacheNodes: Fn::GetOptionSetting: OptionName: NumCacheNodes DefaultValue: 1 Engine: Fn::GetOptionSetting: OptionName: Engine DefaultValue: redis VpcSecurityGroupIds: - Fn::GetAtt: - MyCacheSecurityGroup - GroupId AWSEBAutoScalingGroup : Metadata : ElastiCacheConfig : CacheName : Ref : MyElastiCache CacheSize : Fn::GetOptionSetting: OptionName : NumCacheNodes DefaultValue: 1 WebServerUser : Type : AWS::IAM::User Properties : Path : "/" Policies: - PolicyName: root PolicyDocument : Statement : - Effect : Allow Action : - cloudformation:DescribeStackResource - cloudformation:ListStackResources - elasticache:DescribeCacheClusters Resource : "*" WebServerKeys : Type : AWS::IAM::AccessKey Properties : UserName : Ref: WebServerUser Outputs: WebsiteURL: Description: sample output only here to show inline string function parsing Value: | http://`{ "Fn::GetAtt" : [ "AWSEBLoadBalancer", "DNSName" ] }` MyElastiCacheName: Description: Name of the elasticache Value: Ref : MyElastiCache NumCacheNodes: Description: Number of cache nodes in MyElastiCache Value: Fn::GetOptionSetting: OptionName : NumCacheNodes DefaultValue: 1 files: "/etc/cfn/cfn-credentials" : content : | AWSAccessKeyId=`{ "Ref" : "WebServerKeys" }` AWSSecretKey=`{ "Fn::GetAtt" : ["WebServerKeys", "SecretAccessKey"] }` mode : "000400" owner : root group : root "/etc/cfn/get-cache-nodes" : content : | # Define environment variables for command line tools export AWS_ELASTICACHE_HOME="/home/ec2-user/elasticache/$(ls /home/ec2-user/elasticache/)" export AWS_CLOUDFORMATION_HOME=/opt/aws/apitools/cfn export PATH=$AWS_CLOUDFORMATION_HOME/bin:$AWS_ELASTICACHE_HOME/bin:$PATH export AWS_CREDENTIAL_FILE=/etc/cfn/cfn-credentials export JAVA_HOME=/usr/lib/jvm/jre # Grab the Cache node names and configure the PHP page aws cloudformation list-stack-resources --stack `{ "Ref" : "AWS::StackName" }` --region `{ "Ref" : "AWS::Region" }` --output text | grep MyElastiCache | awk '{print $4}' | xargs -I {} aws elasticache describe-cache-clusters --cache-cluster-id {} --region `{ "Ref" : "AWS::Region" }` --show-cache-node-info --output text | grep '^ENDPOINT' | awk '{print $2 ":" $3}' > `{ "Fn::GetOptionSetting" : { "OptionName" : "NodeListPath", "DefaultValue" : "/var/www/html/nodelist" } }` mode : "000500" owner : root group : root "/etc/cfn/hooks.d/cfn-cache-change.conf" : "content": | [cfn-cache-size-change] triggers=post.update path=Resources.AWSEBAutoScalingGroup.Metadata.ElastiCacheConfig action=/etc/cfn/get-cache-nodes runas=root sources : "/home/ec2-user/elasticache" : "https://elasticache-downloads.s3.amazonaws.com/AmazonElastiCacheCli-latest.zip" commands: make-elasticache-executable: command: chmod -R ugo+x /home/ec2-user/elasticache/*/bin/* packages : "yum" : "aws-apitools-cfn" : [] container_commands: initial_cache_nodes: command: /etc/cfn/get-cache-nodes
  3. 在本地计算机上,使用以下代码段创建配置文件 node-express/.ebextensions/elasticache_settings.config 以配置 ElastiCache。

    option_settings: "aws:elasticbeanstalk:customoption": CacheNodeType: cache.t2.micro NumCacheNodes: 1 Engine: memcached NodeListPath: /var/nodelist
  4. 在本地计算机上,使用以下代码段替换 node-express/express-app.js。此文件会从磁盘读取节点列表 (/var/nodelist) 并配置 Express,以便在节点存在的情况下将 memcached 用作会话存储。您的文件应类似以下内容。

    /** * Module dependencies. */ var express = require('express'), session = require('express-session'), bodyParser = require('body-parser'), methodOverride = require('method-override'), cookieParser = require('cookie-parser'), fs = require('fs'), filename = '/var/nodelist', app = module.exports = express(); var MemcachedStore = require('connect-memcached')(session); function setup(cacheNodes) { app.use(bodyParser.raw()); app.use(methodOverride()); if (cacheNodes) { app.use(cookieParser()); console.log('Using memcached store nodes:'); console.log(cacheNodes); app.use(session({ secret: 'your secret here', resave: false, saveUninitialized: false, store: new MemcachedStore({'hosts': cacheNodes}) })); } else { console.log('Not using memcached store.'); app.use(cookieParser('your secret here')); app.use(session()); } app.get('/', function(req, resp){ if (req.session.views) { req.session.views++ resp.setHeader('Content-Type', 'text/html') resp.write('Views: ' + req.session.views) resp.end() } else { req.session.views = 1 resp.end('Refresh the page!') } }); if (!module.parent) { console.log('Running express without cluster.'); app.listen(process.env.PORT || 5000); } } // Load elasticache configuration. fs.readFile(filename, 'UTF8', function(err, data) { if (err) throw err; var cacheNodes = []; if (data) { var lines = data.split('\n'); for (var i = 0 ; i < lines.length ; i++) { if (lines[i].length > 0) { cacheNodes.push(lines[i]); } } } setup(cacheNodes); });
  5. 在本地计算机上,更新 node-express/package.json 以添加四个依赖项。

    { "name": "node-express", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "cookie-parser": "*", "debug": "~2.6.9", "express": "~4.16.0", "http-errors": "~1.6.2", "jade": "~1.11.0", "morgan": "~1.9.0", "connect-memcached": "*", "express-session": "*", "body-parser": "*", "method-override": "*" } }
  6. 部署更新的应用程序。

    node-express$ eb deploy
  7. 您的环境将在几分钟后进行更新。在环境变为绿色并准备就绪后,验证代码是否正常。

    1. 检查 Amazon CloudWatch 控制台以查看 ElastiCache 指标。要查看 ElastiCache 指标,请在左侧窗格中选择指标,然后搜索当前项目数。选择 ElastiCache > 缓存节点指标,然后选择缓存节点以查看缓存中的项目数。

      注意

      确保您查看的是您的应用程序所部署到的相同地区。

      如果您复制您的应用程序 URL 并将其粘贴到其他 Web 浏览器中,则在刷新页面之后,您应看到您的当前项目数在 5 分钟后上升。

    2. 制作日志的快照。有关检索日志的更多信息,请参阅从 Elastic Beanstalk 环境中的 Amazon EC2 实例查看日志

    3. 检查日志文件包中的文件 /var/log/nodejs/nodejs.log。您应看到类似如下所示的内容:

      Using memcached store nodes: [ 'aws-my-1oys9co8zt1uo.1iwtrn.0001.use1.cache.amazonaws.com.cn:11211' ]

清除

如果不再希望运行您的应用程序,您可通过终止环境并删除应用程序进行清除。

请使用 eb terminate 命令终止环境并使用 eb delete 命令删除应用程序。

终止环境

从您在其中创建本地存储库的目录中,运行 eb terminate

$ eb terminate

此过程可能耗时数分钟。成功终止环境后,Elastic Beanstalk 会立即显示一条消息。