xframe/component/agollo/protocol/http/request.go

139 lines
3.5 KiB
Go
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package http
import (
"fmt"
"io/ioutil"
"net/http"
"time"
"git.wishpal.cn/wishpal_ironfan/xframe/component/agollo/env"
"git.wishpal.cn/wishpal_ironfan/xframe/component/agollo/env/config"
"git.wishpal.cn/wishpal_ironfan/xframe/component/agollo/loadbalance"
"git.wishpal.cn/wishpal_ironfan/xframe/component/agollo/utils"
"git.wishpal.cn/wishpal_ironfan/xframe/component/logger"
"github.com/pkg/errors"
)
var (
//for on error retry
onErrorRetryInterval = 2 * time.Second //2s
connectTimeout = 1 * time.Second //1s
//max retries connect apollo
maxRetries = 5
)
// CallBack 请求回调函数
type CallBack struct {
SuccessCallBack func([]byte) (interface{}, error)
NotModifyCallBack func() error
}
// Request 建立网络请求
func Request(requestURL string, connectionConfig *env.ConnectConfig, callBack *CallBack) (interface{}, error) {
client := &http.Client{}
//如有设置自定义超时时间即使用
if connectionConfig != nil && connectionConfig.Timeout != 0 {
client.Timeout = connectionConfig.Timeout
} else {
client.Timeout = connectTimeout
}
retry := 0
var responseBody []byte
var err error
var res *http.Response
var retries = maxRetries
if connectionConfig != nil && !connectionConfig.IsRetry {
retries = 1
}
for {
retry++
if retry > retries {
break
}
res, err = client.Get(requestURL)
if res == nil || err != nil {
logger.Errorf("Connect Apollo Server Fail,url:%s,Error:%s", requestURL, err)
// if error then sleep
time.Sleep(onErrorRetryInterval)
continue
}
//not modified break
switch res.StatusCode {
case http.StatusOK:
responseBody, err = ioutil.ReadAll(res.Body)
if err != nil {
logger.Errorf("Connect Apollo Server Fail,url:%s,Error:", requestURL, err)
// if error then sleep
time.Sleep(onErrorRetryInterval)
continue
}
if callBack != nil && callBack.SuccessCallBack != nil {
return callBack.SuccessCallBack(responseBody)
}
return nil, nil
case http.StatusNotModified:
//log.Info("Config Not Modified, requestURL = %v", requestURL)
if callBack != nil && callBack.NotModifyCallBack != nil {
return nil, callBack.NotModifyCallBack()
}
return nil, nil
default:
logger.Errorf("Connect Apollo Server Fail,url:%s,StatusCode:%s", requestURL, res.StatusCode)
err = errors.New("connect Apollo Server Fail")
// if error then sleep
time.Sleep(onErrorRetryInterval)
continue
}
}
logger.Errorln("Over Max Retry Still Error,Error:", err)
if err != nil {
err = errors.New("over Max Retry Still Error")
}
return nil, err
}
// RequestRecovery 可以恢复的请求
func RequestRecovery(appConfig *config.AppConfig,
connectConfig *env.ConnectConfig,
callBack *CallBack) (interface{}, error) {
format := "%s%s"
var err error
var response interface{}
for {
host := loadBalance(appConfig)
if host == "" {
return nil, err
}
requestURL := fmt.Sprintf(format, host, connectConfig.URI)
response, err = Request(requestURL, connectConfig, callBack)
if err == nil {
return response, err
}
env.SetDownNode(host)
}
}
// 链接分为直连server和非直连。
// 非直连的情况下会通过配置中的ip访问到metaserver(类似于zookeeper)从metaserver中获取数据。只有当非直连失败的情况下才可能使用直连
func loadBalance(appConfig *config.AppConfig) string {
if !appConfig.IsConnectDirectly() {
return appConfig.GetHost()
}
serverInfo := loadbalance.GetLoadBalance().Load(env.GetServers())
if serverInfo == nil {
return utils.Empty
}
return serverInfo.HomepageURL
}