apache + mod_perl + couchbase = 偶尔出现连接问题

apache + mod_perl + couchbase = occasional connection problems

我们使用 couchbase 作为 mod_perl 脚本的会话存储。为了避免因等待新连接而导致客户端延迟,我们在 child_init apache 阶段预连接到 couchbase。因此,在 apache 重新启动/新 child 创建过程中,它会自动连接到 couchbase,然后在 apche child 生命周期内使用该连接。

通常一切正常,但有时我们在预连接期间遇到以下错误:

Couldn't connect: 0x13 (Operation not supported) at /perl/lib64/perl5/Couchbase/Bucket.pm line 38.

通常它出现在 apache 重启期间和几个(或几十个)childs 上,几乎从来没有出现在一个 child 上。通常再次重启apache即可解决问题。

什么会导致这样的问题?是不是代码/服务器配置/couchbase服务器本身的问题?

可能是由于某种原因同时重新连接了很多?一些 ulimits 东西/或 selinux 限制?

更新: 版本

OS:
 Centos 6, 2.6.32-358.2.1.el6.x86_64

libcouchbase:
 libcouchbase-devel.x86_64  2.4.7-1.el6
 libcouchbase2-core.x86_64 2.4.7-1.el6
 libcouchbase2-libevent.x86_64 2.4.7-1.el6

couchbase server:
 2.2.0 community edition (build-837)

SDK:
 perl  (Couchbase::Core v2.0.2)

连接代码(隔离和简化):

# in mod_perl environment
use Couchbase;
use Couchbase::Bucket;
use Couchbase::Document;
use Apache2::ServerUtil ();

my $cb = undef; 
# connection handler, initialized once, used during apache child lifetime

sub connect_couchbase_on_child_init {
    my ($child_pool, $s) = @_; 
    my $dsn = 'couchbase://192.168.0.1,192.168.0.2/my_bucket_name?detailed_errcodes=1';
    eval { $cb = Couchbase::Bucket->new($dsn); };
    # here we get the occasional warnings during apache restarts
    if ($@) { warn "COUCHBASE CONNECTION ERROR! $@"; $cb = undef; } 
    return Apache2::Const::OK;
}

Apache2::ServerUtil->server->push_handlers(PerlChildInitHandler => \&connect_couchbase_on_child_init);

# in request handlers it used with the following calls (only if connected):
# $doc = Couchbase::Document->new($key);
# $cb->get($doc);
# ...   
# $cb->replace($doc);
# ... 
# $cb->insert($doc);
# ...
# $cb->remove($doc);

因为您使用的是服务器 2.2.0,而且当您同时连接多个客户端时似乎会发生这种情况,我的理论是您收到了来自服务器的最后一个错误。当前客户端 bootstrap 进程尝试使用 bootstrap 而不是 memcached(仅支持版本 >= 2.5.0 的服务器),失败并尝试使用 'terse' bootstrapping(同样,仅在服务器的 >= 2.5.0 上支持),最后是 'classic' HTTP(所有版本都可用)。

将以下选项添加到您的 DSN/connection 字符串中,为您的服务器删除一些步骤。请注意,如果您升级到 >= 2.5,则应删除这些选项:

  • bootstrap_on=http 不尝试 memcached bootstrap
  • http_urlmode=2 默认使用 bootstrapping 的 pre-2.5 风格

这两个选项不一定会解决你的问题,但它们至少会减少一些初始连接时间,并且可能会显示更清楚的错误原因(你也可以在环境中设置 LCB_LOGLEVEL=5 以获得实际日志记录)。

在您的情况下,连接字符串为:

couchbase://192.168.0.1,192.168.0.2/my_bucket_name?detailed_errcodes=1&bootstrap_on=http&http_urlmode=2