Skip to content

Commit 289ed0c

Browse files
authored
Merge pull request Ehco1996#437 from Ehco1996/fix/network-failure-resilience
2 parents 42f4ced + 99e7502 commit 289ed0c

3 files changed

Lines changed: 18 additions & 40 deletions

File tree

internal/cmgr/cmgr.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,14 @@ func (cm *cmgrImpl) Start(ctx context.Context, errCH chan error) {
194194
cm.l.Info("sync stop")
195195
return
196196
case <-ticker.C:
197+
// Tolerate transient sync failures: retryablehttp already does
198+
// internal backoff; on final error we just log and wait for the
199+
// next tick. The traffic stats accumulated for this interval are
200+
// dropped on the floor.
201+
// TODO: persist unsent stats locally so they can be retried on
202+
// later ticks instead of being lost when the upstream is down.
197203
if err := cm.syncOnce(ctx); err != nil {
198-
cm.l.Errorf("meet non retry error: %s ,exit now", err)
199-
errCH <- err
204+
cm.l.Errorf("sync failed, will retry on next tick in %ds: %s", cm.cfg.SyncInterval, err)
200205
}
201206
}
202207
}

pkg/xray/user.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package xray
33
import (
44
"context"
55
"fmt"
6-
"net/http"
76
"strconv"
87
"sync"
98
"time"
109

1110
"github.com/Ehco1996/ehco/pkg/bytes"
11+
myhttp "github.com/Ehco1996/ehco/pkg/http"
1212
proxy "github.com/xtls/xray-core/app/proxyman/command"
1313
stats "github.com/xtls/xray-core/app/stats/command"
1414
"github.com/xtls/xray-core/common/protocol"
@@ -120,7 +120,6 @@ type UserPool struct {
120120
// map key : ID
121121
users map[int]*User
122122

123-
httpClient *http.Client
124123
proxyClient proxy.HandlerServiceClient
125124
statsClient stats.StatsServiceClient
126125

@@ -253,7 +252,10 @@ func (up *UserPool) syncTrafficToServer(ctx context.Context, proxyTag string) er
253252
"Total Increment By Xray :", bytes.PrettyByteSize(float64(req.GetTotalTraffic())),
254253
)
255254
}
256-
if err := postJson(up.httpClient, up.remoteConfigURL, req); err != nil {
255+
// TODO: traffic accumulated in `tfs` has already been reset on each user
256+
// at this point; if the upstream POST fails (after retries), this batch is
257+
// lost. Persist unsent batches locally and replay them on the next tick.
258+
if err := myhttp.PostJSONWithRetry(up.remoteConfigURL, req); err != nil {
257259
return err
258260
}
259261
up.l.Sugar().Infof("Call syncTrafficToServer ONLINE USER COUNT: %d", len(tfs))
@@ -262,7 +264,7 @@ func (up *UserPool) syncTrafficToServer(ctx context.Context, proxyTag string) er
262264

263265
func (up *UserPool) syncUserConfigsFromServer(ctx context.Context, proxyTag string) error {
264266
resp := SyncUserConfigsResp{}
265-
if err := getJson(up.httpClient, up.remoteConfigURL, &resp); err != nil {
267+
if err := myhttp.GetJSONWithRetry(up.remoteConfigURL, &resp); err != nil {
266268
return err
267269
}
268270
userM := make(map[int]struct{})
@@ -316,7 +318,6 @@ func (up *UserPool) Start(ctx context.Context) error {
316318
}
317319
up.proxyClient = proxy.NewHandlerServiceClient(conn)
318320
up.statsClient = stats.NewStatsServiceClient(conn)
319-
up.httpClient = &http.Client{Timeout: time.Second * 10}
320321

321322
syncOnce := func() error {
322323
for _, tag := range up.proxyTags {
@@ -331,8 +332,11 @@ func (up *UserPool) Start(ctx context.Context) error {
331332
}
332333
return nil
333334
}
335+
// Tolerate a failed initial sync: starting up with an empty user pool is
336+
// preferable to a crash-loop when the upstream is briefly unreachable.
337+
// The periodic loop below will pick the users up on the next tick.
334338
if err := syncOnce(); err != nil {
335-
return err
339+
up.l.Sugar().Errorf("Initial sync failed, will retry on next tick in %ds: %v", SyncTime, err)
336340
}
337341

338342
ctx2, cancel := context.WithCancel(ctx)
@@ -345,7 +349,7 @@ func (up *UserPool) Start(ctx context.Context) error {
345349
return
346350
case <-ticker.C:
347351
if err := syncOnce(); err != nil {
348-
up.l.Error("Sync User Configs From Server Error: %v", zap.Error(err))
352+
up.l.Error("sync failed, will retry on next tick", zap.Error(err))
349353
}
350354
}
351355
}

pkg/xray/utils.go

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

0 commit comments

Comments
 (0)