成功的云级别应用程序设计需要计划如何正确地在应用程序组件和服务中实现横向扩展。在本教程中,您将在 Bluemix 中创建一个使用 IBM Single Sign On 服务的简单 Node.js 应用程序。您会看到将应用程序扩展到单个实例外,并尝试执行身份验证时会发生什么(提示:不会一切顺利)。然后,我将解释哪里出错了,并指导您借助 Bluemix 中的 Redis Cloud 服务,通过一种实现方法来解决问题。
阅读: Single Sign On 入门
观看: 查看运行中的 IBM Bluemix
“ 要实现最佳的扩展,每个流程都应设计为无状态的,而且应该始终将数据持久保存到可供所有流程使用的备份服务中。 ”
运行应用程序
获取代码
运行我的演示应用程序时,请使用用户名 clouduser
和密码 Bluemix123
进行登录。
您的第一个任务是在 Bluemix 中创建一个使用 IBM Single Sign On 服务的简单 Node.js 应用程序。您将创建一个新应用程序,添加并配置一个 Single Sign On 服务实例,将该服务绑定到该应用程序,然后指定回调 URL。
scaleSSO
作为名称的开头,后跟一个连字符,然后为了让名称保持唯一,请添加您的姓名首字母和日期,例如 scaleSSO-TOR0815
: 在本教程的剩余部分中,请将 <your app name>
替换为您在此处输入的名称。 scaleSSOtest
作为服务名称并单击 Continue : 点击查看大图
关闭 [x]
字段中,输入:
https://<your app name>.mybluemix.net/auth/sso/callback
您的初始应用程序设置工作已完成。
在这一步中,您要克隆一个 IBM DevOps Services 项目,该项目包含一个简单的 Node.js 应用程序,已配置为使用 Single Sign On。修改此代码,将它用于您的现有应用程序,然后将代码推送到 Bluemix 来部署该应用程序。
在您的本地工作站上打开一个命令提示符,然后运行此命令:
git clone https://hub.jazz.net/git/timro/scaleSSO-base <your app name>
git clone
所创建的新目录中的 app.js 文件。在文件的第 49 行代码中更改 callback_url
,使其与您在第 1 步(第 18 小步)中使用的 Return-to URL 值相匹配: // you MUST change the host route to match your application name var callback_url = 'https://<your app name>.mybluemix.net/auth/sso/callback';
host
和 name
属性: applications: - disk_quota:1024M host:<your app name> name:<your app name> path:. domain: mybluemix.net
将命令行工作目录更改为项目目录,使用 Cloud Foundry 命令行工具登录 Bluemix:
cf login -a https://api.ng.bluemix.net
运行以下命令,更新您的应用程序并将其部署到 Bluemix 中:
cf push
cf push
命令的暂存消息。 部署后,该应用程序将启动,您会看到应用程序实例的状态为 running
: 点击查看大图
关闭 [x]
现在可以测试该应用程序了。
在这一步中,您要测试应用程序的身份验证 — 首先使用单个应用程序实例,然后添加第二个实例。
通过在 Single Sign On 配置管理器中更改可用的模板 HTML,可以更改 Single Sign On Chooser 的外观并更新 Consent 页面。
输入您在配置 Single Sign On 服务时添加到 Cloud Directory 的用户名和密码,并单击 Login 。如果提示您将初始密码更改为新密码,请执行该操作: 您会看到一条问候消息,其中包括已验证的用户名和验证范围 — 例如 揌ello, scalessotest-nw2nz9occb-ck11.iam.ibmcloud.com/www.ibm.com/clouduser!? —这表示您已成功通过了此应用程序实例的验证。使用单个实例时,这个简单的应用程序没有身份验证问题,但使用两个实例时存在该问题,因为此应用程序未采用 12 因素应用程序 方法。 确切地讲,它违背了因素 6:?#x5C06;应用程序作为一个或多个无状态进程来执行?#x3002;
这种非故意的失败是 Bluemix 中的 Node.js 应用程序使用 Passport 和 express-session
中间件为 Bluemix Single Sign On 服务提供 OpenID Connect 支持的方式的副产品。 express-session
服务将会话数据存储在内存中,所以该数据只能用于两个实例中的一个。当 Single Sign On 服务在验证用户后将浏览器重定向到回调 URL 时,如果将浏览器路由到另一个实例,Express Web 引擎将无法查找已验证用户的会话 ID,因此会抛出一条 404 消息。
此图演示了为什么一个会话中的数据只能用于应用程序中的实例 0:
解决方案是什么?因素 6 随后声明,?#x4EFB;何需要持久保存的数据必须存储在有状态的备份服务中,通常存储在数据库中。擥itHub 上的 express-session
文档列出了多个兼容的备份存储。您将使用 Redis 实现此持久性,它提供了一种内存型键-值缓存。此更改会将 express-session
的会话数据从实例内存中移出,然后将数据迁移到一个可供所有实例使用的持久存储中:
Bluemix 中的 Redis Cloud 服务托管在与您的应用程序相同的 SoftLayer 环境中,从而最大限度地缩短了访问此备份服务的响应时间。
dependencies
节,在其中的第 14 行上添加一个逗号并添加另外两个条目: "passport-idaas-openidconnect":"1.0.x", "connect-redis":"2.4.x", "redis":"0.12.1" },
redis
和 connect-redis
添加到 require
部分,并将这部分附加到第 17 行: var OpenIDConnectStrategy = require('passport-idaas-openidconnect').IDaaSOIDCStrategy; var redis = require('redis'); var RedisStore = require('connect-redis')(session);
// get configuration for redis backing service and connect to service var redisConfig = appEnv.getService(/Redis.*/) var redisPort = redisConfig.credentials.port; var redisHost = redisConfig.credentials.hostname; var redisPasswd = redisConfig.credentials.password; var redisclient = redis.createClient(redisPort, redisHost, {no_ready_check: true}); redisclient.auth(redisPasswd, function (err) { if (err) { throw err; } }); redisclient.on('connect', function() { console.log('Connected to Redis'); });
app.use(cookieParser())
语句后面最初的 app.use(session(...
语句,并将它替换为一个代码块,使用 Redis 作为存储来初始化 express-session
: // define express-session services, etc. for SSO app.use(cookieParser()); // app.use(session({resave:'true', saveUninitialized:'true' , secret:'keyboard cat'})); app.use(session({ store: new RedisStore({ client: redisclient }), resave:'true', saveUninitialized:'true', secret:'top secr8t' })); app.use(passport.initialize()); app.use(passport.session());
通过命令行更新该应用程序:
cf push
logs
命令和 recent
选项:
cf logs <your app name> --recent
点击查看大图
关闭 [x]
大功告成!现在该应用程序已可使用两个(或更多)实例正常运行。
在本教程中,您创建了一个使用 Bluemix Single Sign On 服务的简单应用程序,然后运行一两个实例来测试该应用程序。使用两个实例时,该应用程序出现了错误,因为 Node.js express-session
中间件默认情况下会使用一个本地内存存储。
借助 Bluemix 中的 Redis Cloud 服务,您通过为 express-session
会话添加持久存储解决了该问题。本教程重点介绍了一个关键的设计原则,让您能够通过流程模型扩展云应用程序。要实现最佳的扩展,每个流程都应设计为无状态的,而且应该始终将数据持久保存到可供所有流程使用的备份服务中。
BLUEMIX SERVICES USED IN THIS TUTORIAL:
相关主题: 安全性 Redis