Routes Java Edition connections by the hostname in the handshake, with wildcard domains, backend failover, PROXY protocol v2, cached server-list status from health probes, hot-reloaded config, and an admin page and metrics endpoint. Includes CI, tagged releases and a container image. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e640c5bf02
commit
b53af0e196
29 files changed
+2640
No files matched your search
@@ -0,0 +1,75 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
type serverStats struct {
|
||||
active atomic.Int64
|
||||
total atomic.Int64
|
||||
failures atomic.Int64
|
||||
bytesIn atomic.Int64 // client -> backend
|
||||
bytesOut atomic.Int64 // backend -> client
|
||||
}
|
||||
|
||||
type Stats struct {
|
||||
Started time.Time
|
||||
active atomic.Int64
|
||||
total atomic.Int64
|
||||
rejected atomic.Int64
|
||||
unknown atomic.Int64
|
||||
mu sync.Mutex
|
||||
servers map[string]*serverStats
|
||||
}
|
||||
|
||||
func newStats() *Stats {
|
||||
return &Stats{Started: time.Now(), servers: map[string]*serverStats{}}
|
||||
}
|
||||
|
||||
func (s *Stats) server(name string) *serverStats {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
ss := s.servers[name]
|
||||
if ss == nil {
|
||||
ss = &serverStats{}
|
||||
s.servers[name] = ss
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
type ServerSnapshot struct {
|
||||
Name string `json:"name"`
|
||||
Active int64 `json:"active"`
|
||||
Total int64 `json:"total"`
|
||||
Failures int64 `json:"failures"`
|
||||
BytesIn int64 `json:"bytes_in"`
|
||||
BytesOut int64 `json:"bytes_out"`
|
||||
}
|
||||
|
||||
type Snapshot struct {
|
||||
UptimeSecs int64 `json:"uptime_secs"`
|
||||
Active int64 `json:"active"`
|
||||
Total int64 `json:"total"`
|
||||
Rejected int64 `json:"rejected"`
|
||||
Unknown int64 `json:"unknown_host"`
|
||||
Servers []ServerSnapshot `json:"servers"`
|
||||
}
|
||||
|
||||
func (s *Stats) Snapshot() Snapshot {
|
||||
out := Snapshot{
|
||||
UptimeSecs: int64(time.Since(s.Started).Seconds()),
|
||||
Active: s.active.Load(), Total: s.total.Load(),
|
||||
Rejected: s.rejected.Load(), Unknown: s.unknown.Load(),
|
||||
}
|
||||
s.mu.Lock()
|
||||
for n, ss := range s.servers {
|
||||
out.Servers = append(out.Servers, ServerSnapshot{n, ss.active.Load(), ss.total.Load(),
|
||||
ss.failures.Load(), ss.bytesIn.Load(), ss.bytesOut.Load()})
|
||||
}
|
||||
s.mu.Unlock()
|
||||
sort.Slice(out.Servers, func(i, j int) bool { return out.Servers[i].Name < out.Servers[j].Name })
|
||||
return out
|
||||
}
|
||||
Reference in new issue
Block a user