Commit Graph

9 Commits

Author SHA1 Message Date
Matthew Holt
6670b5e1cc
Improve handshake logic
- Only load cert from storage (or manager) if allowed to do so  (fix #174)
- Sync cert loading so storage isn't stampeded (fix #185)
- Update dependencies
2023-05-05 20:26:50 -06:00
Matt Holt
b76b76abfc
Replace lego with ACMEz (close #71) (#78) 2020-07-27 16:50:41 -06:00
Matthew Holt
5ed364019b
Add nil check; recover from all goroutines 2020-05-12 09:28:56 -06:00
Matthew Holt
06d8cc766c
Minor improvements to rate limiter
- Constructor blocks until loop() goroutine is actually ready to send
  (this prevents callers from constructing a brand new rate limiter and
  immediately calling Allow() and getting false, even when it should be
  true, just because the goroutine hasn't gotten to its select{} yet)

- Don't treat 0 time as a special case; if a clock is <= unix 0, that's
  potentially a problem, but that would also cause cert validations for
  all TLS connections to fail, so we assume computer clock is correct.
  By removing the special case, we gain some simplicity.
2019-12-16 21:23:11 -07:00
Matthew Holt
ce14d6d76c
Stop timer when rate limiter is stopped 2019-12-16 13:41:32 -07:00
Matthew Holt
1c70bb8ce4 Update rate limiter to allow cancellation; add context to arguments
The previous rate limiter design did not allow reservation cancellation.
This became problematic with lots of config reloads in Caddy for large
numbers of domain names. While the rate limiter had a backlog, a new
config would come in and add even more to the rate limiter, and even
more over time as background maintenance (renewals) kicked in. This
leaked goroutines and memory as a side-effect, and blocked the issuance
of certificates nigh indefinitely.

The new rate limiter does not make future reservations like the previous
one did. However, this requires us to run a single scheduler goroutine
when a rate limiter is created, which requires being cleaned up when the
rate limiter is no longer needed. As rate limits are global and should
live up to the life of the process, there is currently no actual cleanup
that takes place, but if it did happen, one would simply call Stop() on
the rate limiter to stop that goroutine.

With this new design, reservations are made only as the event actually
happens; implementing cancellation with the old design would have been
almost impossible to do correctly in a practical, elegant way. Although
the trade-off is an extra goroutine that needs cleaning up, this is
seldom (if ever?) needed in practice, and the benefit is that waiting
goroutines can be unblocked when their context is canceled. This allows
Caddy, for example, to reload configs often and cancel any goroutines
that were merely waiting on the rate limiter.

Now, all Obtain, Renew, and Revoke calls accept a context that can be
cancelled.

We also eliminate the acmeMu, a mutex that permitted only a single ACME
operation at a time by the process, which was our early, naive form of
rate limiting, which should no longer be necessary.

On-demand obtain and renew do not yet use cancelable contexts, because
what defines the context of a TLS handshake is still unclear. We might
end up using a simple context with a timeout that is the maximum length
of a TLS handshake in practice, say, 1 minute.

This is a breaking change, but critical for larger deployments with very
dynamic configurations.
2019-12-16 13:36:48 -07:00
Matthew Holt
b9cbcfbbbe
ratelimiter: Fix panic when ring size is 0 2019-10-21 11:59:14 -06:00
Matthew Holt
23518b4d6c
ratelimiter: Add Window() and MaxEvents() methods; handle 0 values 2019-10-21 11:48:22 -06:00
Matthew Holt
035d803533 Implement rate limits for new orders (Obtain and Renew)
Also extend exponential backoff in ManageAsync to maximum backoff of
~24 hours, with an abort after ~14 days.
2019-10-21 11:02:05 -06:00