当前位置: 首页 > Linux学院 > 程序开发 > 编程应用 > 利用IBM Bluemix快速且轻松地扩展您的应用程序能力

利用IBM Bluemix快速且轻松地扩展您的应用程序能力

2014-06-20 16:36 来源:IBM 作者:Ryan Baxter 人气指数: 我要评论
使用 Bluemix 和它满是服务的目录,所有这些操作只需单击一个按钮即可完成。IBM Bluemix 是一款 beta 级产品,随着我们不断让其功能更加完善和更易于使用,它也将不断改进。我们会竭尽全力保持本文最新,但并不总是完全跟得上现状。感谢大家的理解!

使用 Bluemix 运行您的应用程序的最有吸引力的原因之一是,它快速且轻松地扩展您的应用程序的能力。使用传统的基础设施即服务 (IaaS) 产品,伸缩您的应用程序需要购买额外的虚拟映像,配置这些映像,在映像上部署您的应用程序,以及配置某种类型的负载平衡器来在新映像上分布负载。使用 Bluemix 和它满是服务的目录,所有这些操作只需单击一个按钮即可完成。

尽管在 Bluemix 中使用扩展功能非常简单,但并不意味着每个应用程序在伸缩后都能正常工作。常常,在内部运行的应用程序会将状态存储在内存中或本地文件系统中。这些类型的应用程序在扩展到云中时常常会发生故障,因为客户端请求将随机分配给该应用程序在云中运行的不同实例。一个实例上的应用程序状态与任何其他应用程序实例都不同。要解决此问题,Bluemix 等平台即服务 (PaaS) 产品提供了一些服务,可供应用程序用于跨多个实例共享状态。

我将介绍如何构建一个聊天应用程序,允许用户实时将消息发送给其他用户,跨多个实例扩展应用程序来处理负载。

开始

要构建此应用程序,您需要以下前提条件。

  1. 基本熟悉 HTML、JavaScript、CSS 和 Node.js。
  2. 已安装 Node.js 和 NPM。NPM 将随 Node.js 一起安装。

创建项目

将您希望执行工作的目录转到本地文件系统上,创建一个名为 bluechatter 的新文件夹。

$ mkdir bluechatter

App.js

在 bluechatter 目录中,创建一个名为 app.js 的文件。在 app.js 内,粘贴以下代码来创建一个基本的 Web 服务器,其中包含流行的 Node.js 库Express JS。

var express = require("express");
var fs = require('fs');
var http = require('http');
var path = require('path');

var app = express();
app.set('port', 3000);
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());

// Serve up our static resources
app.get('/', function(req, res) {
  fs.readFile('./public/index.html', function(err, data) {
    res.end(data);
  });
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Node.js 应用程序使用一个名为 package.json 的文件描述应用程序的基本元数据,以及提供一个依赖关系列表。在 bluechatter 文件夹内,创建一个名为 package.json 的文件并粘贴以下代码。

{
  "name": "BlueChatter",
  "version": "0.0.1",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.4.8"
  }
}

这会给您的应用程序分配一个名称、版本和启动版本。它还会指定该应用程序目前仅有的依赖关系:Express。稍后,您将向该应用程序添加依赖关系。

index.html

在 bluechatter 目录中,创建一个名为 public 的文件夹。在 public 文件夹内,创建一个名为 index.html 的文件并将以下代码粘贴到其中。

<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>BlueChatter</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <link href="stylesheets/style.css" rel="stylesheet">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div id="main-container">
      <h1>BlueChatter</h1>
      <div class="user-form center">
        <h3 class="form-signin-heading">Enter a username to get started</h3>
        <input id="user-name" class="form-control" placeholder="Username" required="" autofocus="">
        <button class="btn btn-lg btn-primary btn-block go-user" type="submit">Go!</button>
      </div>
    </div>
    <div class="footer center">
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script src="javascripts/client.js"></script>
  </body>
</html>

从这段 HTML 可以看到,我们使用了 Bootstrap 和 jQuery,二者都是从一个内容传送网络 (content delivery network, CDN) 获取的。此外,还存在对 style.css 和 client.js 的引用。这些是我们将用于向应用程序添加自定义样式和业务逻辑的文件。

首先创建 style.css。

style.css

在 public 文件夹中,创建一个名为 stylesheets 的文件夹。在 stylesheets 文件夹中,创建一个名为 style.css 的文件并将以下 CSS 代码粘贴到其中。

#main-container {
  margin: 0 auto;
}

#main-container h1 {
  text-align: center;
}

.center {
  text-align: center;
  max-width: 430px;
  padding: 15px;
  margin: 0 auto;
}

.go-user {
  margin-top: 10px;
}

.chat-box {
  max-width: 930px;
  padding: 15px;
  margin: 0 auto;
}

.message-area {
  max-height: 500px;
  overflow: auto;
}

.footer {
  padding-top: 19px;
  color: #777;
  border-top: 1px solid #e5e5e5;
}

现在创建 client.js。

client.js

在 public 文件夹中,创建一个名为 javascripts 的文件夹。在 javascripts 文件夹中,创建一个名为 client.js 的文件。将以下代码添加到其中并保存该文件,稍后将填入剩余代码。

 $(document).ready(function() {

 });

测试应用程序

此刻,您已拥有服务器端和客户端代码来测试应用程序。运行该应用程序之前,必须在 bluechatter 目录内运行 npm install 命令来安装必要的依赖关系。打开一个终端窗口并执行以下命令。

$ cd bluechatter
$ npm install

运行 npm install 时,您必须有一个有效的 Internet 连接,因为 npm 将下载需要的代码依赖关系。npm 完成安装依赖关系后,即可启动服务器。从 bluechatter 目录内运行以下命令。

$ node app.js

如果一切正常,将会看到终端窗口显示 “Express server listening on port 3000”。在您最喜欢的浏览器中访问 http://localhost:3000。在浏览器中,将会看到类似下图的内容。

图 1.

该图显示了浏览器结果示例

客户端代码

实现 Go! 按钮

此刻,如果单击应用程序中的 Go! 按钮,什么都不会发生。这是因为我们还未定义它的单击处理函数。

在您最喜爱的文本编辑器中打开 bluechatter 目录中的 public/javascripts/client.js。我们在这个适合归档的回调中添加一个函数,如下所示:

  var name = '';
  function go() {
    name = $('#user-name').val();
    $('#user-name').val('');
    $('.user-form').hide();
    $('.chat-box').show();
  };

这部分代码非常简单明了。我们真正所做的只是操作 DOM。我们获得了用户在 UI 的 username 字段中输入的名称并将它保存在一个变量中,因为稍后将需要它。接下来,隐藏表单和按钮,显示聊天框,用户可在其中看到和发送聊天消息。(聊天框还未在我们的 HTML 中定义;稍后将完成此任务。)我们仍需要从按钮单击监听器调用此函数。为此,将此代码添加到这个适合归档的回调中。

  $('#user-name').keydown(function(e) {
    if(e.keyCode == 13){ //Enter pressed
      go();
    }
  });
  $('.go-user').on('click', function(e) {
    go();
  });

此代码不仅向 Go! 按钮添加了一个单击监听器,还向 username 字段添加了一个键监听器,所以如果用户在该字段中按回车键,将实现与单击Go! 相同的目的。

最后,我们需要添加一些 HTML 来查看和发送聊天消息。打开 bluechatter/public 文件夹中的 index.html 文件。找到 ID 为 main-container 的 div,将以下 HTML 代码段添加到 main-container div 中已有内容的后面。

      <div class="chat-box well well-lg" style="display: none;">
        <div class="jumbotron">
          <h1>It Is Quiet In Here!</h1>
          <p>No one has said anything yet, type something insightful in the 
text box below and press enter!</p>
        </div>
        <div class="message-area">
        </div>
      </div>
      <div class="chat-box" style="display: none;">
        <textarea id="message-input" placeholder="Type something insightful!" 
class="form-control" rows="3"></textarea>
      </div>

现在如果节点服务器仍在运行,则按 Ctrl+c 停止它,运行以下命令来再次启动该服务器。

node app.js

如果返回到 http://localhost:3000,Go! 按钮应已发挥实际作用。输入一个用户名并单击 Go!。您应看到此界面。

图 2. 发送聊天消息

该图显示了发送聊天消息的过程

如果打算尝试在文本区域中 “键入一些有意义的内容” 并按回车键,就像 UI 告诉您做的一样,您同样会发现什么都不会发生。我们需要定义在按回车键时应发生的操作。应发生什么?在发送一条消息时,我们需要告诉服务器两种信息:发送消息的用户和发送的消息。

要告诉服务器此信息,我们将调用一个 REST API。REST API 还未在服务器代码中定义。所以现在,我们将假设 REST API 端点为 /msg 并接受 JSON。我们向文本区添加一个键监听器,它将调用我们虚构的 REST API。

  $('.chat-box textarea').keydown(function(e) {
    if(e.keyCode == 13){
      $.ajax({
        type: "POST",
        url: "/msg",
        data: JSON.stringify({"username" : name, "message" : $('#message-input').val().trim()}),
        contentType: "application/json"
      });
      $(this).val('');
      $('.jumbotron').hide();
      e.preventDefault()
    }
  });

可以看到,此代码向文本区添加了一个按键监听器。按下回车键(键代码 13)时,我们将使用 jQuery Ajax API 调用一个对 /msg 的 POST 请求。我们在 Ajax 请求中发送的数据是一个 JSON 对象,其中包含用户名和消息。在监听器末尾,我们还做了一些清理工作。我们清除文本区,隐藏显示 “it is quiet in here” 的 UI(因为它不再是安静不动的),然后调用 preventDefault 来阻止事件弹出。

我们运行 node app.js 命令并访问 http://localhost:3000,测试一下这个监听器。输入一个用户名,键入一条消息并按回车键。看起来什么都没发生,对吧?不完全是这样。打开您使用的浏览器的开发人员工具(比如 Firefox 中的 Firebug),转到 console 选项卡。现在键入另一条消息并按回车键。在控制台中,您应看到向 /msg 端点发送了一条请求。以下是此结果在 Firefox 中的 Firebug 内的显示效果示例。

图 3.

该图显示了 Firefox Firebug 示例

但是,请求失败了,因为我们的节点服务器没有定义 /msg。我们稍后再解决此问题,因为客户端 JavaScript 中还有一些事要做。

让我们进行一次轮询

客户端代码中的最后一部分是获取来自其他用户的聊天消息的代码。为了创建此代码,我们利用一种称为 长轮询 的技术长轮询的含义与它的字面意思并不完全相同:它轮询服务器,有时需要很长时间才能获得轮询的响应。对于我们的应用程序,客户端将向服务器发出一个请求,服务器将等待响应该请求,直到它有一些数据发送回客户端。服务器响应后,客户端立即向服务器发回另一个轮询请求,所以它可获得传入的下一条聊天消息。为此,我们将向服务器上的一个 REST API 发送一个 GET 请求。服务器将使用一个包含用户名和该用户发送的聊天消息的 JSON 对象作为响应。

将以下代码段添加到适合归档的回调的 client.js 中。

  function poll() {
    $.getJSON('/poll/' + new Date().getTime(), function(response, statusText, jqXHR) {
      if(jqXHR.status == 200) {
        $('.jumbotron').hide();
        msg = response;
        var html = '<div class="panel \
panel-success"><div class="panel-heading"><h3 class="panel-title">' +
msg.username + \
'</h3></div><div class="panel-body">' + msg.message + '</div></div>';
        var d = $('.message-area');
        d.append(html);
        d.scrollTop(d.prop("scrollHeight"));
      }
      poll();
    });
  };

同样地,我们使用 jQuery 帮助执行 REST API 调用。getJSON API 向 /poll 发出一个请求。您将注意到,我们还附加了当前时间。这么做是因为,浏览器将对发送给同一个端点的请求排队;我们不希望这么做,所以我们通过附加当前时间来唯一地标识端点。在回调中,我们首先检查以确保响应为 200,表明它是一个成功请求。再次隐藏 “jumbotron” 安静消息(因为它不再安静),向聊天区附加一些 HTML 代码,其中包含用户名和消息。最后,我们将聊天区滚动到底部,以便始终可以看到新消息。您还会注意到,该函数是递归性的,因为它会调用自身。这是一种具有长轮询模式 的轮询。

善于观察的开发人员将注意到,我们还没有任何东西调用轮询函数来开始轮询。我们希望何时开始轮询?只要用户按下 Go! 按钮。我们已有一个函数来处理 Go! 按钮单击,所以可从该监听器调用我们的轮询函数。在 go 函数末尾添加一个轮询函数调用。

  function go() {
    name = $('#user-name').val();
    $('#user-name').val('');
    $('.user-form').hide();
    $('.chat-box').show();
    poll();
  };

是时候再次测试我们的应用程序了。在终端运行 node app.js。在浏览器中,确保您已打开开发人员控制台并访问 http://localhost:3000。输入一个用户名并单击 Go!。您应看到我们的轮询请求已发送 — 但失败了,如下所示。

图 4.

该图显示轮询请求失败了

同样的原因,我们还未在服务器上实现该 REST API,所以此结果在预料之中。

大家感兴趣的内容
小伙伴最爱的新闻
小伙伴还关注了以下信息
小伙伴关注的焦点

小伙伴都在关注的热门词

新服 缤纷活动 航海世纪 芈月传 暗黑道具 萌乐网 苹果发布会 最新谍照 三国令 剑雨江湖 怎样修炼战骑 页游 怎样修炼伙伴 木甲世界 仙侠道2 推黑科技 页游模式 武圣试炼场 街机玩法 蓝月传奇 个人BOSS玩法 哥们网 九阴绝学 仗剑出鞘 全新模式 范伟打天下 全新元神玩法 七大神兵简介 新手攻略 跑腿任务 门派五行 城战礼包 页游界 泥石流 傅园慧 经典网页游戏 耐玩 盘点 玉石攻略 提升角色 大黑 实装属性 神兵攻略 问鼎莽荒 莽荒纪 手持神兵 土豪梦 万世 开学清单 财富赚不停 天书世界 大黑游戏 资源战场 ppwan 天问 激战 全国大战 雄霸一方 新增宠物技能 绝对小能手 花千骨 三尾章鱼 风色轨迹 双枪手 弑之神 缤纷好礼 惊喜六重连 帮会 中秋福利 自制月饼 九阴真经 玩家 五周年纪念 纪念银币 名动三界 新服资料片 画江山 勇战妖魔 邪恶势力 上古降魔 老司机玩法 坐骑揭秘 黑科技 竞技场攻略 铁血皇城 披风玩法 书剑恩仇录 装备强化攻略 野外BOSS玩法 全网曝光 赤壁传说 半回合制国 ACT 奇珍商城 热血战歌 传奇宝藏抽奖 打开方式 门徒 门徒获取玩法 三大萌宠简介