跳到主要内容

将 mongodb 安装为 windows 服务

· 阅读需 1 分钟

将mongodb安装为windows服务。

cmd中cd到mongodb的bin目录下,执行以下指令

mongod
--install
--serviceName MongoDB
--serviceDisplayName MongoDB
--logpath D:\MongoDB\logs\MongoDB.log
--dbpath D:\MongoDB\data
--directoryperdb
--journal
--storageEngine=mmapv1

支付宝和微信支付一点感想(9.18更新)

· 阅读需 5 分钟

两边肯定是都有开发文档的,只要签约了之后都会拿到相应的秘钥之类的。

感觉把,支付宝的文档还是比较详细的,而且他们做的事不用说还是比较多的。

举例,支付宝的可以点击按钮跳过去付款再用你给的return_url跳到你的系统过去,或者是加个参数,变成扫码支付,扫完之后付款然后再跳转页面,可以说基本你按他的文档把参数拼接好了之后基本不需要多操心了,而且回调也是query parameter的方式,比较好解析。

微信,我用的扫码支付二(这种扫码直接支付的),感觉挺麻烦的。 首先,交互采用的xml的方式,对于node.js来说不是很友好,发送的时候要拼接一次,接收的时候要解析一次,而且,只是返回一个地址,还要自己生成二维码,扫了之后也没有后续操作了。

我看那个扫码支付模式一台麻烦就没弄,有时间再看看。

唉,不过没办法,两种都要接。


9.18

相当坑,微信支付的notify_url也就是异步的通知接口,必须你这边的地址是走https协议的,所以我放弃了。

只能在微信支付的页面的跳转按钮做手脚了,大致步骤如下:

  1. 扫码后,点击跳转到我的订单,实际上我在中间加了一层
  2. 通过查询接口去查询订单的情况,根据结果来更新你的订单信息
  3. 再跳转到订单列表去

暂时没想到更好的解决方案了,看到过别人有说轮训,对我来说好像不大好实现

sails model 生命周期回调

· 阅读需 2 分钟

1、创建时的回调

beforeValidate: fn(values, cb)
afterValidate: fn(values, cb)
beforeCreate: fn(values, cb)
afterCreate: fn(newlyInsertedRecord, cb)

2、修改的时候回调

beforeValidate: fn(valuesToUpdate, cb)
afterValidate: fn(valuesToUpdate, cb)
beforeUpdate: fn(valuesToUpdate, cb)
afterUpdate: fn(updatedRecord, cb)

3、销毁的时候回调

beforeDestroy: fn(criteria, cb)
afterDestroy: fn(destroyedRecords, cb)

如在创建用户的时候对密码机密操作:

var bcrypt = require('bcrypt');

module.exports = {
attributes: {
username: {
type: 'string',
required: true
},
password: {
type: 'string',
minLength: 6,
required: true,
columnName: 'encrypted_password'
}
},
beforeCreate: function (values, cb) {
bcrypt.hash(values.password, 10, function(err, hash) {
if(err) return cb(err);
values.password = hash;
cb();
});
}
};

sails 使用 connect-redis 存储 session 的一个小坑

· 阅读需 1 分钟

我在config/session中添加session配置的时候,提示我需要安装connect-redis

安装完后启动发现报错,如下信息:

Could not load Connect session adapter :: connect-redis
A hook (`session`) failed to load!

后来搜到github上的issue发现,还只能使用v1.4.5版本的,于是我切换到1.4.5的,启动就没报错了。

https://github.com/balderdashy/sails/issues/2379

sails 中使用事务

· 阅读需 2 分钟

解决的思路主要还是使用原生的方式打开一个事务。

下面是在stackoverflow上的一个帖子的答案

http://stackoverflow.com/questions/25079408/how-to-handle-async-concurrent-requests-correctly/25100188#25100188

buyItem: function(req, res) {
try {
// Start the transaction
User.query("BEGIN", function(err) {
if (err) {throw new Error(err);}
// Find the user
User.findOne(req.param("userId").exec(function(err, user) {
if (err) {throw new Error(err);}
// Update the user balance
user.balance = user.balance - req.param("itemCost");
// Save the user
user.save(function(err) {
if (err) {throw new Error(err);}
// Commit the transaction
User.query("COMMIT", function(err) {
if (err) {throw new Error(err);}
// Display the updated user
res.json(user);
});
});
});
});
}
// If there are any problems, roll back the transaction
catch(e) {
User.query("ROLLBACK", function(err) {
// The rollback failed--Catastrophic error!
if (err) {return res.serverError(err);}
// Return the error that resulted in the rollback
return res.serverError(e);
});
}
}

不过提个建议就是,这种写法的风格不好,建议改成promise方式

还有个npm模块是在sails-mysql基础上封装了事务 https://github.com/postmanlabs/sails-mysql-transactions

node.js sails框架同步表的坑

· 阅读需 2 分钟

错误信息

以下是报的错误

error: Error: The hook `orm` is taking too long to load.
Make sure it is triggering its `initialize()` callback, or else set `sails.config.orm._hookTimeout to a higher value (currently 20000)
at tooLong [as _onTimeout] (C:\Users\KAMI\AppData\Roaming\npm\node_modules\sails\lib\app\private\loadHooks.js:92:21)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15

解决方案

在config目录下创建两个文件,orm和pubsub,不过据回答的作者说是名字并不重要。

// config/orm.js
module.exports.orm = {
_hookTimeout: 60000 // I used 60 seconds as my new timeout
};
// config/pubsub.js
module.exports.pubsub = {
_hookTimeout: 60000 // I used 60 seconds as my new timeout
};

不建议直接在 node_modules 中修改

原问题地址:http://stackoverflow.com/questions/28524926/the-hook-orm-taking-too-long-to-load

语义化版本控制

· 阅读需 2 分钟

简介

在软件管理的领域里存在着被称作“依赖地狱”的死亡之谷,系统规模越大,加入的套件越多,你就越有可能在未来的某一天发现自己已深陷绝望之中。

摘要

版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

  1. 主版本号:当你做了不兼容的API 修改,
  2. 次版本号:当你做了向下兼容的功能性新增,
  3. 修订号:当你做了向下兼容的问题修正。

先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

http://semver.org/lang/zh-CN/

新浪微博的时间是怎么实时变化的

· 阅读需 7 分钟

由来

那时候还很无知,虽然发现了有这么一个用户体验不错的细节,可惜开动了小脑经也并不知道怎么玩的。

场景

地点:新浪微博 事件:发现每条微博的时间都会不断的自己变咧!这样就算你放了N久,也会知道这条微博是到底什么时候发的,不用再去刷新页面了。

问题

是怎么能实现批量更新时间的呢? 通常都是在服务端查询后根据时间算出对应的人性化时间,“几秒前”“*分钟前”等等。 而这样的字符串是很难再哪来二次计算的。

分析

时间的代码片段

上面是时间的代码片段,简单看一下,跟时间有关系的属性,只有titledatenode-tpye,这三个属性:

  • title 从值看来是年月日时分的格式化后的字符串
  • date 时间戳
  • node-type 从值来看应该算是表示了某一类的类名

通常来讲,用时间戳来计算是最方便的,因为他是以毫秒为单位,而天、时、分、秒都可以用毫秒来表示,而超过了某个单位的最大值,比如一分钟前的微博,用现在的时间戳减去之前的时间戳,大于60000毫秒的话,那么肯定就是一分钟前了。

而找到这些元素只需要通过找到node-type属性为feed_list_item_date的元素再获取date属性计算后改变即可。

这里我是尝试了一下把feed_list_item_date改为feed_list_item_date1他的时间就不变了,而其他的已然在周期性的变化,改回去之后又在周期的变化。


补充

然而有个事被我差点忘记了,就是这个title属性,为毛没有讲是干啥用的,我开始也没想明白,而后来我看到了这个 时间格式化

我好像有点明白了,我又观察了一下,在一个小时内,时间是会显示xx分钟前的,但是超过了一个小时之后,时间就会变成今天 13:00, 昨天 13:008月20日 13:00这个样子了,那么这个title感觉很好解释了,超过1小时候拿这title来替换掉其中的yyyy-MM-dd部分,就成了稍微久远点的人性化时间。

总结

其实一些不错的产品很值得琢磨的,不管是用户体验也好,优化也好

mongodb从2.6迁移到3.0过程

· 阅读需 11 分钟

总共有这么几个问题需要解决:

  1. mongodb3.0版本的二进制包
  2. wiredTiger引擎的配置
  3. 数据的迁移
  4. 权限

mongodb3.0的二进制包

这个就不用多说了,直接去官网选择对应的系统下载就好 https://www.mongodb.org/downloads 我是centos 6.3,对应的发行版貌似是redhat6.x,所以选择的redhat6 64bit

wiredTiger引擎的配置

官方给的例子是以yaml形式写的配置,我还是以conf文件形式,所以就在后面追加了一个选项就可以了。当然我是重建的库路径,如果原有的数据路径的话,启用wiredTiger是会报错的。这就是下面要说的一个部分。

dbpath=/your/data/path
logpath=/your/log/path
logappend=true
bind_ip = 127.0.0.1
auth = true
port = 27017
journal = true
#fork=true
storageEngine=wiredTiger

数据的迁移

由于需要换引擎,所以原来的数据不能直接使用了,必须使用monogodumpmongorestore两个工具来迁移数据。 具体操作可以参见这篇文章 通过mongodump和mongorestore实现Mongodb备份和恢复

权限

那么将数据导入之后,如果需要设置权限的话,首先是需要admin库中创建一个user的,还是先把auth=true给注释掉了,创建个用户,到这里懵逼了一下,提示addUser方法错误,查了一下发现,3.0的用户及权限有些改变。

定义

创建一个数据库新用户用db.createUser()方法,如果用户存在则返回一个用户重复错误。

语法

db.createUser(user, writeConcern)

  • user这个文档创建关于用户的身份认证和访问信息;
  • writeConcern这个文档描述保证MongoDB提供写操作的成功报告。

· user文档,定义了用户的以下形式:

{ user: "<name>",
pwd: "<cleartext password>",
customData: { <any information> },
roles: [
{ role: "<role>", db: "<database>" } | "<role>",
...
]
}

user文档字段介绍:

  • user字段,为新用户的名字;
  • pwd字段,用户的密码;
  • cusomData字段,为任意内容,例如可以为用户全名介绍;
  • roles字段,指定用户的角色,可以用一个空数组给新用户设定空角色; 在roles字段,可以指定内置角色和用户定义的角色。

Built-In Roles内置角色

  1. 数据库用户角色:read、readWrite;
  2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;
  3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
  4. 备份恢复角色:backup、restore;
  5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
  6. 超级用户角色:root // 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)
  7. 内部角色:__system PS:关于每个角色所拥有的操作权限可以点击上面的内置角色链接查看详情。

writeConcern文档 官方说明

  • w选项:允许的值分别是 1、0、大于1的值、"majority"、<tag set>
  • j选项:确保mongod实例写数据到磁盘上的journal(日志),这可以确保mongd以外关闭不会丢失数据。设置true启用。
  • wtimeout:指定一个时间限制,以毫秒为单位。wtimeout只适用于w值大于1。

例如:在products数据库创建用户accountAdmin01,并给该用户admin数据库上clusterAdmin和readAnyDatabase的角色,products数据库上readWrite角色。

use products
db.createUser( { "user" : "accountAdmin01",
"pwd": "cleartext password",
"customData" : { employeeId: 12345 },
"roles" : [ { role: "clusterAdmin", db: "admin" },
{ role: "readAnyDatabase", db: "admin" },
"readWrite"
] },
{ w: "majority" , wtimeout: 5000 } )

以上是新版本用户、角色、权限的一些说明。

看看我们现在要做的: 先创建个管理员

use admin
db.createUser(
{
user: "adminuser",
pwd: "12345678",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)

再创建我们应用库的用户

use appdb
db.createUser(
{
user: "luoyjx",
pwd: "12345678",
roles: [
{ role: "readWrite", db: "appdb" }
]
}
)

使用db.auth(username,pwd)可以验证一下

创建用户大概到这里了,创建完admin,再创建一个普通用户就基本OK了。

到这里,单实例的mongodb从2.6迁移到3.0就基本完成了。

TODO

副本集(没有折腾)