capistrano/sshkit — pull request #70 by mbrictson (2013-12-06 07:06:59+00:00)
Title: Use a connection pool to reuse SSH connections.

Hi,

What do you think of this implementation for reusing SSH connections via a simple connection pool? (In response to #69.)

I tried to minimize the impact to existing code. The changes consist of one new class, `Backend::ConnectionPool`, and a few changed in `netssh.rb`.

I saw that there was a placeholder `connection` method in `Backend::Abstract` for pooling, but I think this implementation is cleaner. I don’t think pooling is something that can be generalized in the superclass. Not to mention the other Backend implementations (`Local`, `Skipper`) have no use for it.

If you think this is a good approach, I can work on adding tests, as well as updating the README and CHANGELOG.

More details from my commit message:

---

Using a connection pool saves time of negotiating a new SSH connection for every SSHKit `on()` block. When testing with a simple capistrano recipe, a `cap deploy` ran 10-15% faster with this connection pool.

By default, an existing pooled connection will be replaced with a new connection if it hasn't been used for more than 30 seconds. This can be changed, e.g.:

```
SSHKit::Backend::Netssh.pool.idle_timeout = 60 # seconds
```

Setting the timeout to 0 will disable pooling (connections will not be reused).

Note that the connection pool will not recover gracefully if a connection somehow "goes bad". For example, if the server closes an idle connection, or if the underlying socket gets reset, a subsequent command sent to that server could fail, and the command will not be retried with a new connection. Therefore it is a good idea to use a conservative (small) value for the idle_timeout.