我正在尝试重用以前建立的websocket连接以避免websocket握手。我发现可以使用build_websocket_tx
(更多细节here)构建自定义websocket事务,并且每个websocket连接都有一个连接标识符,可以使用connection
中定义的子例程来检索它。 1}}(更多细节here)。我可以以某种方式将这两者结合起来重新使用连接吗?还有另一种方法吗?
PS:Websocket连接应该是一致的和可重用的。但是Mojolicoious没有为websocket连接提供任何这样的选择。
没有连接重复使用的示例代码。
Mojo::Transaction
答案 0 :(得分:2)
预备:使用调试信息运行Mojolicious客户端脚本:
MOJO_EVENTEMITTER_DEBUG=1 MOJO_USERAGENT_DEBUG=1 perl mua.pl
截至7.43版,Mojo::UserAgent
有built-in connection pooling但specifically refuses to use it for WebSockets。这可能是因为正如你所说,WebSockets是有状态的,如果UserAgent盲目地重用连接,那么可能会导致混乱。但是,如果您的应用程序知道如何安全地重用它们,那就不同了。
最近在Mojolicious的IRC频道中提出了这个问题,sri, the author, said:
16:28 sri mohawk: some frameworks like phoenix have their own higher level protocol on top of websockets to multiplex multiple channels https://hexdocs.pm/phoenix/channels.html 16:28 sounds like that's what you want 16:28 mojolicious should have something like that, but doesn't yet [...] 16:42 sri it's not hard to build on top of mojolicious, but for now you have to do that yourself 16:42 ultimately i'd hope for us to have it in core, without the message bus part 16:43 but channel management and routing [...] 16:50 jberger mohawk I did write Mojolicious::Plugin::Multiplex which might help 16:51 For an example of a higher level tool
我承认OP说:
我能够重用连接的唯一方法是存储事务对象并在后续调用中使用它。
但是,正如当前的代码所示,这似乎是唯一的方法。此代码演示了如何创建,维护和使用您自己的连接池:
#!/usr/bin/perl
use strict;
use warnings;
use Mojo::UserAgent;
use Time::HiRes qw(time);
$| = 1;
my $REQ = {
type => "ping",
reqid => 0,
};
my $URL = "wss://trello.com/1/Session/socket";
my $SECONDS = 2;
my $POOL_SIZE = 5;
my $ua = Mojo::UserAgent->new;
my @pool;
sub make_conn {
my ($ua, $url, $pool) = @_;
$ua->websocket($URL => sub {
my (undef, $tx) = @_;
die "error: ", $tx->res->error->{message}, "\n" if $tx->res->error;
die 'Not a websocket connection' unless $tx->is_websocket;
push @$pool, $tx;
});
}
# pool gets pushed onto, shifted off, so using recently-used connection
sub send_message {
my ($pool, $request, $start) = @_;
my $tx = shift @$pool;
die "got bad connection" unless $tx; # error checking needs improving
$tx->once(message => sub {
my (undef, $msg) = @_;
print "got back: $msg\n";
print "took: ", time - $start, "\n";
push @$pool, $tx;
});
$tx->send({json => $request});
}
make_conn($ua, $URL, \@pool) for (1..5); # establish pool
# every 2 secs, send a message
my $timer_cb;
$timer_cb = sub {
my $loop = shift;
print "every $SECONDS\n";
send_message(\@pool, $REQ, time);
$loop->timer($SECONDS => $timer_cb);
};
Mojo::IOLoop->timer($SECONDS => $timer_cb);
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
在高层次上,它的工作原理如下:
send_message
使用该池中最近最少使用的连接为了简单起见,它不检查连接从池中获取时是否仍然有效,并依赖于前两秒延迟来初始化所有5个连接。
time
调用的使用证明了使用此池的速度提升。您提供的代码(在我的系统上)大约需要300毫秒来启动连接,然后发送和接收。使用游泳池需要大约120毫秒。