Skip to content

Commit 04048e4

Browse files
authored
Merge pull request #3224 from openziti/add-router-initializers
Add some router lifecycle eventing and do some router startup cleanup
2 parents e01944a + 781d760 commit 04048e4

File tree

15 files changed

+333
-192
lines changed

15 files changed

+333
-192
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ problem.
3535
* github.com/openziti/storage: [v0.4.22 -> v0.4.26](https://github.com/openziti/storage/compare/v0.4.22...v0.4.26)
3636
* github.com/openziti/transport/v2: [v2.0.183 -> v2.0.188](https://github.com/openziti/transport/compare/v2.0.183...v2.0.188)
3737
* github.com/openziti/ziti: [v1.6.7 -> v1.6.8](https://github.com/openziti/ziti/compare/v1.6.7...v1.6.8)
38+
* [Issue #3207](https://github.com/openziti/ziti/issues/3207) - Allow router embedders to customize config before start
39+
* [Issue #3241](https://github.com/openziti/ziti/issues/3241) - Disconnecting Routers May Have Nil Fingerprint, causes panic
40+
* [Issue #3248](https://github.com/openziti/ziti/issues/3248) - let cluster agent also support unix domain sockets
3841
* [Issue #3219](https://github.com/openziti/ziti/issues/3219) - AuthenticatorManager ReadByFingerprint/Username should use indexes
3942
* [Issue #3225](https://github.com/openziti/ziti/issues/3225) - JWT edge sessions should generate events
4043
* [Issue #3245](https://github.com/openziti/ziti/issues/3245) - Revocation time check is checking wrong entity

router/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Ziti Router Components
2+
3+
This document describes the key components of the Ziti router architecture.
4+
5+
## Core Components
6+
7+
### NetworkControllers
8+
Manages connections to Ziti controllers. Handles controller discovery, connection establishment, failover, and maintains heartbeats. Routes control plane messages between the router and controllers.
9+
10+
### Link Registry
11+
Maintains the registry of active links to other routers in the mesh. Tracks link states, manages link lifecycle, and provides link lookup capabilities for routing decisions.
12+
13+
### Forwarder
14+
The packet forwarding engine that routes data between xgress instances. Delivers payloads to links,
15+
xgress instances or edge forwarders.
16+
17+
### Faulter
18+
Monitors link health and detects failures. Automatically reports link faults to controllers and triggers link recovery processes when connectivity issues are detected.
19+
20+
### Scanner
21+
Continuously scans the forwarder's state to detect and clean up stale forwarding entries. Removes inactive circuits and performs periodic maintenance of the forwarding tables.
22+
23+
## Data Plane Components
24+
25+
### Xgress Components
26+
Handle ingress and egress traffic for the router:
27+
28+
- **Xgress Listeners**: Accept incoming connections from clients and services
29+
- **Xgress Dialers**: Establish outbound connections to services
30+
- **Xgress Factories**: Create protocol-specific xgress instances (edge, transport, proxy, tunnel)
31+
- **Xgress Registry**: Global registry managing all xgress factory types
32+
33+
### Xgress Types
34+
- `edge`: Handles Ziti SDK connections
35+
- `transport`: Router-to-router communication
36+
- `proxy`: TCP/UDP proxy connections
37+
- `tunnel`: Intercepted traffic from tunneling clients
38+
39+
## Metrics
40+
Comprehensive metrics collection covering:
41+
- Link latency and throughput
42+
- Xgress connection statistics
43+
- Pool utilization (link dialer, egress dialer, rate limiter)
44+
45+
All metrics are reported to controllers and available via health check APIs.

router/agent.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import (
44
"bufio"
55
"bytes"
66
"fmt"
7+
"io"
8+
"net"
9+
"os"
10+
"time"
11+
712
"github.com/michaelquigley/pfxlog"
813
"github.com/openziti/channel/v4"
914
"github.com/openziti/ziti/common/handler_common"
@@ -12,14 +17,11 @@ import (
1217
"github.com/pkg/errors"
1318
"github.com/sirupsen/logrus"
1419
"google.golang.org/protobuf/proto"
15-
"io"
16-
"net"
17-
"os"
18-
"time"
1920
)
2021

2122
const (
22-
AgentAppId byte = 2
23+
AgentAppId byte = 2
24+
DumpApiSessions byte = 128
2325
)
2426

2527
func (self *Router) RegisterAgentBindHandler(bindHandler channel.BindHandler) {
@@ -42,6 +44,10 @@ func (self *Router) RegisterDefaultAgentOps(debugEnabled bool) {
4244
}
4345
return nil
4446
}))
47+
48+
if debugEnabled {
49+
self.RegisterAgentOp(DumpApiSessions, self.GetStateManager().DumpApiSessions)
50+
}
4551
}
4652

4753
func (self *Router) RegisterAgentOp(opId byte, f func(c *bufio.ReadWriter) error) {

router/debugops/debugops.go

Lines changed: 0 additions & 15 deletions
This file was deleted.

router/env/env.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package env
1818

1919
import (
20+
"time"
21+
2022
"github.com/openziti/channel/v4"
2123
"github.com/openziti/foundation/v2/goroutines"
2224
"github.com/openziti/foundation/v2/rate"
@@ -27,7 +29,6 @@ import (
2729
"github.com/openziti/ziti/common"
2830
"github.com/openziti/ziti/common/config"
2931
"github.com/openziti/ziti/router/xlink"
30-
"time"
3132
)
3233

3334
type RouterEnv interface {

router/lifecycle.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package router
2+
3+
import (
4+
"github.com/openziti/foundation/v2/concurrenz"
5+
"github.com/openziti/ziti/router/env"
6+
)
7+
8+
// LifecycleEvent represents different phases in the router's lifecycle.
9+
// Events are fired during router startup and shutdown to allow external
10+
// components to hook into the router's lifecycle.
11+
type LifecycleEvent int
12+
13+
const (
14+
// LifecycleEventConfigLoaded is fired when the router's Create() method is called,
15+
// before the router instance is created. This allows listeners to modify the
16+
// router configuration before the router is instantiated.
17+
LifecycleEventConfigLoaded LifecycleEvent = iota
18+
19+
// LifecycleEventStart is fired when the router's Start() method is called,
20+
// before any initialization logic begins. This allows listeners to perform
21+
// setup operations or modify the router configuration before startup.
22+
LifecycleEventStart
23+
)
24+
25+
// LifecycleListener defines the interface for components that want to receive
26+
// notifications about router lifecycle events. Implementations should be
27+
// thread-safe as they may be called concurrently.
28+
type LifecycleListener interface {
29+
// OnLifecycleEvent is called when a lifecycle event occurs.
30+
// The event parameter indicates which lifecycle phase is occurring.
31+
// The router parameter provides access to the router instance. This will be nil
32+
// for LifecycleEventConfigLoaded since the router has not been created yet.
33+
// The config parameter provides access to the router configuration.
34+
OnLifecycleEvent(event LifecycleEvent, router *Router, config *env.Config)
35+
}
36+
37+
// LifecycleNotifier manages a collection of lifecycle listeners and provides
38+
// methods to notify them of router lifecycle events. It uses a thread-safe
39+
// copy-on-write slice to store listeners, allowing concurrent access during
40+
// event notification.
41+
type LifecycleNotifier struct {
42+
listeners concurrenz.CopyOnWriteSlice[LifecycleListener]
43+
}
44+
45+
// NewLifecycleNotifier creates a new lifecycle notifier with an empty listener list.
46+
func NewLifecycleNotifier() *LifecycleNotifier {
47+
return &LifecycleNotifier{}
48+
}
49+
50+
// AddListener registers a new lifecycle listener. The listener will receive
51+
// notifications for all future lifecycle events. This method is thread-safe
52+
// and can be called concurrently with NotifyListeners.
53+
func (ln *LifecycleNotifier) AddListener(listener LifecycleListener) {
54+
ln.listeners.Append(listener)
55+
}
56+
57+
// NotifyListeners sends a lifecycle event notification to all registered listeners.
58+
// Listeners are called synchronously in the order they were registered.
59+
// If a listener panics, the panic will propagate and prevent subsequent
60+
// listeners from being notified.
61+
func (ln *LifecycleNotifier) NotifyListeners(event LifecycleEvent, router *Router, config *env.Config) {
62+
for _, listener := range ln.listeners.Value() {
63+
listener.OnLifecycleEvent(event, router, config)
64+
}
65+
}
66+
67+
// GlobalLifecycleNotifier is the default lifecycle notifier instance used by
68+
// the router. External components can register listeners with this global
69+
// instance to receive router lifecycle events.
70+
//
71+
// Example usage:
72+
//
73+
// router.GlobalLifecycleNotifier.AddListener(myListener)
74+
var GlobalLifecycleNotifier = NewLifecycleNotifier()

0 commit comments

Comments
 (0)