You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.1 KiB
89 lines
2.1 KiB
package simulation |
|
|
|
import ( |
|
"math/rand" |
|
) |
|
|
|
type CDNNode struct { |
|
ID string |
|
Label string |
|
TTL int |
|
GeoReplication string |
|
CachingStrategy string |
|
Compression string |
|
HTTP2 string |
|
CacheHitRate float64 // % of requests served from edge cache |
|
CurrentLoad int // optional: can track active queue length |
|
Queue []*Request // incoming request queue |
|
EdgeNodes map[string]*CDNNode // future expansion: simulate geographic edge clusters |
|
Alive bool |
|
Targets []string |
|
output []*Request // cache HIT responses |
|
missQueue []*Request // cache MISSes to forward |
|
} |
|
|
|
func (n *CDNNode) GetID() string { return n.ID } |
|
func (n *CDNNode) Type() string { return "cdn" } |
|
func (n *CDNNode) IsAlive() bool { return n.Alive } |
|
func (n *CDNNode) QueueState() []*Request { return n.Queue } |
|
|
|
func (n *CDNNode) Tick(tick int) { |
|
if len(n.Queue) == 0 { |
|
return |
|
} |
|
|
|
maxProcessPerTick := 10 |
|
processCount := min(len(n.Queue), maxProcessPerTick) |
|
|
|
// Avoid slice leak by reusing a cleared slice |
|
queue := n.Queue |
|
n.Queue = n.Queue[:0] |
|
|
|
for i := 0; i < processCount; i++ { |
|
req := queue[i] |
|
|
|
// Simulate cache hit or miss |
|
hitRate := n.CacheHitRate |
|
if hitRate == 0 { |
|
hitRate = 0.8 // default if unset |
|
} |
|
|
|
if rand.Float64() < hitRate { |
|
// Cache HIT |
|
req.LatencyMS += 5 |
|
req.Path = append(req.Path, n.ID) |
|
n.output = append(n.output, req) |
|
} else { |
|
// Cache MISS |
|
req.LatencyMS += 10 |
|
req.Path = append(req.Path, n.ID+"(miss)") |
|
n.missQueue = append(n.missQueue, req) |
|
} |
|
} |
|
|
|
// Optionally simulate cache expiration every 100 ticks |
|
if tick%100 == 0 { |
|
// e.g., simulate reduced hit rate or TTL expiration |
|
} |
|
} |
|
|
|
func (n *CDNNode) Receive(req *Request) { |
|
if req == nil { |
|
return |
|
} |
|
|
|
geoLatency := rand.Intn(20) + 5 // 5–25ms routing delay |
|
req.LatencyMS += geoLatency |
|
|
|
n.Queue = append(n.Queue, req) |
|
} |
|
|
|
func (n *CDNNode) Emit() []*Request { |
|
out := append(n.output, n.missQueue...) |
|
|
|
// Clear for next tick |
|
n.output = n.output[:0] |
|
n.missQueue = n.missQueue[:0] |
|
|
|
return out |
|
}
|
|
|