将您的 Linux 应用程序迁移到 Amazon 云,第 3 部分: 实现可扩展性

简单地实现更大流量支持

Sean A. Walberg, 高级网络工程师
从 1994 开始,Sean Walberg 就一直在学术、企业和 Internet 服务供应者环境中从事 Linux 和 UNIX 系统的研究。在过去几年里,他撰写了大量有关系统管理的文章。

 

简介: 如果是连续阅读 本系列文章 至本文,您就知道我们已经将示例 Linux® 应用程序移植到云中了,此外我们还配置了一些基本的可靠性特性。本文是关于将应用程序移植到 Amazon 云中的系列文章的第 3 篇,是时候利用云的动态性的优势了,通过增加或减少基础架构来将静态资产加载和部署到云边界。

查看本系列更多内容

<!-- <p class="ibm-no-print"> <div id="dw-tag-this" class="ibm-no-print"></div> <div id="interestShow" class="ibm-no-print"></div> </p> -->

 

发布日期: 2010 年 10 月 25 日
级别: 中级 其他语言版本: 英文
访问情况 8240 次浏览
建议: 0 (添加评论) <!-- Rating_Area_Begin --><!-- Ensure that div id is based on input id and ends with -widget -->

1 star 2 stars 3 stars 4 stars 5 stars 平均分 (共 3 个评分 )
<script type="text/javascript"></script><!-- Rating_Area_End -->

 

<!-- dW_Summary_Area_END --><!-- CONTENT_BODY -->
<!-- MAIN_COLUMN_BEGIN -->
<!-- Related_Searches_Area_And_Overlays_Begin --><!-- MAIN_COLUMN_CONTAINER_BEGIN -->
<!-- MAIN_COLUMN_CONTENT_BEGIN -->

本系列文章的 将您的 Linux 应用程序迁移到 Amazon 云,第 1 部分:初始迁移 首先介绍了名为 SmallPayroll.ca 的软件即服务(Software as a Service)。这个应用程序被移植到 Amazon Elastic Compute Cloud (Amazon EC2)。然后,在 将您的应用移植到 Amazon 云,第 2 部分:提高应用的可靠性 中,我们通过增加冗余、备份和更可靠磁盘使这个应用程序变得更加健壮。

现在,我们是时候考虑稳定性之外的可扩展性。因为服务器是按小时租赁的,只在需要时才运行额外的服务器会有意义吗?异步处理作业呢?

内容分布式网络(CDN)将静态资产缓存到网络边缘,这在过去是非常昂贵的。即使非常小的网站也可以使用云计算创建的 CDN。使用 CDN 可以大大提升性能,所以让我们先实现这一步。

自动部署

实现动态扩展基础架构的一个关键原因是新实例可以在不需要人工干预的前提下部署到生产环境。在每一次修改后均不间断地重新绑定一个 Amazon Machine Instance (AMI) 都是可以实现的,如部署代码或修改数据库。然而,使用一些脚本就可以使服务器直接进行自动部署。

SmallPayroll.ca 的部署过程类似于其他的应用程序:

  1. 从知识库获取代码,如 Subversion 或 git。
  2. 启动应用程序服务器。
  3. 验证应用程序已正确启动。
  4. 将新的服务器添加到负载均衡池。

这个实例还必须在 /etc/hosts 上配置一个数据库服务器。

从知识库获取代码

SmallPayroll.ca 代码库是存储在一个 Subversion 知识库中的。Subversion 是一个源代码控制系统,它可以跟踪代码库的修改,允许开发人员创建新分支和在单独环境中合并特性开发代码。

最简单的情况是,一个 Rails 应用程序正好可以运行源代码的检出副本。修改后,生产服务器会执行一个更新,然后重新启动。名为 Capistrano 的 Ruby Gem 以一种支持集中控制多个服务器的方式来管理这些部署,而且如果发生问题,这种方式很容易回滚。

新的服务器可以引导 Capistrano 过程启动,而不需要手动检出代码。这需要事先做更多的操作,但是它意味着 Capistrano 之后可以更快速简单地管理这个服务器。清单 1 显示了 Capfile 的初始内容,这个文件位于购买产品用户的 home 目录下。


清单 1. 引导启动 Capistrano 部署的 Capfile
				
load 'deploy' 

# Where is the code? This will need to be customized!
set :repository,  "http://svn.smallpayroll.ca/svn/payroll/trunk/"
set :scm_username, "DEPLOY_USERNAME"
set :scm_password, "DEPLOY_PASSWORD"

# Deploy to the local server
server "localhost", :app, :web, :db, :primary => true

# By default Capistrano tries to do some things as root through sudo - disable this
set :use_sudo, false

# Define where everything goes
set :home, '/home/payroll'
set :deploy_to, "#{home}"
set :rails_env, "production"

这个 Capfile 是通过 cap 命令执行的。Capistrano 要求使用 Secure Shell (SSH) 连接一个服务器,即使在本地主机上也是一样。清单 2 是作为应用程序用户运行的,准备好了服务器,这样用程序用户就可以使用 SSH 连接到本地服务器,然后 Capistrano 任务就可以运行。


清单 2. 准备环境
				
# Create the SSH directory and generate a secure key pair
mkdir .ssh
chmod 700 .ssh
ssh-keygen -b 1024 -t dsa -q -f .ssh/id_dsa -N ""

# Allow the user to SSH in to the server without a password
cat .ssh/id_dsa.pub >> .ssh/authorized_keys
# SSH is very fussy about permissions! Nothing should be readable
# by other users
chmod 600 .ssh/*

# SSH in once, ignoring host keys, so that the server will save the host key
ssh 127.0.0.1 -o StrictHostKeyChecking=false /bin/false

清单 2 分为以下 3 部分:

  • 前两个命令会创建一个 SSH 目录,它只允许应用程序用户读取。第三个命令创建了一个 1024 位的 Digital Signature Algorithm (DSA) 密钥(-b 1024 -t dsa),关闭输出(-q),指定密钥的名称,在这里不指定密码。
  • 将用户的公钥复制到 authorized_keys 文件,这允许用户使用相应的密钥登录,而不需要使用密码。同时要保证其他人无法读取这个目录的文件。
  • 如果不保存主机密钥,SSH 和 Capistrano 会提示验证密钥,这会中断自动化部署过程。最后一个命令是忽略主机密钥而登录到本地服务器,然后运行 /bin/false。这样就可以保存主机密钥。

这个过程的最后一步是创建环境,并部署应用程序当前版本。清单 3 说明了如何使用 Capistrano 处理这些任务。


清单 3. 使用 Capistrano 部署应用程序
				
cap deploy:setup
chmod 700 /home/payroll
cap deploy

清单 3 运行了 deploy:setup 任务,它会在应用程序的 home 目录下创建出目录结构,这个目录结构由名为 shared 和 releases 的目录构成。每一个部署在 releases 文件夹下有自己的一个目录。而 shared 目录是用于保存日志和其他可能在各个部署间共享的元素。

在部署这个应用程序之前,第二个命令会将 home 目录的权限修改为 700。如果安装程序开放这个部署目录的权限,允许组成员写入,那么这个部件会被部署到 home 目录,而不是它的子目录。如果除应用程序用户以外还有人能够修改 home 目录,那么 SSH 守护进程就不支持基于密钥的认证。

最后运行的是 deploy 任务,它会从 Subversion 检出代码,并将代码保存到 release 目录,然后创建一个名为 current 的符号链接(symlink)。有了这个符号链接及每一个位于单独目录的部署,应用程序就可以轻松回滚到之前的版本。


自动启动应用程序服务器

即使我们能够创建一个在负载增大时会自动增加更多 Web 服务器的系统,但是这并不总是一个好的做法。Web 流量的波动是非常大的,所以您可能希望保证流量在启动另一个服务器之前停下来。您大约需要 10 分钟才能确定所遇到的负载是否需要一个新服务器,然后还需要在 5 到 10 分钟后才能启动一个实例,从而在池中创建一个新的 Web 服务器。这个过程可能对于 Web 服务器不可行的,但是它对于工作服务器仍然是有效的。

您仍然可以定期扩大或缩小您的应用程序服务器。例如,SmallPayroll.ca 应用程序的大多数用户会在每周工作日的 8:00 a.m. 到 9:00 p.m. 之间到达。为了改进注册用户的响应时间并减少服务器开销,在 8:00 a.m. 到 9:00 p.m. 这段时间会运行三个服务器,而在其他时间则运行两个服务器。这个部署脚本已经写好:您所需要的就是启动服务器,并将它添加到负载均衡器上。

从 cron 启动服务器

cron 工具仍然是使额外实例按预设方案启动或关闭的天然场所。理想的 crontab 类似于清单 4 所示。


清单 4. 一个自动启动和关闭服务器的 crontab
				
0  8 * * 1-5 $BASEDIR/servercontrol launch app
0 21 * * 1-5 $BASEDIR/servercontrol terminate app

您需要在虚拟环境以外的一个主机上的用户 crontab 中输入清单 4 的代码。在星期一到星期五的 8:00 a.m.,脚本 servercontrol 会执行带有参数 launch app 的命令。而在 9:00 p.m.,它会使用参数 terminate app。这个脚本将这些参数解析为操作和服务器角色。现在,这些角色总是为 app。

编写控制脚本

然后,下一步是编写服务器控制脚本,这个脚本是从 cron 执行的,并根据要求启动服务器。清单 5 显示的是这个脚本的代码。


清单 5. servercontrol 脚本
				
#!/bin/bash

AMI=ami-ad7e95c4
OP=$1
ROLE=$2

if [ "$OP" == "" -o "$ROLE" == "" ]; then
  echo You\'re doing it wrong.
  echo $0 operation number role
  exit
fi

case "$OP" in
  "launch")

    # Launch the instance and parse the data to get the instance ID
    DATA=`ec2-run-instances -k main -d "DB=10.126.17.1;ROLE=$ROLE" $AMI`
    INSTANCE=`echo $DATA | grep INSTANCE  | cut -f 6 -d ' '`
    echo $INSTANCE is your instance

    # Keep on checking until the state is "running"
    STATE=""
    while [ "$STATE" != "running" ]; do
      STATE=`ec2-describe-instances  $INSTANCE |awk '/^INSTANCE/ {print $6}'`
      echo the state is $STATE
      sleep 10
    done
    # Keep track of which instances were started by this method
    echo $INSTANCE >> $HOME/.ec2-$ROLE

    # Now that the instance is running, grab the IP address
    IP=`ec2-describe-instances $INSTANCE |awk '/^INSTANCE/ {print $13}'`

    # If this is to be an app server...
    if [ "$ROLE" == "app" ]; then
      # Check the web server to make sure it returns our content
      UP=0
      while [ $UP -eq 0 ]; do
        OUTPUT=`curl -s -m 5 http://$IP`
        if [ $? -eq 0 ]; then # curl was successful
          echo $OUTPUT | grep -qi 'welcome'
          if [ $? -eq 0 ]; then
            UP=1
          else
            sleep 5
          fi
        fi
      done

      # Register with the load balancer
      elb-register-instances-with-lb smallpayroll-http --instances $INSTANCE
    fi

  ;;

  "terminate")
     # Grab the instance ID. It's the last line of the file
     FILE=.ec2-$ROLE

     # Assuming the file exists, of course
     if [ ! -f $FILE ]; then
        echo No dynamic instances have been started for the $ROLE role
        exit
     fi

     # The last instance started is the last line of the file
     INSTANCE=`tail -1 $HOME/.ec2-$ROLE`

     # Assuming there's something in that file, that is
     if [ "$INSTANCE" == "" ]; then
         echo No dynamic instances have been started for the $ROLE role
         exit
     fi

     # Terminate the instance
     ec2-terminate-instances $INSTANCE

     # Take the instance out of the load balancer
     elb-deregister-instances-from-lb smallpayroll-http --instances $INSTANCE

     # Delete the last line of the file
     sed -i '$d' $FILE
  ;;

  *)
      echo "You may only launch or terminate"
      exit
  ;;
esac

这个脚本比较长,但是它有很多代码是用于错误处理的。这个脚本在开头解析参数,将 launch 和 terminate 函数调用放到 case 语句中。在 launch 函数中,这个脚本启动了一个实例,并等待这个实例进入 running 状态。然后脚本会获取这个实例的 IP 地址,并等待服务器的一个 Web 请求成功返回包含 welcome 的页面。

停止这个实例是非常简单的。实例 ID 已经被写到用户 home 目录下的一个 dotfile 中,其中较新的实例 ID 会依次被附加到文件后面的。为了停止这个实例,脚本会读取文件的最后几行来获取最近启动的实例 ID,发出一个停止命令,将实例从负载均衡器删除,然后删除文件中包含这些实例的最后几行内容。

注意,每一个角色都拥有它自己的文件。现在只有 Web 角色,但是将来还会有更多的角色。

清单 5 中比较奇怪的一项是 -d 参数,它会被传递给 ec2-run-instances。这个参数包含了实例访问一个只允许本实例访问的 URI 结果信息。这个信息是用一个字符串表示的。在清单 5 中,服务器的角色和数据库服务器都会传递给这个实例。

编写 init 脚本

init 脚本是在系统启动时运行的,它会在实例上配置一个当前版本的应用程序,同时启动对应的应用程序配置。清单 6 使用了来自控制脚本的信息来确定配置信息。清单中的这些代码可能是 SYSV 启动脚本的一部分,或者它可能位于启动时只运行一次的 rc.local 文件。


清单 6. 应用程序的 startup 脚本
				
USER=payroll
HOME=/home/payroll
SRC=/etc/smallpayroll

# If this is a fresh AMI, set up the application directories
if [ ! -d $HOME/releases ]; then
  echo "Setting up environment"
  cp $SRC/Capfile $HOME
  # Listing 2
  su - $USER -c "cd $HOME && sh $SRC/setup_environment"
fi

echo "Deploying the application"
su - $USER -c "cd $HOME && /opt/ree/bin/cap deploy"

# Grab the user supplied data. 169.254.169.254 returns data unique to the instance.
USER_DATA=`/usr/bin/curl -s http://169.254.169.254/2007-01-19/user-data`
DBHOST=`echo $USER_DATA | sed 's/.*DB=\([0-9\.]*\).*/\1/'`
ROLE=`echo $USER_DATA | sed 's/.*ROLE=\([a-zA-Z]*\).*/\1/'`
logger "Starting application with DBHOST=$DBHOST and ROLE=$ROLE"

# If available, put the dbhost in /etc/hosts
if [ "$DBHOST" != "" ]; then
  sed -i '/dbhost/d' /etc/hosts
  echo "$DBHOST dbhost" >> /etc/hosts
fi

# Depending on the role...
case "$ROLE" in
  'app')
    # Web server... start up mongrel
    su - $USER -c "mongrel_rails cluster::start \
      -C $HOME/current/config/mongrel_cluster.yml"
  ;;
  *)
    logger "$ROLE doesn't make sense to me"
  ;;
esac

清单 6 开头先初始化了一些变量。接下来,它会检查应用程序用户的 home 目录,查看 cap deploy:setup 任务之前是否已运行过;如果没有运行,那么这个任务就会运行。然后,它会运行一个部署操作,将最新代码部署到实例上。

现在,代码已经准备好了,该脚本会使用一些 sed 操作检查传递给这个实例的元数据,将组件保存到变量中。如果设置了 DBHOST 变量,那么它的值会被写入 /etc/hosts,这样应用程序就知道如何查找这个数据库。脚本也会检查服务器角色;如果这个服务器会成为一个应用程序服务器,那么相关的服务器也会被启动。

清单 5 和清单 6 中的代码相对较多,但它们设置了自动启动和停止任何类型服务器所需要做的操作。通过使用清单 4 的 crontab,附加服务器也会在高峰时间打开,然后在空闲时间关闭。接下来,您需要扩展这个框架来启动更多不同类型的服务器。


异步任务处理

使动态网站更加高效的一个常用技术是将一些运行时间很长的请求移到后台过程完成。这些运行时间很长的任务通常不像真实请求那样对处理时间有很高的要求。应用程序可能会使用 Asynchronous JavaScript + Extensible Markup Language (Ajax) 向任务处理系统发送一个请求,且在后台轮询完成。用户会看到一些等待图示,表示应用程序正在运行过程中,但是用户并不需要更复杂的过程来发送更多交互请求。

这种方法也一样要求使用足够的资源来处理这些任务。但是如果任务队列太长,用户会不愿意等待他们的报表完成。这似乎是一个动态服务器启动的理想情况。这些任务的运行会有专门的组件进行监控;如果运行负载超过一定的临界值,那么就会启动新的服务器来帮助解决问题。完成之后,这个服务器就会停止。

“没有免费的午餐”

运行新服务器并不是免费,所以当您决定要启动新服务器时,您需要考虑一些经济因素。

本系列文章所介绍的 m1.small 一小时或一小时内的花费大约为 8.5 美元。所以,如果您启动一个实例,哪怕只启动了一分钟,您也需要花费一个小时的费用。如果您决定使用更大的实例来完成更多操作,那么每小时的花费会增大。

您一定要理解启动和不启动一个新服务器的花费情况。较慢的服务意味着客户满意度下降。较快的服务则能够提高客户满意度,但是会增加成本。

后台处理是通过良好的 delayed_job gem 实现的 — 特别是,collectiveidea 分支(见 参考资料)。您可以在一行代码中使用这个 gem 清除所有任务和实现优先级队列,这样您的重要任务就不需要在例程作业后等待了。这个任务处理守护进程会耗尽 Rails 应用程序目录,并使用数据库来请求工作。这意味着您需要扩展当前的脚本,以处理 delayed_job 守护进程。

修改 init 脚本以支持任务处理服务器

在前面的 清单 6 中,脚本检查了它的实例元数据,以查看 servercontrol 脚本所传递的参数值。ROLE 参数表示服务器的任务,其中 app 表示一个应用程序服务器。每一个服务器类型的说明都封装在一个 case 语句中。清单 7 扩展了这个 case 语句,来处理 delayed_job 角色。


清单 7. 处理 delayed_job 服务器的启动
				
case "$ROLE" in
  'app')
    # For an application server, start the mongrels
    su - payroll -c "/opt/ree/bin/mongrel_rails cluster::start \
      -C /home/payroll/current/config/mongrel_cluster.yml"
  ;;
  'job')
    # For a job server, figure out what kind of machine this is, and run
    # an appropriate number of job processing daemons
    TYPE=`curl -s http://169.254.169.254/2007-08-29/meta-data/instance-type`
    case "$TYPE" in
      'm1.small') NUM=2 ;; # 2 per ECU * 1 ECU
      'm1.large') NUM=8 ;; # 2 per ECU * 4 ECUs
      *) NUM=2 ;;
    esac
    su - payroll -c "RAILS_ENV=production $HOME/current/script/delayed_job -n $NUM start"
  ;;
  *)
  logger "$ROLE doesn't make sense to me"
  ;;
esac

这个脚本会检查服务器的角色。如果这个服务器是一个应用程序服务器,那么脚本就会启动混合服务器。如果这个服务器只是一个作业服务器,那么脚本就会检查它运行在哪一个实例上。这些信息可以从另一个 169.254.169.254 虚拟主机的 URL 上获取。粗略地估计,这个脚本在每一个 Elastic Compute Unit(ECU) 期间会启动两个 delayed_job 工作者。您的工作负载会有所不同。

至此,servercontrol 脚本可以通过在命令行上输入 launch job 启动一个新的作业服务器。

监控队列

您有许多方法可以监控队列运行。您可以添加一个任务及其处理时间限制,如果时间超出了临界值就启动一个新服务器。这个方法的缺点是当队列真正恢复后,需要经过很长时间您才能确定它已经恢复。最简单的方法是查询数据库中未完成的请求数量,并将查询放到一个控制器中进行。清单 8 显示了这样一个控制器。


清单 8. 一个显示队列长度的控制器
				
class QueueController < ApplicationController
  def length
    render :text => Delayed::Job.count(
      :conditions => "priority > 0 AND failed_at IS NULL").to_s
  end
end

清单 8 显示了队列的长度 — 特别是,优先级大于 0 的任务和未处理的任务(不包括失败的任务)— 并直接显示这个数字,而不是将它传递到一个模板。浏览 /queue/length,您就可以知道当前的队列等待情况。

根据要求启动新的作业服务器

现在您可以很容易确定队列的长度,但是您还需要一个脚本来处理这个数据。清单 9 显示了这样一个脚本。


清单 9. 在需要时启动更多的作业服务器
				
#!/bin/bash

# What's the length of the queue
QUEUE=`curl -s http://app.smallpayroll.ca/queue/length`
# How many servers are running now? (zero out if file doesn't exist)
SERVERS=`wc -l $HOME/.ec2-job`
if [ "$SERVERS" == "" ]; then SERVERS=0; fi

# launch up to two servers while the queue is over 20
if [ $SERVERS -le 2 -a $QUEUE -gt 20 ]; then
  servercontrol launch job
fi

# Terminate one instance if the queue is under 5
if [ $SERVERS -gt 0 -a $QUEUE -lt 5 ]; then
  export TZ=/usr/share/zoneinfo/UTC 
  LAST=`tail -1 $HOME/.ec2-job`
  # But only if the server has run for at least 45 minutes
  UPTIME=`ec2-describe-instances $LAST | \
    awk '/INSTANCE/ {t=$10; gsub(/[\-:T\+]/, " ", t); print systime() - mktime(t) }'`
  if [ $UPTIME -gt 2700 ]; then
    servercontrol terminate job
  fi
fi

业务逻辑

清单 9 实现了一个简单的算法。它能够演示动态启动服务器的内在原则,但是它可以更加智能些。例如,这个脚本可以不停地观察队列的长度,然后在长度值稳定一段时间后关闭服务器,而不是使用像现在这样的判断方法。

清单 9 的代码应该在 cron 中每 5 分钟执行一次。它首先获取队列的长度,以及当前运行的作业服务器数。这个作业服务器数是从包含动态运行服务器实例 ID 的 .ec2-job 文件长度计算得来的。如果队列的长度超过 20,而且现在运行的服务器少于 2 个,那么就需要启动一个服务器。如果现在运行的服务器超过一个,而队列长度小于 5,那么这个脚本就需要进行更多的检查,以决定它是否应该停止一个实例。

这个脚本首先通过设置 TZ 环境变量将时区设置为 Coordinated Universal Time (UTC)。然后获取最后运行的作业服务器实例 ID,并查询启动时间。这个时间会进行某些 awk 替换,从而获得以秒为单位的服务器活动时间。如果服务器已在线超过 45 分钟,那么这个实例就可以关闭了。否则,这个服务器将继续运行。

这里设置的 45 分钟界限可以避免过早关闭服务器。如果队列减少,那么会有后续任务加入,这个服务器仍然运行。


使用一个内容分布式网络

当有人访问您的网站,他或她也会加载图像、Cascading Style Sheets (CSS) 和 JavaScript 代码。CDN 服务能够缓存静态资产,并将它们分布式地部署在许多互联网服务器上。这样,您就可以为用户实现更快速的静态资产访问,使他们能够同时下载多个文件。Amazon 提供了一个名为 Amazon CloudFront 的服务 — 与其他服务一样是按使用付费的。

由 CDN 挂载的资产是从另一个服务器请求的,所以请求的 URL 也是不一样的。例如,http://app.smallpayroll.ca/stylesheets/style.css 会从应用程序服务器加载样式表,而 http://cdn0.smallpayroll.ca/stylesheets/style.css 则是从 CDN 加载样式表。如果 CDN 上没有这个内容,那么它可以从原始 服务器获取内容,然后缓存并返回给用户。

CloudFront 与其他的 CDN 稍微有一些不同,因为它的原始服务器是一个 Amazon Simple Storage Service (Amazon S3) 存储区。要使用 CloudFront,您首先必须将静态资产存储到 Amazon S3 存储区中,然后把 URL 改为使用 CloudFront 主机。

创建 CloudFront

在 CloudFront 主页(见 参考资料 的链接),单击链接进行注册。您需要等待一个激活电子邮件到达后才能继续操作。

当您接收到激活的确认信息,您就可以在您的 Amazon Web Services 控制页面,单击 Amazon CloudFront 选项卡。您可以看到图 1 所示的页面。


图 1. CloudFront 发布控制面板
CloudFront 分配控制面板

注意,还没有创建发布。一个发布 指的仅仅是将会连接到一个 Amazon S3 存储区的一组文件。单击 Create Distribution 就可以到达如图 2 所示的页面。


图 2. 创建一个发布
创建一个发布

执行以下操作:

  1. 在 Delivery Method 中选择 Download。
  2. 在 Origin 下拉列表中选择一个 Amazon S3 存储区,或者使用您的 Amazon S3 工具创建一个新存储区。
  3. 在 Logging 中选择 Off;这表示您不需要使用这些日志。
  4. 在 CNAMEs 域中输入 4 个子域名,例如从 cdn0.smallpayroll.ca 到 cdn3.smallpayroll.ca。
  5. 在 Comments 中输入一些备注信息。
  6. 在 Distribution Status 选择 Enabled。

单击 Create,您会回到 CloudFront 选项卡,这时您就可以看到刚刚创建的发布了(见图 3)。


图 3. 配置的一个发布
配置的一个发布

在这个页面上有一个域名,如 djdzxdmb99068.cloudfront.net。您现在必须到您的 DNS 服务器上配置这四个 CNAME,将它们指定对应发布的域名。Amazon Elastic Load Balancing 采用了类似的方式,只是它要求创建四个数字形式的名称。

在与这个发布相对应的 Amazon S3 存储区上创建一个测试文件。您就能够通过浏览这个发布的域名看到这个文件,如在浏览器访问 http://djdzxdmb99068.cloudfront.net/test.htm,可以查看到存储区中名为 test.htm 的文件。如果出现拒绝访问的错误,您需要确认这些文件开启了公共访问权限(具体的设置方法取决于您所使用的 Amazon S3 存储区管理工具)。如果上面这个测试通过,那么您就可以尝试使用之前创建的 CNAME,如 http://cdn1.smallpayroll.ca/test.htm。

同步文件

您必须将公共目录下的文件复制到 Amazon S3 原始存储区。最简单的方法是在 Rails 应用程序的根目录下运行以下命令:

s3sync.rb -r -p public/ smallpayroll-cdn:

-r 选项表示复制是递归的。-p 选项表示将所有文件设置为公开可读。

如果您希望自动地完成这个过程,请参考 参考资料 关于执行这个任务的 gem 链接。

修改您的应用程序

最简单的情况,您可以修改所有的图像、JavaScript 和 CSS 链接,将它们指向其中一个 CDN 链接,而不是 Web 服务器。如果您使用了诸如 image_tag 的 Rails URL 标签,那么您可以在 Rails 中实现这个操作。将下面一行代码添加到 config/environments/production.rb:

ActionController::Base.asset_host = "cdn%d.smallpayroll.ca"

这行代码添加了一行生产环境配置 — 静态资产保存在 asset_hosts 定义的主机上。%d 的默认值是 0 到 3,所以 Railes 会循环查询 cdn0.smallpayroll.ca、cdn1.smallpayroll.ca、cdn2.smallpayroll.ca 和 cdn3.smallpayroll.ca 来获取内容。这些都是您在 CloudFront 上配置的相同主机。通过这 4 个主机,您就可以支持在浏览器上同时下载 8 个资产,因为浏览器通常限制一次只向一个网站创建最多两个连接。

现在,您的应用程序将会使得 CDN。这时应用程序的访问速度会大大提升!


结束语

应用程序使用 Amazon CloudFront 作为一个 CDN 可以提高客户端下载速度并支持并行下载,从而大大提升页面加载速度。应用程序也可以修改为支持动态扩展和缩减计算资源。有一些启动和停止操作可以通过调度实现,而另外一些则可以根据负载自动进行。此外,有一些脚本可扩展用于处理更多的情况。

管理是之前缺少的一环。在任何时刻,您可能都无法知道到底有多少计算机在运行。部署还不是自动执行的,因为服务器清单总是在变化。您也还不知道这些服务器本身的运行状态是怎么样的。请阅读本系列的最后一篇文章,以了解这些问题的答案。

<!-- CMA ID: 556095 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->

参考资料

学习

获得产品和技术

  • 现在您已经了解了几个 Amazon S3 的 AMI,您可能希望调整一些旧的 AMI。Amazon S3 File Manager 是一个基于 Web 的文件管理器,它与许多独立应用程序或浏览器插件有相似的特性。如果删除一个 AMI,请别忘记将它 ec2-deregister。

  • S3Sync 是一个很有用的复制 Amazon S3 文件以及处理存储区的工具。

  • Capistrano 是一个流行的部署包,它的工作方式与 Rake 相似。

  • delayed_job 是一个后台作业服务器,它能够与 Rails 和 ActiveRecord 整合。这个是项目的 collectiveidea 分支的链接,它是当前维护的分支。

  • synch_s3_asset_host 是一个快速同步 Amazon S3 原始存储区和应用程序静态文件的 gem。

  • 以最适合您的方式 IBM 产品评估试用版软件:下载产品试用版,在线试用产品,在云环境下试用产品,或者在 IBM SOA Sandbox for People 中花几个小时来学习如何高效实现面向服务架构。

讨论

关于作者

从 1994 开始,Sean Walberg 就一直在学术、企业和 Internet 服务供应者环境中从事 Linux 和 UNIX 系统的研究。在过去几年里,他撰写了大量有关系统管理的文章。

AWS DataSync实战:企业级数据迁移的稳定性与性能调优 AWS DataSync 是面向混合云场景的企业级数据同步服务,其核心价值在于解决传统脚本迁移中普遍存在的不可预测性、不可验证性和不可扩展性问题。它基于服务化架构,内置并行流调度、端到端SHA256校验、纳秒级增量识别等能力,无需用户深入理解TCP拥塞控制或NFSv4.1权限继承机制,即可实现高带宽利用率与POSIX权限零丢失。在金融、医疗、政务等强合规场景中,DataSync 与 EC2 Agent 模拟本地环境、VPC Endpoint 安全通道、CloudWatch 精细告警深度结合,支撑PB级影像、 阅读详情

相关推荐

游戏运行时架构解析:从ECS到O3DE构建模块化游戏世界

游戏运行时(Game Runtime)是现代游戏开发的核心架构范式,它标志着开发重心从传统渲染框架向世界模拟器的转变。其核心原理在于将游戏内容与底层平台基础设施解耦,通过模块化设计、数据驱动和网络抽象,构建可扩展、可维护的游戏系统。这一架构的技术价值在于解决了大型开放世界、服务型游戏和跨平台体验的工程痛点,如可扩展性差、热更新困难和协作效率低等问题。应用场景广泛覆盖了从AAA级开放世界到实时多人在线游戏的开发。以开源引擎O3DE为例,其Gem模块化系统和Atom渲染器充分体现了运行时的设计思想,通过ECS架

ithome 559

将您的 Linux 应用程序迁移到 Amazon 云,第 2 部分: 提高应用程序可靠性

如何提高您迁移的 Linux 应用程序的可靠性 Sean A. Walberg, 高级网络工程师 从 1994 开始,Sean Walberg 就一直在学术、企业和 Internet 服务供应者环境中从事 Linux 和 UNIX 系统的研究。在过去几年里,他撰写了大量有关系统管理的文章。   简介: 本文是迁移一个 Linux 应用程序到 Amazon 云 系列 的第...

xinlanzero 178

亚马逊推荐系统

亚马逊作为一流的电商其平台服务能力在行业中屈指可数,本文介绍了亚马逊的推荐的核心,有很好的借鉴意义

将您的 Linux 应用程序迁移到 Amazon 云,第 1 部分: 初始迁移

如何将您的应用程序迁移到云中 Sean A. Walberg, 高级网络工程师 从 1994 开始,Sean Walberg 就一直在学术、企业和 Internet 服务供应者环境中从事 Linux 和 UNIX 系统的研究。在过去几年里,他撰写了大量有关系统管理的文章。   简介: 云计算和基础设施即服务(Infrastructure as a Service,IaaS)的相关...

xinlanzero 326

LAMMPS实操系列(四): 高熵合金FCC-CoCrCuFeNi的退火模拟

我们对FCC-CoCrCuFeNi的退火模拟思路主要是,首先将材料以均匀的速率用100 ps从300 K升温至1000 K,然后在1000 K的温度下平衡100 ps,随后以均匀的速率用100 ps从1000 K降温至300 K,随后通过共轭梯度下降法做静力学结构优化得到退火后的结构。由于FCC-CoCrCuFeNi高熵合金被认为是潜在的工程结构材料[1],接下来我们将对退火前后的结构进行压缩模拟,对比退火前后FCC-CoCrCuFeNi高熵合金的力学性能变化,敬请各位读者关注我们的更新。

Ceshigo_CD的博客 4837

深入理解「二进制掩码」:从原理到实践

二进制掩码本质上是一个二进制数,用于通过位操作(如与、或、非、异或等)选择性地操作目标数据的某些位。掩码的每一位(bit)可以看作一个“开关”,决定是否对目标数据的对应位进行操作。二进制掩码是位操作的灵魂,掌握它不仅能提升代码效率,还能解锁许多高级编程技巧。从基础的位提取到复杂的子集枚举,掩码的应用无处不在。希望本文的讲解和代码示例能帮助你快速上手,并在实际项目中灵活运用。如果你有更多关于掩码的疑问或应用场景,欢迎在评论区留言交流!

m0_73494933的博客 2432

从商品到商品的协同过滤

Amazon经典论文,中文版由网友翻译。从商品到商品的协同过滤Greg Linden, Brent Smith, and Jeremy York Amazon.com推荐算法以其在电子商务网站的用途而著称1,它们利用有关一个顾客的兴趣作为输入,来产生一个推荐商品的列表。很多应用仅仅使用顾客购买并明确表示代表其兴趣的商品,但它们也可以利用其他属性,包括已浏览的商品、人口统计特征数据、主题兴趣,以及偏

wswyb001的专栏 1341

港口集装箱码头运营FlexSim仿真

列队4中的集装箱会根据不同类型的集装箱会放置在不同的堆场,因此根据前面对集装箱设置的标签Type的数值不同,设置不同的发送端口。集装箱到达列队3后,会有70%的集装箱到达堆场,30%的集装箱运出港口,因此在Queue列队3的Flow界面设置按照百分比发送端口,其中70%发送到端口1,即发送到列队4等待进入堆场,30%发送到端口2,即发送至出闸口。通过上述对比表格可以看出,当集卡数量在10的时候,岸桥和场桥的设备利用率达到了最高,当集卡数量为12的时候场桥1和场桥3的利用率有所下降,因此综合考虑。

m0_72514516的博客 1331

实验性的亚马逊返利连接编辑系统

这是一个亚马逊返利连接,亚马逊识别码为B00KT7DOSE https://www.amazon.com/gp/product/B00KT7DOSE/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=amazon083b5-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00KT7DOSE&linkId=

a552298242的博客 814

记录LeNet的硬件加速器设计(一)

LeNet的硬件加速器设计实现。

2301_81029398的博客 3543

相位相关匹配法的opencv C++实现

这一段就是PCIAM算法的核心了,计算两幅图像的峰值相关矩阵,也是完全按照matlab移植过来的,但是后面几行,是为了筛选一些不可能存在的情况,比如边缘处的完全重合,或者只有一行,或者一列重合等等情况,由于PCIAM算法在边缘处的响应值高,所以在一些场景下可能是一种干扰,所以进行了剔除,当然可以不剔除,就是对后期的峰值选取会有影响。头文件,以及各类函数,还有主函数,第一次独立的写这种分文件类型的项目,写的拉跨还请包涵,以及当然可以转成类的形式,但感觉有点小麻烦,后期再修改吧。

qq_43616651的博客 4260

将您的 Linux 应用程序迁移到 Amazon 云,第 4 部分: 征服管理挑战

避免您发展过程中的难题 Sean A. Walberg, 高级网络工程师 Sean Walberg 自 1994 年开始就先后在学院,企业,以及 Internet Service Provider 环境中研究 Linux 和 UNIX 系统。在过去几年中,他撰写了大量有关系统管理的书籍。   简介: 目前为止,您已经将应用程序迁移到了云环境中,可以根据需求自动地启...

xinlanzero 239

Plant Simulation 实战指南:从二次分配问题到优化布局设计

本文是一份Plant Simulation实战指南,详细讲解了如何利用该仿真软件解决工厂布局中的二次分配问题。通过从数据准备、模型搭建到集成遗传算法进行自动化优化的完整流程,帮助工程师在数字孪生环境中高效寻找最优设备布局方案,从而显著降低物流成本,提升生产效率。

i1j2k的博客 564

使用Amazon Q加速从Windows到Linux的移植

使用Amazon Q加速从Windows到Linux的移植

2401_89014665的博客 849

PD3.0详解 电源规则,全解!!!全解!!!

电源规则 大师匈今天谈一下PD3.0的电源规则,PD3.0标准标定的规则。 USB协议声称,为了世界和平世界环境,让大家用上统一标准的充电器,不用再为每一个用电设备都配一个专门的充电器,这些充电器各种各样的都有,所以有时候大师匈也很烦!!!那么为了维护世界和平,USB协议呢就制订了这个PD快充协议,还有它的规则,只要全世界都用PD,就解决了这个大问题。 在这里先了解一个关键字,PDP: Power Delivery Power PD电源的功率。 每个PD充电产品的功率要以0.5W的精度上报,比如大师匈做的P

大师匈的博客 1万+

qt open3dBPA重建

open3d BPA重建

阁楼 516

Amazon Q Developer 新功能上线

近日,亚马逊云科技推出了Amazon Q Developer转换功能的公开预览版,旨在加速.NET、大型机及VMware工作负载的现代化和迁移。这一功能支持自动化代码重构和迁移,结合团队协作,简化了整个转换过程。用户可通过生成式AI Agents和协作Web体验,帮助企业高效实现大规模转换。借助 Amazon Q Developer,开发者可以通过直观界面管理任务,并实时跟踪进度,从而提升迁移效率、优化应用的安全性和性能,帮助企业确保其应用的安全性、性能和可扩展性。

2403_86893713的博客 964

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

无缝迁移VMware工作负载至亚马逊云科技:一个成功案例

无缝迁移VMware工作负载至亚马逊云科技:一个成功案例

2401_89014665的博客 768

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

amazon-ecs-nodejs-microservices基础设施详解:ECS集群与CloudFormation模板使用指南

amazon-ecs-nodejs-microservices是一个展示如何将Node.js应用容器化并作为微服务部署在Amazon Elastic Container Service(ECS)上的参考架构。本指南将深入解析其基础设施架构,重点介绍ECS集群配置与CloudFormation模板的使用方法,帮助开发者快速掌握基于AWS的容器化部署流程。 ## 从单体到微服务:架构演进全解析 现

gitblog_00767的博客 220

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

将Amazon Lightsail迁移到更广泛的亚马逊云科技生态系统(如EC2)

截止今天,已在美国东部(俄亥俄)、美国东部(弗吉尼亚北部)、美国西部(俄勒冈)、亚太地区(孟买)、亚太地区(首尔)、亚太地区(新加坡)、亚太地区(悉尼)、亚太地区(东京)、加拿大(中部)、欧洲(法兰克福)、欧洲(爱尔兰)、欧洲(伦敦)和欧洲(巴黎)区域提供。Amazon Lightsail是一项易于使用的云服务,可为您提供部署应用程序或网站所需的一切,从而实现经济高效且易于理解的月度计划。任何可以在容器内运行的编程语言和框架都可以工作。部署指的是要在刚创建的服务上部署的特定容器映像和版本的组合。

MJ13125030552的博客 204

拥抱云原生:MinIO对象存储系统在Linux上的完美部署指南

拥抱云原生:MinIO对象存储系统在Linux上的完美部署指南 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在当今数据驱动的时代,高效、可靠的对象存储解决方案成为了开发者构建云原生应用的关键组件。MinIO,作为一款高度兼容Amazon S3的高性能分布式对象存储系统,凭借其卓越的性能和灵活的部署方式,成为了众多开发者的首选。本文档提供了一套详尽的指南,旨在帮助用户...

gitblog_06519的博客 457

Kokoro TTS 语音选择指南:3 分钟内选对 Kokoro 语音

Kokoro 是一个 8200 万参数的开源文本转语音(TTS)模型,内置 50 多种语音,直接决定最终音频的音色与风格。这篇文章不按语音列表逐条讲解,而是给你一条“先按场景缩小范围、再试听验证”的决策路径。只要跑通 Kokoro TTS 的最小流程,大约 3 分钟就能选定并验证一个合适的 Kokoro 语音。 ## Kokoro 是什么:8200 万参数的轻量级 TTS 模型 Kokoro

gitblog_00120的博客 199

把老旧Echo Dot 2改造成本地LLM终端:嵌入式Linux与llama.cpp实战

嵌入式Linux开发与本地大模型部署常常被视为两个独立的技术栈,但通过交叉编译与模型量化,我们可以将硬件资源有限的旧设备改造成可用的AI推理节点。本文从获取root权限的通用思路出发,讲解如何通过UART调试口和uboot参数修改,为老旧智能音箱植入llama.cpp运行环境。交叉编译工具链的选择与GGUF量化模型的适配,是降低资源占用、实现本地化推理的关键。这种改造路径不仅适用于旧款音箱,也能迁移至ARM开发板、电视盒子等嵌入式设备,为私有化、可控的AI应用提供低成本方案。最终以Echo Dot 2为例,

weixin_34347651的博客 465

MinIO是什么?

对象存储是一种将数据存储为对象的系统,与传统的块存储和文件存储不同,对象存储不需要文件系统的层次结构,数据以扁平的结构存储。每个对象包含数据本身、元数据和一个唯一的标识符。这种存储方式特别适合大规模、非结构化数据的存储和管理,如视频、图片、备份数据等。MinIO 作为一款高性能、易扩展的开源对象存储系统,为企业级数据存储提供了强有力的支持。其简洁的设计和强大的功能,使得用户可以轻松部署和管理大规模的数据存储需求。如果你正在寻找一个高效、安全的对象存储解决方案,不妨试试 MinIO。

chen的博客 1745

LDAP 目录服务器的现代化应用

基于 Linux 的 LDAP 目录服务器仍然是开发运维的重要工具。但这些服务器大多是本地服务器,似乎与当前的云环境格格不入。幸运的是,新一代基于云的 LDAP-as-a-service 平台已经出现,满足了管理员将资源上云管理的需求,并且无需安装、配置和管理本地 Linux LDAP 目录服务器。 1. LDAP 目录服务器的历史 轻量级目录访问协...

墨鱼菜鸡 190

Saltbox未来路线图:即将推出的5大令人期待的新功能

Saltbox作为一个基于Ansible的Docker容器化云媒体服务器快速部署解决方案,已经帮助无数用户轻松搭建个人媒体中心。随着技术的不断发展和用户需求的日益增长,Saltbox团队正在规划一系列令人兴奋的新功能。在这篇终极指南中,我们将深入探讨Saltbox未来路线图中最值得期待的5大新功能,帮助你了解这个强大媒体服务器平台的未来发展方向。 ## 🎯 为什么关注Saltbox未来路线图?

gitblog_00452的博客 1113
上一篇: 将您的 Linux 应用程序迁移到 Amazon 云,第 2 部分: 提高应用程序可靠性
下一篇: 将您的 Linux 应用程序迁移到 Amazon 云,第 4 部分: 征服管理挑战
xinlanzero
博客等级 码龄25年 10粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值