基于Cloud Foundry平台部署nodejs项目上线

时间:2023-03-08 15:36:44

Cloud Foundry(以下简称CF),CF是Vmware公司的PaaS服务平台,Paas(Platform as a Service,平台即服务), 是为开发者提供一个应用运行的平台,有了这人平台,开发者无需搭建线上应用运行环境和服务(Mysql/mongodb/Rabbitmq等),包括硬件和软件(os/应用软件如tomcat/rails等)环境。开发者可专注代码开发,最终提供源码(或war包之类的)信息,上传至PAAS,即可运行;同时pass平台提供DNS服务,一些Webapp可以直接完成上线。

  简而言之,有了paas,开发者只需要提供源码,即可瞬间启动一个企业级的web service

1. 注册免费账户

1) 登陆注册网站http://my.cloudfoundry.com/signup进行注册。

基于Cloud Foundry平台部署nodejs项目上线

2) 输入邮箱,注册,然后出现如下提示

基于Cloud Foundry平台部署nodejs项目上线

3)进入你的邮箱,打开验证链接,根据提示输入登录密码、用户信息等

基于Cloud Foundry平台部署nodejs项目上线

4)输入正确的手机号,需要验证码验证;

基于Cloud Foundry平台部署nodejs项目上线

5)输入组织名,后期可随意修改

基于Cloud Foundry平台部署nodejs项目上线

6)申请成功

基于Cloud Foundry平台部署nodejs项目上线

2、下载CF CLI(命令行终端)管理工具

1)上面最后一步已经提示非常清楚,根据你现在环境下载对应的管理工具;

2)以windows环境为例,下载安装完成后,运行CMD;

输入cf命令,可以查看所有相关命令操作选项

如果出现一堆的使用信息,说明你已经安装成功了……

3、关于CF CLI工具使用

Getting Started with the cf CLI

1)登录(cf login)

cf login [-a API_URL] [-u USERNAME] [-p PASSWORD] [-o ORG] [-s SPACE]

命令行:cf login -a https://api.run.pivotal.io

email:user#example.com

Password:.....

也可以使用cf api, cf auth,或cf target命令,来指定脚本文件来登录;

登录成功后,默认情况,CLI工具保存一个名为config.json的配置文件到~/.cf目录,其中包含你在pivotal上申请的组织名,空间大小,访问令牌等;

2)cf push 发布

用法:

cf push APP [-b URL] [-c COMMAND] [-d DOMAIN] [-i NUM_INSTANCES] [-m MEMORY] [-n HOST] [-p PATH] [-s STACK] [--no-hostname] [--no-route] [--no-start]

cf push my-app(上传并发布my-app应用)

-b 自定义的buildpack地址,一般如github上打包的.tar.gz的文件包

-c 指定启动命令,如nodejs中,cf push -c node myappstart.js,指定使用node myappstart.js来启动你的应用

-d 指定域名,如example.com

-f  指定manifest.yml文件路径,无此参数时,cf push会将当前你所处文件目录遍历,并上传到pivotal中你申请的空间中,并使用当前目录中manifest.yml文件配置的选项启动应用,如果没有此文件,一般会报错,关于manifest.yml的用法,请参考下面实例部分;

-p 指定你要上传发布的应用源码路径;默认是当前路径

-m 指定分配给该应用的内在大小如:cf push -m 10mb

-h 指定主机

3)用户提供的服务实例(cf cups --help)

TODO《这块没太仔细研究》

  1. cf cups (create-user-provided-service的别名),创建服务实例,使这个由用户提供的服务实例对应用生效,服务实例名为必选
  2. cf create-user-provided-service 服务实例 [-p 参数] [-l SYSLOG-syslog转发地址]
  3. 通过逗号分隔参数来使用交互模式:
  4. cf create-user-provided-service 服务实例 -p "逗号,分隔的,参数,名称"
  5. 传递JSON格式的参数来使用非交互方式创建服务:
  6. cf create-user-provided-service 服务实例 -p '{"名称":"值","名称":"值"}'
  7. 示例:
  8. cf create-user-provided-service oracle-db-mine -p "主机, 端口, 数据库名, 用户名, 密码"
  9. cf create-user-provided-service oracle-db-mine -p '{"用户名":"admin","密码":"pa55woRD"}'
  10. cf create-user-provided-service my-drain-service -l syslog://example.com
  11. cf uups(update-user-provided-service的别名),更新用户提供的服务实例
  12. 用法:
  13. cf update-user-provided-service 服务实例 [-p 参数] [-l SYSLOG-syslog转发地址]'
  14. 示例:
  15. cf update-user-provided-service oracle-db-mine -p '{"用户名":"admin","密码":"pa55woRD"}'
  16. cf update-user-provided-service my-drain-service -l syslog://example.com
  17. 可选参数:
  18. -p 参数
  19. -l Syslog转发地址

4)域,路由,组织和空间

cf CLI v6版本将以上概念进行简化

  • 所有域都映射到一个组织,该组织一般默认为你外网访问地址
  • 路由作用到空间和应用,也就是路由可以控制指向空间或你的应用

之前的路由是一个URL地址,类似HOSTNAME.DOMAIN,如果你不提供一个域名,那么默认路由(子域)一般是APPNAME.DOMAIN

在我实验过程中,关于DOMAIN,主域一般固定为.cfapps.io,子域默认是应用名,如: gjflying-org.cfapp.io是我申请的一个应用路由

当然,一个应用的路由可以后期添加,你上传的应用名'如上例中gjflying-org'后期都是添加和修改的;修改的方法有两种:

(1)使用cf CLI命令行工具,

Commands for managing domains:

  • cf create-domain — Create a domain.
  • cf delete-domain — Delete a domain.
  • cf create-shared-domain — Share a domain with all organizations. Admin only.
  • cf delete-shared-domain — Delete a domain that was shared with all organizations. Admin only.

Commands for managing routes:

  • cf create-route — Create a route.
  • cf map-route — Map a route to an application. If the route does not exist, this command creates it and then maps it.
  • cf unmap-route — Remove a route from an application.
  • cf delete-route — Delete a route.

Mapping a Route

  1. Use cf create-domain to create a domain in the desired organization, unless the domain already exists in (or has been shared with) the organization.
  2. Use cf map-route to map the domain to an application. Use the -n HOSTNAMEoption to specify a unique hostname for each route that uses the same domain.

(2)登录pivotal网站,在个人中心中进行管理

基于Cloud Foundry平台部署nodejs项目上线

5)关于用户及角色,

这方面不多说了,pivotal网站个人中心提供用户及角色相关管理操作,非常简单,可以进行添加、删除操作;满足多用户团队开发,代码提交等协同工作;

6)关于CLI中约定

  • 别名及缩写,提供缩写简化操作、提高效率和正确率;如cf p 是cf push的别名,cf tj 对target别名
  • 命令行提示中,大写是用户填写
  • 可选参数使用中括号括起
  • 命名 help或 h,可提供该命令的操作提示帮助(注册命令及h之间的空格哦)

4、一个nodejs简单应用编写:

准备工作:环境+数据库

  • 确定你安装了nodejs
  • 确定安装了npm
  • 确定安装了mongodb

如果你准备好,那我们开始吧:

1、创建package.json文件

找个空文件夹如gjflying-app,创建一个package.json文件,写入应用的一些基本信息:

  1. {
  2.     "name": "gjflying-app",
  3.     "version": "0.0.1",
  4.     "description": "使用express框架、hbs模板引擎、mongodb数据库的简单nodejs应用,依赖vmware的pass平台cloudFoundary进行发布上线;",
  5.     "main": "index.js",
  6.     "scripts": {
  7.         "test": "echo \"Error: no test specified\" && exit 1"
  8.     },
  9.     "author": "gaojun",
  10.     "private": true,
  11.     "dependencies": {
  12.         "express": "4.9"
  13.     },
  14.     "devDependencies": {
  15.         "hbs": "^2.7.0",
  16.         "body-parser": "^1.9.3"
  17.     }
  18. }

2、安装依赖;

打开命令行工具,进入该文件夹中,运行npm install,安装相关依赖包;

完成后发现应用中需要连接mongodb的驱动及连接池包,安装之:

npm install mongodb --save //保存依赖到package.json中devDependencies

npm install mongodb --save

3、应用目录

如下:

gjflying-org

-node_modules

-public    //静态文件目录

-css

-images

-js

-views     //模板目录

login.html(此处的后缀,是与配置的模板后缀一致)

app.js      //启动应用的主文件

server_mongodb.js //处理数据库连接

package.json

manifest.yml    //用于向CF提供运行配置的文件(后面讲其用处)

4、启动数据库

启动mongodb数据库,并创建数据库实例;以windows平台,安装数据库在D://program files中为例,

CMD命令行模式进入D://program files//mongodb//bin//文件夹

mongod.exe运行服务,

mongo.exe运行mongodb数据库用户交互命令

show dbs查看数据库(默认进入数据,是test数据库)

show collections 查看当前数据库中的数据集

创建我们使用的数据:gjflying

use gjflying

db.login.insert({name:"admin",pwd:"123456"});

db.login.find({});查看插入的数据,

5、编写代码

server_mongodb.js

  1. var http = require('http'),
  2.     mongodb = require('mongodb'),
  3.     poolModule = require('generic-pool');
  4. //自动调整连接池数
  5. var pool = poolModule.Pool({
  6.     name: 'mongodb',
  7.     create: function (callback) {
  8.         mongodb.MongoClient.connect('mongodb://localhost/gjflying', {
  9.             server: {poolSize: 1}
  10.         }, function (err, db) {
  11.             callback(err, db);
  12.         });
  13.     },
  14.     destroy: function (db) {
  15.         db.close();
  16.     },
  17.     max: 10,//根据应用的可能最高并发数设置
  18.     idleTimeoutMillis: 3000,
  19.     log: false
  20. });
  21. exports.pool = pool;

app.js

  1. var express = require('express'),
  2.     bodyParser = require('body-parser'),
  3.     hbs = require('hbs'); //hbs模板引擎
  4. var app = express();
  5. //全局配置
  6. app.set("views", __dirname + "/views"); //模板目录
  7. app.set('view engine', 'html'); //模板后缀为'.html'
  8. app.engine('html', hbs.__express); //使用hbs来解析模板
  9. //配置静态资源目录
  10. app.use(express.static(__dirname + '/public'));
  11. //加载中间件
  12. app.use(bodyParser.json());
  13. app.use(bodyParser.urlencoded({extended: true}));
  14. //添加路由处理(实际环境,路由往往单独放到一个router文件中)
  15. app.get('/', function (req, res) {
  16.     res.render('login');
  17. });
  18. app.get('/login', function (req, res) {
  19.     var pool = require('./server_mongodb').pool;
  20.     pool.acquire(function (err, db) {
  21.         if(err) {
  22.             res.statusCode = 500;
  23.             res.end(JSON.stringify(err, null, 2));
  24.         } else {
  25.             var uname = req.query.uname;
  26.             db.collection('user').find({uname: uname}).toArray(function (err, data) {
  27.                 //如果不存在,存储
  28.                 if(data.length == 0) {
  29.                     db.collection('user').save(req.query, function (err, result) {
  30.                         if(err) {
  31.                             res.send(err);
  32.                             return;
  33.                         }
  34.                         res.send('<h2>注册成功,你的用户名:' + uname + '</h2>');
  35.                         pool.release(db);
  36.                     });
  37.                 } else {
  38.                     res.send('<h2>您注册的用户已经存在,请重新注册!<a href="/">《返回》</a></h2>');
  39.                 }
  40.             });
  41.         }
  42.     });
  43. });
  44. app.listen(process.env.VCAP_APP_PORT || 3000);

login.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4.     <meta charset="UTF-8">
  5.     <title>用户注册</title>
  6. </head>
  7. <body>
  8. <h2>用户注册:</h2>
  9. <form action="/login" method="get">
  10.     用户名:
  11.     <input type="text"/>
  12.     <br>
  13.     密码:
  14.     <input type="password"/>
  15.     <br>
  16.     <input type="submit" value="提交注册"/>
  17. </form>
  18. </body>
  19. </html>

6、应用运行

命令行中运行 node app.js

浏览器中输入网址:http://localhost:3000/login

基于Cloud Foundry平台部署nodejs项目上线

填写信息,提交注册

返回:

基于Cloud Foundry平台部署nodejs项目上线

到此,应用在本地已经正常运行,下面介绍如何发布到线上;

5、应用发布上线

1、添加数据库

上述示例使用mongodb,因此需要在CF(cloud Foundary)平台的个人中心添加数据库服务,

基于Cloud Foundry平台部署nodejs项目上线

在弹出列表中选择从Marketplace中添加,选择

基于Cloud Foundry平台部署nodejs项目上线

添加完成后,可从个人中心的services已经绑定的服务列表查看该服务,

基于Cloud Foundry平台部署nodejs项目上线

其中,uri用于数据库连接,这是mongodb1.2版本后支持新连接方式,当然传统的-user -password的方式也是支持;你可以点上图右上角的manage进入数据库管理,查看连接方式,添加数据库用户等管理操作;

将上面uri复制到我们app.js文件中的数据连接处,替换之;

2、编写manifest.yml文件

该文件用于提供cf push命令哪些源码文件不需要上传(默认cf push会将当前目录下所有文件上传,当然不会上传svn版本文件),还有告诉云平台服务器如何运行你的应用,一个常用的配置内容如下:

---     //三个中线表示开始

#注释部分,使用#开始

applications:    //应用开始

- name: gjflying-app        //一个应用,指定名子并以一个中线开始

command: node app.js //启动应用命令

memory: 512M

官网解释如下:(值得注意的是:基于Cloud Foundry平台部署nodejs项目上线 红框处是两个空格)

基于Cloud Foundry平台部署nodejs项目上线

创建 .cfignore 可以指定哪些目录被push上传时排除,如:

public/     排除public目录上传

关于manifest其它编写,可以参考官网上说明;本应用中,上述配置够用;

3、发布应用

命令行进入gjflying-org目录运行:

cf login

输入邮件、密码验证通过;

再运行:

cf push gjflying-org

提示你使用manifest.yml配置,通过验证后开始上传文件

基于Cloud Foundry平台部署nodejs项目上线

完成上传后,告诉你运行一个应用实例,此时,说明你的应用已经跑起来,快在浏览器中打开它(http://yourappname.cfapps.io)试用一下试试吧;

基于Cloud Foundry平台部署nodejs项目上线