502 bad gateway error when deploy rails app with dokku on digitalocean

Follow this how-to-use-the-dokku-one-click-digitalocean-image-to-run-a-ruby-on-rails-app guide, i got nginx error – ’502 bad gateway’.

How to solve?

first, check app logs to see what happen.

dokku logs <your-app-name>

I got DATABASE_URL error. it seems dokku didn’t link my app with PostgreSQL.

Checkout the PostgreSQL database_url:

dokku postgresql:info <your-app-name>

Host: xxxxxx
Port: 49154
User: 'root'
Password: '*********'
Database: 'db'

Url: 'postgres://root:*******@xxxxx:49154/db'

now link this url with my app:

dokku postgresql:link <your-app-name> <your-db-name>

or

dokku config:set <your-app-name> DATABASE_URL='postgres://root:*******@xxxxx:49154/db'

git push again, got db:migration error!

rake manually according to this gist:

docker run -i -t app/mg /bin/bash

cd app/
export HOME=/app
for file in /app/.profile.d/*; do source $file; done
hash -r
cd /app
RAILS_ENV=production rake db:migrate

DONE! push again, it works.

[mongodb]tcmalloc: large alloc out of memory, printing stack and exiting

最近Mongodb会经常突然挂掉,检查日志发现如下的错误:

tcmalloc: large alloc 2061584302080 bytes == (nil) @
Tue Nov 26 17:45:04.539 out of memory, printing stack and exiting:
0xdddd81 0x6cfb4e 0x121021d 0xafcc1f 0xaf815f 0xaf8d1d 0xaf8e0f 0xaf52ae 0xaf53c9 0xb1eb11 0x8ab6a2 0x8d78ca 0x8d951d 0x8daa72 0xa80970 0xa8523c 0x9f9079 0x9fa5a3 0x6e8b88 0xdca34e
 ./mongod(_ZN5mongo15printStackTraceERSo+0x21) [0xdddd81]
 ./mongod(_ZN5mongo14my_new_handlerEv+0x3e) [0x6cfb4e]
 ./mongod(_Znwm+0x6d) [0x121021d]
 ./mongod(_ZNSt6vectorIN5mongo18DocumentSourceSort9KeyAndDocESaIS2_EE7reserveEm+0x6f) [0xafcc1f]
 ./mongod(_ZN5mongo18DocumentSourceSort12populateTopKEv+0x6f) [0xaf815f]
 ./mongod(_ZN5mongo18DocumentSourceSort8populateEv+0x2d) [0xaf8d1d]
 ./mongod(_ZN5mongo18DocumentSourceSort3eofEv+0xf) [0xaf8e0f]
 ./mongod(_ZN5mongo18DocumentSourceSkip7skipperEv+0x6e) [0xaf52ae]
 ./mongod(_ZN5mongo18DocumentSourceSkip3eofEv+0x9) [0xaf53c9]
 ./mongod(_ZN5mongo8Pipeline3runERNS_14BSONObjBuilderERSs+0x1b1) [0xb1eb11]
 ./mongod(_ZN5mongo15PipelineCommand3runERKSsRNS_7BSONObjEiRSsRNS_14BSONObjBuilderEb+0x132) [0x8ab6a2]
 ./mongod(_ZN5mongo12_execCommandEPNS_7CommandERKSsRNS_7BSONObjEiRSsRNS_14BSONObjBuilderEb+0x3a) [0x8d78ca]
 ./mongod(_ZN5mongo7Command11execCommandEPS0_RNS_6ClientEiPKcRNS_7BSONObjERNS_14BSONObjBuilderEb+0x71d) [0x8d951d]
 ./mongod(_ZN5mongo12_runCommandsEPKcRNS_7BSONObjERNS_11_BufBuilderINS_16TrivialAllocatorEEERNS_14BSONObjBuilderEbi+0x5f2) [0x8daa72]
 ./mongod(_ZN5mongo11runCommandsEPKcRNS_7BSONObjERNS_5CurOpERNS_11_BufBuilderINS_16TrivialAllocatorEEERNS_14BSONObjBuilderEbi+0x40) [0xa80970]
 ./mongod(_ZN5mongo8runQueryERNS_7MessageERNS_12QueryMessageERNS_5CurOpES1_+0xd7c) [0xa8523c]
 ./mongod() [0x9f9079]
 ./mongod(_ZN5mongo16assembleResponseERNS_7MessageERNS_10DbResponseERKNS_11HostAndPortE+0x383) [0x9fa5a3]
 ./mongod(_ZN5mongo16MyMessageHandler7processERNS_7MessageEPNS_21AbstractMessagingPortEPNS_9LastErrorE+0x98) [0x6e8b88]
 ./mongod(_ZN5mongo17PortMessageServer17handleIncomingMsgEPv+0x42e) [0xdca34e]

内存溢出了,一开始我以为是有些排序没有加索引,后来一些地方加了索引后还是会出现,细想了下,如果是没加索引的话,是不会让整个Mongodb宕机的。

后来在Mongodb的issue上查到了这样一条提交的bug清单SERVER-10136

原来aggregation如果传递一个$skip特别大的值的时候,就会内存溢出。我看到这个bug已经被修复了,不过是在2.5.2版本,最新的稳定版是2.4.8。所以我们需要在自己的应用程序里面控制,让$skip的值不要超出总长。

[mongodb]exception: $concat only supports strings, not NumberInt32

今天在用mongodb操作aggregation的时候出现这个问题,我是想格式化日期,例如”2013-10-17 04:41:37 UTC”变成”10月17日”,

'fdate' => { '$concat' => ['$date.month', '月', '$date.day', '日'] }

出现 exception: $concat only supports strings, not NumberInt32

原来$concat只能操作字符串,不支持数字类型,解决办法是用$substr

$date形如’2013-10-13 11:17:18 UTC’

'fdate' => { '$concat' => [ {$substr=>['$date', 5, 2]}, '月', {$substr=>['$date', 8, 2]}, '日'] }

$substr接受两个参数,一个是字符串的起点,一个是截取的字符串的长度。

再看mongodb的分组group

在之前的记一次Mongodb性能调优文章中,最后使用了aggregation来做聚合查询,今天又有一个新的需求,需要在之前按日期聚合的基础上再按照店铺来聚合(说实话,到这里已经感觉到非关系数据库这方面的弱势了)。

幸运的是aggregation的操作其实是类似于管道(pipeline),可以进行多次group,这样就方便多次处理数据,得到想要的结果。

def diary_with_shop(opts = {})
  page       = opts[:page] || 1
  per_page   = opts[:per_page] || 20
  conditions = [{'$match' => {user_id: self.id, deleted_at: nil}}]
  conditions << {'$project' => {
    'year'  => {'$year'      => '$created_at'},
    'month' => {'$month'     => '$created_at'},
    'day'   => {'$dayOfYear' => '$created_at'},
    'date'  => '$created_at', 'shop_id' => 1
  }}
  conditions << {'$group' => {
    '_id' => {
      'year' => '$year', 'month' => '$month', 'day' => '$day', 'shop_id' => '$shop_id'
    },
      'date'  => { '$min' => '$date' },
      'food_stories' => { '$push' => '$_id' }
    }}
  conditions << {'$group' => {
    '_id'   => {
      'year' => '$_id.year', 'month' => '$_id.month', 'day' => '$_id.day'
     },
    'date'  => { '$min' => '$date' },
    'shops' => { '$push' => { 'shop_id' => '$_id.shop_id', 'food_stories' => '$food_stories' } }
  }}
  conditions << {'$sort'  => {'date' => -1}}
  conditions << {'$skip'  => (page.to_i - 1)*per_page.to_i}
  conditions << {'$limit' => per_page.to_i}
  Model.collection.aggregate(conditions)
end

如果对比上次的代码,可以发现这里多了一个group操作,第一个group的`_id`带上了shop_id,带上的shop_id在第二个group中又进行了分组,最后得到想要的结果。

在这里,shop只是id,如果想返回shop的名字,可以用类似于关系型数据库的join操作吗?

答案是不行,文档型数据库只能操作一个collection。那如果想得到shop_name,难道需要再次查询吗?尽量不要这样,这样会丧失aggregation的性能,所以如果你有字段在collection中没有,那么—

最好的办法就是直接复制加上去,不用考虑数据库的冗余,这样才能发挥文档型数据库的优势。

其实每个数据库都不可能取代另一个数据库,只有把数据库自有的特点发挥出来,才能达到性能的最大化,所以如果mongodb里面有很多的外键关联,那么可以考虑是否数据库的设计偏离了mongodb的本质。

Mavericks mac 10.9 gem install json 1.8.1 error failed

升级到最新的mac os Mavericks。装json出现错误:

gem install json -v '1.8.1'


Building native extensions.  This could take a while...
ERROR:  Error installing json:
  ERROR: Failed to build gem native extension.

    /usr/local/var/rbenv/versions/2.0.0-p247/bin/ruby extconf.rb
creating Makefile

make "DESTDIR="
compiling generator.c
In file included from /usr/local/var/rbenv/versions/2.0.0-p247/include/ruby-2.0.0/ruby.h:33,
                 from ../fbuffer/fbuffer.h:5,
                 from generator.c:1:
/usr/local/var/rbenv/versions/2.0.0-p247/include/ruby-2.0.0/ruby/ruby.h:51:21: error: string.h: No such file or directory
/usr/local/var/rbenv/versions/2.0.0-p247/include/ruby-2.0.0/ruby/ruby.h:61:21: error: stdint.h: No such file or directory
/usr/local/var/rbenv/versions/2.0.0-p247/include/ruby-2.0.0/ruby/ruby.h:64:23: error: inttypes.h: No such file or directory
/usr/local/var/rbenv/versions/2.0.0-p247/include/ruby-2.0.0/ruby/ruby.h:68:19: error: stdio.h: No such file or directory

解决办法:

xcode-select --install

需要重新安装Command Line Developer Tools

参考链接installing-rails-on-mavericks

[2013-11-29]修改:
如果这个办法还是不行,mac下需要安装下apple-gcc42

brew install apple-gcc42

注意brew 0.9.4应该是不带apple-gcc42的源的,可以使用brew doctor检查下是否和Mavericks兼容,这里需要升级

brew update