mirror of
https://github.com/tuna/tunasync.git
synced 2025-04-20 20:22:46 +00:00
fix(tunasync): connection leakage caused by http keep-alive
This commit is contained in:
parent
d1981379a4
commit
2268eb3b0f
@ -8,6 +8,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetTLSConfig generate tls.Config from CAFile
|
// GetTLSConfig generate tls.Config from CAFile
|
||||||
@ -28,20 +29,34 @@ func GetTLSConfig(CAFile string) (*tls.Config, error) {
|
|||||||
return tlsConfig, nil
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostJSON posts json object to url
|
// CreateHTTPClient returns a http.Client
|
||||||
func PostJSON(url string, obj interface{}, tlsConfig *tls.Config) (*http.Response, error) {
|
func CreateHTTPClient(CAFile string) (*http.Client, error) {
|
||||||
var client *http.Client
|
var tlsConfig *tls.Config
|
||||||
if tlsConfig == nil {
|
var err error
|
||||||
client = &http.Client{}
|
|
||||||
} else {
|
if CAFile != "" {
|
||||||
tr := &http.Transport{
|
tlsConfig, err = GetTLSConfig(CAFile)
|
||||||
TLSClientConfig: tlsConfig,
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
client = &http.Client{
|
|
||||||
Transport: tr,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
MaxIdleConnsPerHost: 20,
|
||||||
|
TLSClientConfig: tlsConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &http.Client{
|
||||||
|
Transport: tr,
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostJSON posts json object to url
|
||||||
|
func PostJSON(url string, obj interface{}, client *http.Client) (*http.Response, error) {
|
||||||
|
if client == nil {
|
||||||
|
client, _ = CreateHTTPClient("")
|
||||||
|
}
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
if err := json.NewEncoder(b).Encode(obj); err != nil {
|
if err := json.NewEncoder(b).Encode(obj); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -50,17 +65,9 @@ func PostJSON(url string, obj interface{}, tlsConfig *tls.Config) (*http.Respons
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetJSON gets a json response from url
|
// GetJSON gets a json response from url
|
||||||
func GetJSON(url string, obj interface{}, tlsConfig *tls.Config) (*http.Response, error) {
|
func GetJSON(url string, obj interface{}, client *http.Client) (*http.Response, error) {
|
||||||
var client *http.Client
|
if client == nil {
|
||||||
if tlsConfig == nil {
|
client, _ = CreateHTTPClient("")
|
||||||
client = &http.Client{}
|
|
||||||
} else {
|
|
||||||
tr := &http.Transport{
|
|
||||||
TLSClientConfig: tlsConfig,
|
|
||||||
}
|
|
||||||
client = &http.Client{
|
|
||||||
Transport: tr,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := client.Get(url)
|
resp, err := client.Get(url)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@ -20,10 +19,10 @@ var manager *Manager
|
|||||||
|
|
||||||
// A Manager represents a manager server
|
// A Manager represents a manager server
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
cfg *Config
|
cfg *Config
|
||||||
engine *gin.Engine
|
engine *gin.Engine
|
||||||
adapter dbAdapter
|
adapter dbAdapter
|
||||||
tlsConfig *tls.Config
|
httpClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTUNASyncManager returns the manager from config
|
// GetTUNASyncManager returns the manager from config
|
||||||
@ -37,19 +36,18 @@ func GetTUNASyncManager(cfg *Config) *Manager {
|
|||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
}
|
}
|
||||||
s := &Manager{
|
s := &Manager{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
engine: gin.Default(),
|
engine: gin.Default(),
|
||||||
adapter: nil,
|
adapter: nil,
|
||||||
tlsConfig: nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Files.CACert != "" {
|
if cfg.Files.CACert != "" {
|
||||||
tlsConfig, err := GetTLSConfig(cfg.Files.CACert)
|
httpClient, err := CreateHTTPClient(cfg.Files.CACert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Error initializing TLS config: %s", err.Error())
|
logger.Error("Error initializing HTTP client: %s", err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s.tlsConfig = tlsConfig
|
s.httpClient = httpClient
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Files.DBFile != "" {
|
if cfg.Files.DBFile != "" {
|
||||||
@ -96,12 +94,20 @@ func (s *Manager) setDBAdapter(adapter dbAdapter) {
|
|||||||
// Run runs the manager server forever
|
// Run runs the manager server forever
|
||||||
func (s *Manager) Run() {
|
func (s *Manager) Run() {
|
||||||
addr := fmt.Sprintf("%s:%d", s.cfg.Server.Addr, s.cfg.Server.Port)
|
addr := fmt.Sprintf("%s:%d", s.cfg.Server.Addr, s.cfg.Server.Port)
|
||||||
|
|
||||||
|
httpServer := &http.Server{
|
||||||
|
Addr: addr,
|
||||||
|
Handler: s.engine,
|
||||||
|
ReadTimeout: 10 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
if s.cfg.Server.SSLCert == "" && s.cfg.Server.SSLKey == "" {
|
if s.cfg.Server.SSLCert == "" && s.cfg.Server.SSLKey == "" {
|
||||||
if err := s.engine.Run(addr); err != nil {
|
if err := httpServer.ListenAndServe(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := s.engine.RunTLS(addr, s.cfg.Server.SSLCert, s.cfg.Server.SSLKey); err != nil {
|
if err := httpServer.ListenAndServeTLS(s.cfg.Server.SSLCert, s.cfg.Server.SSLKey); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,7 +264,7 @@ func (s *Manager) handleClientCmd(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// post command to worker
|
// post command to worker
|
||||||
_, err = PostJSON(workerURL, workerCmd, s.tlsConfig)
|
_, err = PostJSON(workerURL, workerCmd, s.httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("post command to worker %s(%s) fail: %s", workerID, workerURL, err.Error())
|
err := fmt.Errorf("post command to worker %s(%s) fail: %s", workerID, workerURL, err.Error())
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
|
@ -2,7 +2,6 @@ package worker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
@ -26,8 +25,8 @@ type Worker struct {
|
|||||||
semaphore chan empty
|
semaphore chan empty
|
||||||
|
|
||||||
schedule *scheduleQueue
|
schedule *scheduleQueue
|
||||||
httpServer *gin.Engine
|
httpEngine *gin.Engine
|
||||||
tlsConfig *tls.Config
|
httpClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTUNASyncWorker returns a singalton worker
|
// GetTUNASyncWorker returns a singalton worker
|
||||||
@ -48,12 +47,12 @@ func GetTUNASyncWorker(cfg *Config) *Worker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Manager.CACert != "" {
|
if cfg.Manager.CACert != "" {
|
||||||
tlsConfig, err := GetTLSConfig(cfg.Manager.CACert)
|
httpClient, err := CreateHTTPClient(cfg.Manager.CACert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to init TLS config: %s", err.Error())
|
logger.Error("Error initializing HTTP client: %s", err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
w.tlsConfig = tlsConfig
|
w.httpClient = httpClient
|
||||||
}
|
}
|
||||||
|
|
||||||
w.initJobs()
|
w.initJobs()
|
||||||
@ -227,18 +226,25 @@ func (w *Worker) makeHTTPServer() {
|
|||||||
c.JSON(http.StatusOK, gin.H{"msg": "OK"})
|
c.JSON(http.StatusOK, gin.H{"msg": "OK"})
|
||||||
})
|
})
|
||||||
|
|
||||||
w.httpServer = s
|
w.httpEngine = s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) runHTTPServer() {
|
func (w *Worker) runHTTPServer() {
|
||||||
addr := fmt.Sprintf("%s:%d", w.cfg.Server.Addr, w.cfg.Server.Port)
|
addr := fmt.Sprintf("%s:%d", w.cfg.Server.Addr, w.cfg.Server.Port)
|
||||||
|
|
||||||
|
httpServer := &http.Server{
|
||||||
|
Addr: addr,
|
||||||
|
Handler: w.httpEngine,
|
||||||
|
ReadTimeout: 10 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
if w.cfg.Server.SSLCert == "" && w.cfg.Server.SSLKey == "" {
|
if w.cfg.Server.SSLCert == "" && w.cfg.Server.SSLKey == "" {
|
||||||
if err := w.httpServer.Run(addr); err != nil {
|
if err := httpServer.ListenAndServe(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := w.httpServer.RunTLS(addr, w.cfg.Server.SSLCert, w.cfg.Server.SSLKey); err != nil {
|
if err := httpServer.ListenAndServeTLS(w.cfg.Server.SSLCert, w.cfg.Server.SSLKey); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,7 +351,7 @@ func (w *Worker) registorWorker() {
|
|||||||
URL: w.URL(),
|
URL: w.URL(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := PostJSON(url, msg, w.tlsConfig); err != nil {
|
if _, err := PostJSON(url, msg, w.httpClient); err != nil {
|
||||||
logger.Error("Failed to register worker")
|
logger.Error("Failed to register worker")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,7 +374,7 @@ func (w *Worker) updateStatus(jobMsg jobMessage) {
|
|||||||
ErrorMsg: jobMsg.msg,
|
ErrorMsg: jobMsg.msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := PostJSON(url, smsg, w.tlsConfig); err != nil {
|
if _, err := PostJSON(url, smsg, w.httpClient); err != nil {
|
||||||
logger.Error("Failed to update mirror(%s) status: %s", jobMsg.name, err.Error())
|
logger.Error("Failed to update mirror(%s) status: %s", jobMsg.name, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,7 +388,7 @@ func (w *Worker) fetchJobStatus() []MirrorStatus {
|
|||||||
w.Name(),
|
w.Name(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if _, err := GetJSON(url, &mirrorList, w.tlsConfig); err != nil {
|
if _, err := GetJSON(url, &mirrorList, w.httpClient); err != nil {
|
||||||
logger.Error("Failed to fetch job status: %s", err.Error())
|
logger.Error("Failed to fetch job status: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user