Master-Slave

主从复制模式:即一台主写入服务器,多台从备份服务器。从服务器可以实现备份,和读扩展,分担主服务器读密集时压力,充当查询服务器。但是主服务器故障时,我们只能手动去切换备份服务器接替主服务器工作。这种灵活的方式,使扩展多如备份或查询服务器相对比较容易,当然查询服务器也不是无限扩展的,因为这些从服务器定期在轮询读取主服务器的更新,当从服务器过多时反而会对主服务器造成过载。

我们以之前创建的端口为27017做为主服务器,再创建个端口为27018从服务器

重新启动27017为主服务器 –master 主服务器

1
....bin>mongod  --dbpath "usr/local/mongodb/data/dbs/master" --master

创建27018为从服务器 –slave 从服务器 –source 指定主服务器

1
....bin>mongod --port 27018 --dbpath "usr/local/mongodb/data/dbs/slave27018"   --slave --source localhost:27017

主服务器可以通过自己local库的slave集合查看从服务器列表

从服务器可以通过自己local库的source集合查看主服务器信息或维护多个主服务器。 (一个slave服务器可以服务多个master服务器)

Replica Sets

副本集模式:具有Master-Slave模式所有特点,但是副本集没有固定的主服务器,当初始化的时候会通过多个服务器投票选举出一个主服务器。当主服务器故障时会再次通过投票选举出新的主服务器,而原先的主服务器恢复后则转为从服务器。Replica Sets的在故障发生时自动切换的机制可以极时保证写入操作。

创建多个副本集节点 –replSet (注意要区分大小写,官方建议命名空间使用IP地址)

1
2
3
4
5
....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27017"   --port 27017 --replSet replset/127.0.0.1:27017

....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27018" --port 27018 --replSet replset/127.0.0.1:27018

....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27019" --port 27019 --replSet replset/127.0.0.1:27019

首先建立3个是为了投票不会冲突,当服务器为偶数时可能会导致无法正常选举出主服务器。

其次上面3个replset 节点没有全部串联起来,是因为replset 有自检测功可以自动搜索连接其它服务器。

完成上面的工作后,要初始化副本集,随便连接一台服务器执行以下命令 (priority 0~1,被选为主服务器的优先级)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>use admin  
>db.runCommand(
{"replSetInitiate":{
"_id":"replset",
"members":[
{
"_id":1,
"host":"127.0.0.1:27017",
"priority":1
},
{
"_id":2,
"host":"127.0.0.1:27018",
"priority":1
},
{
"_id":3,
"host":"127.0.0.1:27019",
"priority":1
}]}}
)

再增加一个从服务器节点

1
....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27020" --port 27020 --replSet replset/127.0.0.1:27017 

通过rs.add命令往system.replset添加新的从服务器成员

1
2
rs.add("127.0.0.1:27020");   或者
rs.add({"_id":4,"host":"127.0.0.1:27020"}

这里在简单的介绍一下Master Slave/ Replica Sets 备份机制,这两种模式都是基于主服务器的oplog 来实现所有从服务器的同步。

oplog记录了增删改操作的记录信息(不包含查询的操作),但是oplog有大小限制,当超过指定大小,oplog会清空之前的记录,重新开始记录。

Master Slave方式主服备器会产生 oplog.$main 的日志集合。

Replica Sets 方式 所有服务器都会产生oplog.rs 日志集合。

两种机制下,所有从服务器都会去轮询主服务器oplog日志,若主服务器的日志较新,就会同步这些新的操作记录。但是这里有个很重要的问题,从服务器由于网络阻塞,死机等原因无法极时同步主服务器oplog记录:一种情况 主服务器oplog不断刷新,这样从服务器永远无法追上主服务器。另外一种情况,刚好主服务器oplog超出大小,清空了之前的oplog,这样从服务器就与主服务器数据就可能会不一致了,这第二种情况,我是推断的,没有证实。

另外要说明一下Replica Sets 备份的缺点,当主服务器发生故障时,一台从服务器被投票选为了主服务器,但是这台从服务的oplog 如果晚于之前的主服务器oplog的话,那之前的主服务器恢复后,会回滚自己的oplog操作和新的主服务器oplog保持一致。由于这个过程是自动切换的,所以在无形之中就导致了部分数据丢失。

Sublime Text 3 SFTP安装使用

安装

  1. ctrl + shift + p
  2. 输入Package Control: Install Package
  3. 输入SFTP
  4. Enter安装

配置

  1. 目录右键->SFTP->Map to Remote
  2. 配置sftp-config.json

配置项

  • type 链接类型
  • save_before_upload 上传文件前是否保存
  • upload_on_save 保存文件时是否同时上传
  • sync_down_on_open 同步下载打开文件
  • sync_skip_deletes 同步时是否跳过删除的文件
  • confirm_downloads 下载是否需要确认
  • confirm_sync 同步是否需要确认
  • host ftp域名或IP
  • user 登录用户名
  • password 登录密码
  • port ftp端口号
  • remote_path 远程文件路径
  • ignore_regexes 忽视文件的正则
  • connect_timeout 链接超时时间S

PC Static项目ftp推荐配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
// The tab key will cycle through the settings when first created
// Visit http://wbond.net/sublime_packages/sftp/settings for help

// sftp, ftp or ftps
"type": "sftp",

"save_before_upload": true,
"upload_on_save": false,
"sync_down_on_open": false,
"sync_skip_deletes": false,
"sync_same_age": true,
"confirm_downloads": false,
"confirm_sync": true,
"confirm_overwrite_newer": false,

"host": "10.139.64.40",
"user": "trunk",
"password": "Trunk4Test",
"port": "22",

"remote_path": "/home/trunk/apache-static-web-10101/webapps/ROOT/",
"ignore_regexes": [
"\\.sublime-(project|workspace)", "sftp-config(-alt\\d?)?\\.json",
"sftp-settings\\.json", "/venv/", "\\.svn/", "\\.hg/", "\\.git/",
"\\.bzr", "_darcs", "CVS", "\\.DS_Store", "Thumbs\\.db", "desktop\\.ini"
],
//"file_permissions": "664",
//"dir_permissions": "775",

//"extra_list_connections": 0,

"connect_timeout": 30,
//"keepalive": 120,
//"ftp_passive_mode": true,
//"ftp_obey_passive_host": false,
//"ssh_key_file": "~/.ssh/id_rsa",
//"sftp_flags": ["-F", "/path/to/ssh_config"],

//"preserve_modification_times": false,
//"remote_time_offset_in_hours": 0,
//"remote_encoding": "utf-8",
//"remote_locale": "C",
//"allow_config_upload": false,
}

PC开发环境配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
// The tab key will cycle through the settings when first created
// Visit http://wbond.net/sublime_packages/sftp/settings for help

// sftp, ftp or ftps
"type": "sftp",

"save_before_upload": true,
"upload_on_save": false,
"sync_down_on_open": false,
"sync_skip_deletes": false,
"sync_same_age": true,
"confirm_downloads": false,
"confirm_sync": true,
"confirm_overwrite_newer": false,

"host": "10.139.64.73",
"user": "trunk",
"password": "Trunk4Test",
"port": "22",

"remote_path": "/home/trunk/apache-tomcat-7.0.57/webapps/ROOT/",
"ignore_regexes": [
"\\.sublime-(project|workspace)", "sftp-config(-alt\\d?)?\\.json",
"sftp-settings\\.json", "/venv/", "\\.svn/", "\\.hg/", "\\.git/",
"\\.bzr", "_darcs", "CVS", "\\.DS_Store", "Thumbs\\.db", "desktop\\.ini"
],
//"file_permissions": "664",
//"dir_permissions": "775",

//"extra_list_connections": 0,

"connect_timeout": 30,
//"keepalive": 120,
//"ftp_passive_mode": true,
//"ftp_obey_passive_host": false,
//"ssh_key_file": "~/.ssh/id_rsa",
//"sftp_flags": ["-F", "/path/to/ssh_config"],

//"preserve_modification_times": false,
//"remote_time_offset_in_hours": 0,
//"remote_encoding": "utf-8",
//"remote_locale": "C",
//"allow_config_upload": false,
}

APP开发环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
// The tab key will cycle through the settings when first created
// Visit http://wbond.net/sublime_packages/sftp/settings for help

// sftp, ftp or ftps
"type": "sftp",

"save_before_upload": true,
"upload_on_save": false,
"sync_down_on_open": false,
"sync_skip_deletes": false,
"sync_same_age": true,
"confirm_downloads": false,
"confirm_sync": true,
"confirm_overwrite_newer": false,

"host": "10.139.64.73",
"user": "trunk",
"password": "Trunk4Test",
"port": "22",

"remote_path": "/home/trunk/apache-tomcat-7.0.57/webapps/ifaexApp/",
"ignore_regexes": [
"\\.sublime-(project|workspace)", "sftp-config(-alt\\d?)?\\.json",
"sftp-settings\\.json", "/venv/", "\\.svn/", "\\.hg/", "\\.git/",
"\\.bzr", "_darcs", "CVS", "\\.DS_Store", "Thumbs\\.db", "desktop\\.ini"
],
//"file_permissions": "664",
//"dir_permissions": "775",

//"extra_list_connections": 0,

"connect_timeout": 30,
//"keepalive": 120,
//"ftp_passive_mode": true,
//"ftp_obey_passive_host": false,
//"ssh_key_file": "~/.ssh/id_rsa",
//"sftp_flags": ["-F", "/path/to/ssh_config"],

//"preserve_modification_times": false,
//"remote_time_offset_in_hours": 0,
//"remote_encoding": "utf-8",
//"remote_locale": "C",
//"allow_config_upload": false,
}

文件同步

  • 本地同步远程 目录 >> 文件夹 >> SFTP >> Sync Local -> Remote
  • 远程同步本地 目录 >> 文件夹 >> SFTP >> Sync Remote -> Local

破解

首选项 >> Package Settings >> SFTP >> Setting User

加入下面的配置:

1
2
3
4
{
"email": "xiaosong@xiaosong.me",
"product_key": "d419f6-de89e9-0aae59-2acea1-07f92a"
}

微站子系统上线以后,我们有2个域名,分别是www和wx。测试发现,当页面交替请求这2个域名下的资源和服务时,会造成session反复切换,于是依赖session的一些方案都失效了

最后定位到,是因为我们错误地使用express session造成的

express的session中间件的原理是,对于配置了使用session middleware的path,大致上有以下的流程:

  1. 看request是否携带了sid的cookie
  2. 如果没有sid,则在服务端(内存,redis,mongodb)创建一个session,并分配一个sid在响应中给客户端,下次客户端就会带着这个sid cookie上来
  3. 如果有sid,但是在服务端找不到对应的session,那么也创建一个,并重新分配sid
  4. 如果有sid,并且能找到对应的session,则把session中储存的值取出来,放在req.session对象上

因此,在多域名的环境下,要保证session机制正确,需要注意以下几点:

  1. 不同的url配置的mongodb源必须一致,既要是同一个mongodb,还要是同一个database
  2. 需要配置domain属性

参考配置如下:

1
2
3
4
5
6
7
8
9
10
.use("/svc", express.session({     
store: new MongoStore({
url: 'mongodb://' + global['_g_topo'].dataServer.mongodb.connectionurl + '/yilos_session'
}),
cookie: {
domain: "yilos.com",
maxAge: maxAge
},
secret: secret
}))

如果使用的mongodb源不同,那么当URL切换的时候,根据sid就找不到对应的session,于是会重新创建;如果没有配置domain,那么在www和wx域名切换的时候,客户端会携带不同的cookie,也会造成express下发不同的sid,还是找不到

菜鸟教程 http://www.runoob.com/mongodb

连接mongodb

1
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

创建数据库

1
use DATABASE_NAME

列出所有数据库

1
show dbs //只显示有数据的

切换数据库

1
switched to db DATABASE_NAME

删除当前数据库

1
db.dropDatabase()

删除当前集合

1
db.collection.drop()

列出所有集合

1
show collections

插入文档

1
db.COLLECTION_NAME.insert(document)

更新文档

1
2
3
4
5
6
7
8
9
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)

参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如$,$inc…)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。

更新操作符

  • $inc 对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作
  • $set 用来指定一个键并更新键值,若键不存在并创建。
  • $unset 删除键
  • $push 给数组类型键值添加一个元素
  • $ne/$addToSet 给数组类型键值添加一个元素时,避免在数组中产生重复数据
  • $pop 从数组的头或者尾删除数组中的元素
  • $pull 从数组中删除满足条件的元素

参考文档 http://blog.csdn.net/mcpang/article/details/7752736

删除文档

1
2
3
4
db.collection.remove(
<query>,
<justOne>
)

参数说明:

  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档。
  • writeConcern :(可选)抛出异常的级别。

查询文档

1
db.COLLECTION_NAME.find(<key>:<value>,$or:[{<key>:<value>})

MongoDB 与 RDBMS Where 语句比较

操作 格式 范例 RDBMS中的类似语句
等于 {:} db.col.find({“by”:”菜鸟教程”}).pretty() where by = ‘菜鸟教程’
小于 {:{$lt:}} db.col.find({“likes”:{$lt:50}}).pretty() where likes < 50
小于或等于 {:{$lte:}} db.col.find({“likes”:{$lte:50}}).pretty() where likes <= 50
大于 {:{$gt:}} db.col.find({“likes”:{$gt:50}}).pretty() where likes > 50
大于或等于 {:{$gte:}} db.col.find({“likes”:{$gte:50}}).pretty() where likes >= 50
不等于 {:{$ne:}} db.col.find({“likes”:{$ne:50}}).pretty() where likes != 50

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

1
db.COLLECTION_NAME.find().pretty()

pretty() 方法以格式化的方式来显示所有文档。

Limit与Skip方法

如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。

我们除了可以使用limit()方法来读取指定数量的数据外,还可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。

1
db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

sort()方法

在MongoDB中使用使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。

1
db.COLLECTION_NAME.find().sort({KEY:1})

索引ensureIndex

创建索引

1
db.COLLECTION_NAME.ensureIndex({KEY:1})

语法中 Key 值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。

Parameter Type Description
background Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false。
unique Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
name string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDups Boolean 在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
sparse Boolean 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSeconds integer 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
v index version 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weights document 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_language string 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_override string 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

查看索引

1
db.COLLECTION_NAME.getIndexes()

删除索引

1
db.COLLECTION_NAME.dropIndex({KEY:1})

聚合aggregate

1
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
表达式 描述 实例
$sum 计算总和。 db.mycol.aggregate([{$group : {_id : “$by_user”, num_tutorial : {$sum : “$likes”}}}])
$avg 计算平均值 db.mycol.aggregate([{$group : {_id : “$by_user”, num_tutorial : {$avg : “$likes”}}}])
$min 获取集合中所有文档对应值得最小值。 db.mycol.aggregate([{$group : {_id : “$by_user”, num_tutorial : {$min : “$likes”}}}])
$max 获取集合中所有文档对应值得最大值。 db.mycol.aggregate([{$group : {_id : “$by_user”, num_tutorial : {$max : “$likes”}}}])
$push 在结果文档中插入值到一个数组中。 db.mycol.aggregate([{$group : {_id : “$by_user”, url : {$push: “$url”}}}])
$addToSet 在结果文档中插入值到一个数组中,但不创建副本。 db.mycol.aggregate([{$group : {_id : “$by_user”, url : {$addToSet : “$url”}}}])
$first 根据资源文档的排序获取第一个文档数据。 db.mycol.aggregate([{$group : {_id : “$by_user”, first_url : {$first : “$url”}}}])
$last 根据资源文档的排序获取最后一个文档数据 db.mycol.aggregate([{$group : {_id : “$by_user”, last_url : {$last : “$url”}}}])

数据备份(mongodump)

1
mongodump -h dbhost -d dbname -o dbdirectory
  • -h:
    MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
  • -d:
    需要备份的数据库实例,例如:test
  • -o:
    备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。
  • –collection:
    该命令将备份指定数据库的集合。

数据恢复(mongorestore)

1
mongorestore -h dbhost -d dbname --directoryperdb dbdirectory
  • -h:
    MongoDB所在服务器地址
  • -d:
    需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
  • –directoryperdb:
    备份数据所在位置,例如:c:\data\dump\test,这里为什么要多加一个test,而不是备份时候的dump,读者自己查看提示吧!
  • –drop:
    恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!

下载安装包

1
wget http://fastdl.mongodb.org/linux/mongodb-linux-i686-1.8.2.tgz

下载完成后解压缩压缩包

1
tar zxf mongodb-linux-i686-1.8.2.tgz

安装准备

将mongodb移动到/usr/local/server/mongdb文件夹

1
mv mongodb-linux-i686-1.8.2 /usr/local/mongodb

创建数据库文件夹与日志文件

1
2
mkdir /usr/local/mongodb/data
touch /usr/local/mongodb/logs

设置配置文件

1
echo "# Mongodb配置文件" >> /etc/mongodb.conf

配置项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 日志文件位置
logpath=/usr/local/mongodb/logs

# 以追加方式写入日志
logappend=true

# 是否以守护进程方式运行
fork = true

# 默认27017
port = 27017

# 数据库文件位置
dbpath=/usr/local/mongodb/data

# 启用定期记录CPU利用率和 I/O 等待
# cpu = true

# 是否以安全认证方式运行,默认是不认证的非安全方式
# noauth = true
# auth = true

# 详细记录输出
# verbose = true

# Inspect all client data for validity on receipt (useful for
# developing drivers)用于开发驱动程序时验证客户端请求
# objcheck = true

# Enable db quota management
# 启用数据库配额管理
# quota = true

# 设置oplog记录等级
# Set oplogging level where n is
# 0=off (default)
# 1=W
# 2=R
# 3=both
# 7=W+some reads
# diaglog=0

# Diagnostic/debugging option 动态调试项
# nocursors = true

# Ignore query hints 忽略查询提示
# nohints = true

# 禁用http界面,默认为localhost:28017
# nohttpinterface = true

# 关闭服务器端脚本,这将极大的限制功能
# Turns off server-side scripting. This will result in greatly limited
# functionality
# noscripting = true

# 关闭扫描表,任何查询将会是扫描失败
# Turns off table scans. Any query that would do a table scan fails.
# notablescan = true

# 关闭数据文件预分配
# Disable data file preallocation.
# noprealloc = true

# 为新数据库指定.ns文件的大小,单位:MB
# Specify .ns file size for new databases.
# nssize =

# Replication Options 复制选项
# in replicated mongo databases, specify the replica set name here
#replSet=setname

# maximum size in megabytes for replication operation log
# oplogSize=1024

# path to a key file storing authentication info for connections
# between replica set members
# 指定存储身份验证信息的密钥文件的路径
# keyFile=/path/to/keyfile

设置开机自启动

将mongodb启动项目追加入rc.local保证mongodb在服务器开机时启动

1
echo "/usr/local/mongodb/bin/mongod --config=/etc/mongodb.conf" >> /etc/rc.local

启动mongodb

cd到mongodb目录下的bin文件夹启动mongodb

//下面这个是需要权限的登录方式, 用户连接需要用户名和密码

1
/usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data --logpath=/usr/local/mongodb/logs --logappend  --auth  --port=27017 --fork

//这个是不需要密码的

1
/usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data --logpath=/usr/local/mongodb/logs --logappend  --port=27017 --fork

参数解释: –dbpath 数据库路径(数据文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--logpath 日志文件路径
--master 指定为主机器
--slave 指定为从机器
--source 指定主机器的IP地址
--pologSize 指定日志文件大小不超过64M.因为resync是非常操作量大且耗时,最好通过设置一个足够大的oplogSize来避免resync(默认的 oplog大小是空闲磁盘大小的5%)。
--logappend 日志文件末尾添加
--port 启用端口号
--fork 在后台运行
--only 指定只复制哪一个数据库
--slavedelay 指从复制检测的时间间隔
--auth 是否需要验证权限登录(用户名和密码)

-h [ --help ] show this usage information
--version show version information
-f [ --config ] arg configuration file specifying additional options
--port arg specify port number
--bind_ip arg local ip address to bind listener - all local ips
bound by default
-v [ --verbose ] be more verbose (include multiple times for more
verbosity e.g. -vvvvv)
--dbpath arg (=/data/db/) directory for datafiles 指定数据存放目录
--quiet quieter output 静默模式
--logpath arg file to send all output to instead of stdout 指定日志存放目录
--logappend appnd to logpath instead of over-writing 指定日志是以追加还是以覆盖的方式写入日志文件
--fork fork server process 以创建子进程的方式运行
--cpu periodically show cpu and iowait utilization 周期性的显示cpu和io的使用情况
--noauth run without security 无认证模式运行
--auth run with security 认证模式运行
--objcheck inspect client data for validity on receipt 检查客户端输入数据的有效性检查
--quota enable db quota management 开始数据库配额的管理
--quotaFiles arg number of files allower per db, requires --quota 规定每个数据库允许的文件数
--appsrvpath arg root directory for the babble app server
--nocursors diagnostic/debugging option 调试诊断选项
--nohints ignore query hints 忽略查询命中率
--nohttpinterface disable http interface 关闭http接口,默认是28017
--noscripting disable scripting engine 关闭脚本引擎
--noprealloc disable data file preallocation 关闭数据库文件大小预分配
--smallfiles use a smaller default file size 使用较小的默认文件大小
--nssize arg (=16) .ns file size (in MB) for new databases 新数据库ns文件的默认大小
--diaglog arg 0=off 1=W 2=R 3=both 7=W+some reads 提供的方式,是只读,只写,还是读写都行,还是主要写+部分的读模式
--sysinfo print some diagnostic system information 打印系统诊断信息
--upgrade upgrade db if needed 如果需要就更新数据库
--repair run repair on all dbs 修复所有的数据库
--notablescan do not allow table scans 不运行表扫描
--syncdelay arg (=60) seconds between disk syncs (0 for never) 系统同步刷新磁盘的时间,默认是60s

Replication options:
--master master mode 主复制模式
--slave slave mode 从复制模式
--source arg when slave: specify master as <server:port> 当为从时,指定主的地址和端口
--only arg when slave: specify a single database to replicate 当为从时,指定需要从主复制的单一库
--pairwith arg address of server to pair with
--arbiter arg address of arbiter server 仲裁服务器,在主主中和pair中用到
--autoresync automatically resync if slave data is stale 自动同步从的数据
--oplogSize arg size limit (in MB) for op log 指定操作日志的大小
--opIdMem arg size limit (in bytes) for in memory storage of op ids指定存储操作日志的内存大小

Sharding options:
--configsvr declare this is a config db of a cluster 指定shard中的配置服务器
--shardsvr declare this is a shard db of a cluster 指定shard服务器

关闭Mongodb

1
db.shutdownServer()

创建用户

1
2
use DATABASE_NAME
db.createUser({user:"username", pwd:"password", roles:[{role:"role", db:"DATABASE_NAME"]})

修改密码

1
db.changeUserPassword("username", "password")

修改用户信息

1
db.updateUser("username",updateObject)

删除用户

1
2
db.dropUser("username")
db.removeUser()

进入数据库的CLI管理界面

cd到mongodb目录下的bin文件夹,执行命令./mongo

运行如下:

1
2
3
4
5
[root@namenode mongodb]# ./bin/mongo
MongoDB shell version: 1.8.2
connecting to: test
> use test;
switched to db test

若数据库出现如不能连上,则是一个data目录下的mongod.lock文件的问题,可以用如下的修复的命令,

1
mongod --repair

express + nodemon

==nodemon重启速度比supervisor快==

安装

1
cnpm install -g nodemon

启动

local-authentication-with-passport-and-express-4

http://mherman.org/blog/2015/01/31/local-authentication-with-passport-and-express-4/#.WH8vn1V95hF

express框架之session 内存存储

express-session 是基于express框专门用于处理session的中间件。这里不谈express-session怎么安装,只给出相应的实例代码。另外,session的认证机制离不开cookie,需要同时使用cookieParser 中间件,有关的介绍可以专门参考
https://github.com/expressjs/session/blob/master/README.md
或者参考
http://blog.modulus.io/nodejs-and-express-sessions
这个博客上讲的比较清楚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var express = require('express');
var session = require('express-session');
var cookieParser = require('cookie-parser');

var app = express();

app.use(cookieParser());
app.use(session({
secret: '12345',
name: 'testapp', //这里的name值得是cookie的name,默认cookie的name是:connect.sid
cookie: {maxAge: 80000 }, //设置maxAge是80000ms,即80s后session和相应的cookie失效过期
resave: false,
saveUninitialized: true,
}));


app.get('/awesome', function(req, res){

if(req.session.lastPage) {
console.log('Last page was: ' + req.session.lastPage + ".");
}
req.session.lastPage = '/awesome'; //每一次访问时,session对象的lastPage会自动的保存或更新内存中的session中去。
res.send("You're Awesome. And the session expired time is: " + req.session.cookie.maxAge);
});

app.get('/radical', function(req, res){
if (req.session.lastPage) {
console.log('Last page was: ' + req.session.lastPage + ".");
}
req.session.lastPage = '/radical';
res.send('What a radical visit! And the session expired time is: ' + req.session.cookie.maxAge);
});

app.get('/tubular', function(req, res){
if (req.session.lastPage){
console.log("Last page was: " + req.session.lastPage + ".");
}

req.session.lastPage = '/tubular';
res.send('Are you a suffer? And the session expired time is: ' + req.session.cookie.maxAge);
});

app.listen(5000);

express-session中间件的使用:

只需要用express app的use方法将session挂载在‘/’路径即可,这样所有的路由都可以访问到session。可以给要挂载的session传递不同的option参数,来控制session的不同特性。具体可以参见官网:https://github.com/expressjs/session/blob/master/README.md。

session内容的存储和更改:

To store or access session data, simply use the request property req.session, which is (generally) serialized as JSON by the store, so nested objects are typically fine.

一旦我们将express-session中间件用use挂载后,我们可以很方便的通过req参数来存储和访问session对象的数据。req.session是一个JSON格式的JavaScript对象,我们可以在使用的过程中随意的增加成员,这些成员会自动的被保存到option参数指定的地方,默认即为内存中去。

session的生命周期

session与发送到客户端浏览器的生命周期是一致的。而我们在挂载session的时候,通过option选项的cookie.maxAge成员,我们可以设置session的过期时间,以ms为单位(但是,如果session存储在mongodb中的话,任何低于60s(60000ms)的设置是没有用的,下文会有详细的解释)。如果maxAge不设置,默认为null,这样的expire的时间就是浏览器的关闭时间,即每次关闭浏览器的时候,session都会失效。

express框架之session 数据库存储

有时候,我们需要session的声明周期要长一点,比如好多网站有个免密码两周内自动登录的功能。基于这个需求,session必须寻找内存之外的存储载体,数据库能提供完美的解决方案。这里,我选用的是mongodb数据库,作为一个NoSQL数据库,它的基础数据对象时database-collection-document 对象模型非常直观并易于理解,针对node.js 也提供了丰富的驱动和API。express框架提供了针对mongodb的中间件:connect-mongo,我们只需在挂载session的时候在options中传入mongodb的参数即可,程序运行的时候, express app 会自动的替我们管理session的存储,更新和删除。具体可以参考:
https://github.com/kcbanner/connect-mongo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var express = require('express');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var MongoStore = require('connect-mongo')(session);
var app = express();

app.use(cookieParser());
app.use(session({
secret: '12345',
name: 'testapp',
cookie: {maxAge: 80000 },
resave: false,
saveUninitialized: true,
store: new MongoStore({ //创建新的mongodb数据库
host: 'localhost', //数据库的地址,本机的话就是127.0.0.1,也可以是网络主机
port: 27017, //数据库的端口号
db: 'test-app' //数据库的名称。
})
}));


app.get('/awesome', function(req, res){

if(req.session.lastPage) {
console.log('Last page was: ' + req.session.lastPage + ".");
}
req.session.lastPage = '/awesome';
res.send("You're Awesome. And the session expired time is: " + req.session.cookie.maxAge);
});

app.get('/radical', function(req, res){
if (req.session.lastPage) {
console.log('Last page was: ' + req.session.lastPage + ".");
}
req.session.lastPage = '/radical';
res.send('What a radical visit! And the session expired time is: ' + req.session.cookie.maxAge);
});

app.get('/tubular', function(req, res){
if (req.session.lastPage){
console.log("Last page was: " + req.session.lastPage + ".");
}

req.session.lastPage = '/tubular';
res.send('Are you a suffer? And the session expired time is: ' + req.session.cookie.maxAge);
});


app.listen(5000);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const mongoose = require('mongoose');

// Basic usage
mongoose.connect(connectionOptions);

app.use(session({
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));

// Advanced usage
const connection = mongoose.createConnection(connectionOptions);

app.use(session({
store: new MongoStore({ mongooseConnection: connection })
}));

跟session的内存存储一样,只需增加红色部分的store选项即可,app会自动替我们把session存入到mongodb数据,而非内存中。

session的生命周期:

由于session是存在服务器端数据库的,所以的它的生命周期可以持久化,而不仅限于浏览器关闭的时间。具体是由cookie.maxAge 决定:如果maxAge设定是1个小时,那么从这个因浏览器访问服务器导致session创建开始后,session会一直保存在服务器端,即使浏览器关闭,session也会继续存在。如果此时服务器宕机,只要开机后数据库没发生不可逆转的破坏,maxAge时间没过期,那么session是可以继续保持的。

当maxAge时间过期后,session会自动的数据库中移除,对应的还有浏览器的cookie。不过,由于connect-mongo的特殊机制(每1分钟检查一次过期session),session的移除可能在时间上会有一定的滞后。

connect-mongo uses MongoDB’s TTL collection feature (2.2+) to have mongod automatically remove expired sessions. (mongod runs this check every minute.)

Note: By connect/express’s default, session cookies are set to expire when the user closes their browser (maxAge: null). In accordance with standard industry practices, connect-mongo will set these sessions to expire two weeks from their last ‘set’. You can override this behavior by manually setting the maxAge for your cookies – just keep in mind that any value less than 60 seconds is pointless, as mongod will only delete expired documents in a TTL collection every minute.

当然,由于cookie是由浏览器厂商实现的,cookie不具有跨浏览器的特性,例如,我用firefox浏览器在京东上购物时,勾选了2周内免密码输入,但是当我第一次用IE登陆京东时,同样要重新输入密码。所以,这对服务器的同一个操作,不同的浏览器发起的请求,会产生不同的session-cookie。

CSS3的大多新属性(比如:圆角、阴影、渐变、文字阴影等)在 FF、Chrome、Opera都还支持,但是IE 6-8是一点也不支持的,今天提供PIE.htc解决IE浏览器对CSS3属性的支持问题,让IE也能实现一些常见的CSS3效果,如圆角(border-radius),盒阴影(box-shadow),文字阴影(text-shadow) 背景渐变(gradient),多图片背景(multiple background images)。

htc文件下载地址:http://github.com/lojjic/PIE/downloads

设置css样式

behavior: url(css/PIE/PIE.htc); //PIE.htc文件路径,该文件路径是相对于html页面的文件路径,如果用到.css文件,该文件路径依然是相对于html页面的路径

supervisor进程管理工具,可以在代码修改后自动重启服务,开发环境的选择

安装

cnpm install -g supervisor

启动

Express4.x之前版本

supervisor app.js

Express4.x版本

supervisor .\bin\www

nodemon重启速度比supervisor快

0%