Skip to content

Commit a355b40

Browse files
committed
ethstats: reduce ethstats traffic by trottling reports
1 parent 067dc2c commit a355b40

File tree

1 file changed

+51
-22
lines changed

1 file changed

+51
-22
lines changed

ethstats/ethstats.go

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"time"
3232

3333
"github.com/ethereum/go-ethereum/common"
34+
"github.com/ethereum/go-ethereum/common/mclock"
3435
"github.com/ethereum/go-ethereum/consensus"
3536
"github.com/ethereum/go-ethereum/core"
3637
"github.com/ethereum/go-ethereum/core/types"
@@ -119,7 +120,7 @@ func (s *Service) Stop() error {
119120
// loop keeps trying to connect to the netstats server, reporting chain events
120121
// until termination.
121122
func (s *Service) loop() {
122-
// Subscribe tso chain events to execute updates on
123+
// Subscribe to chain events to execute updates on
123124
var emux *event.TypeMux
124125
if s.eth != nil {
125126
emux = s.eth.EventMux()
@@ -132,6 +133,46 @@ func (s *Service) loop() {
132133
txSub := emux.Subscribe(core.TxPreEvent{})
133134
defer txSub.Unsubscribe()
134135

136+
// Start a goroutine that exhausts the subsciptions to avoid events piling up
137+
var (
138+
quitCh = make(chan struct{})
139+
headCh = make(chan *types.Block, 1)
140+
txCh = make(chan struct{}, 1)
141+
)
142+
go func() {
143+
var lastTx mclock.AbsTime
144+
145+
for {
146+
select {
147+
// Notify of chain head events, but drop if too frequent
148+
case head, ok := <-headSub.Chan():
149+
if !ok { // node stopped
150+
close(quitCh)
151+
return
152+
}
153+
select {
154+
case headCh <- head.Data.(core.ChainHeadEvent).Block:
155+
default:
156+
}
157+
158+
// Notify of new transaction events, but drop if too frequent
159+
case _, ok := <-txSub.Chan():
160+
if !ok { // node stopped
161+
close(quitCh)
162+
return
163+
}
164+
if time.Duration(mclock.Now()-lastTx) < time.Second {
165+
continue
166+
}
167+
lastTx = mclock.Now()
168+
169+
select {
170+
case txCh <- struct{}{}:
171+
default:
172+
}
173+
}
174+
}
175+
}()
135176
// Loop reporting until termination
136177
for {
137178
// Resolve the URL, defaulting to TLS, but falling back to none too
@@ -151,7 +192,7 @@ func (s *Service) loop() {
151192
if conf, err = websocket.NewConfig(url, "http://localhost/"); err != nil {
152193
continue
153194
}
154-
conf.Dialer = &net.Dialer{Timeout: 3 * time.Second}
195+
conf.Dialer = &net.Dialer{Timeout: 5 * time.Second}
155196
if conn, err = websocket.DialConfig(conf); err == nil {
156197
break
157198
}
@@ -181,6 +222,10 @@ func (s *Service) loop() {
181222

182223
for err == nil {
183224
select {
225+
case <-quitCh:
226+
conn.Close()
227+
return
228+
184229
case <-fullReport.C:
185230
if err = s.report(conn); err != nil {
186231
log.Warn("Full stats report failed", "err", err)
@@ -189,30 +234,14 @@ func (s *Service) loop() {
189234
if err = s.reportHistory(conn, list); err != nil {
190235
log.Warn("Requested history report failed", "err", err)
191236
}
192-
case head, ok := <-headSub.Chan():
193-
if !ok { // node stopped
194-
conn.Close()
195-
return
196-
}
197-
if err = s.reportBlock(conn, head.Data.(core.ChainHeadEvent).Block); err != nil {
237+
case head := <-headCh:
238+
if err = s.reportBlock(conn, head); err != nil {
198239
log.Warn("Block stats report failed", "err", err)
199240
}
200241
if err = s.reportPending(conn); err != nil {
201242
log.Warn("Post-block transaction stats report failed", "err", err)
202243
}
203-
case _, ok := <-txSub.Chan():
204-
if !ok { // node stopped
205-
conn.Close()
206-
return
207-
}
208-
// Exhaust events to avoid reporting too frequently
209-
for exhausted := false; !exhausted; {
210-
select {
211-
case <-headSub.Chan():
212-
default:
213-
exhausted = true
214-
}
215-
}
244+
case <-txCh:
216245
if err = s.reportPending(conn); err != nil {
217246
log.Warn("Transaction stats report failed", "err", err)
218247
}
@@ -398,7 +427,7 @@ func (s *Service) reportLatency(conn *websocket.Conn) error {
398427
select {
399428
case <-s.pongCh:
400429
// Pong delivered, report the latency
401-
case <-time.After(3 * time.Second):
430+
case <-time.After(5 * time.Second):
402431
// Ping timeout, abort
403432
return errors.New("ping timed out")
404433
}

0 commit comments

Comments
 (0)