服务调用客户端
package util
import (
"fmt"
"math/rand/v2"
"net/http"
"net/url"
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
"github.com/nacos-group/nacos-sdk-go/v2/vo"
)
type ServiceClient struct {
namingClient naming_client.INamingClient
webClient *WebClient
}
func NewServiceClient(namingClient naming_client.INamingClient, webClient *WebClient) *ServiceClient {
return &ServiceClient{
namingClient: namingClient,
webClient: webClient,
}
}
func (m *ServiceClient) Get(serviceName string, path string, urlValues url.Values) (int, []byte, error) {
_, code, bytees, err := m.Do(serviceName, "GET", "application/json;charset=UTF-8", path, urlValues, nil)
return code, bytees, err
}
func (m *ServiceClient) Post(serviceName string, path string, bodyValue any) (int, []byte, error) {
_, code, bytees, err := m.Do(serviceName, "POST", "application/json;charset=UTF-8", path, nil, bodyValue)
return code, bytees, err
}
func (m *ServiceClient) Put(serviceName string, path string, urlValues url.Values, bodyValue any) (int, []byte, error) {
_, code, bytees, err := m.Do(serviceName, "PUT", "application/json;charset=UTF-8", path, urlValues, bodyValue)
return code, bytees, err
}
func (m *ServiceClient) Delete(serviceName string, path string, urlValues url.Values, bodyValue any) (int, []byte, error) {
_, code, bytees, err := m.Do(serviceName, "DELETE", "application/json;charset=UTF-8", path, urlValues, bodyValue)
return code, bytees, err
}
func (m *ServiceClient) Do(
serviceName string,
method string,
contentType string,
path string, urlValues url.Values,
bodyValue any) (*http.Response, int, []byte, error) {
serviceUrl, err := m.GetServiceUrl(serviceName)
if err != nil {
return nil, 0, nil, err
}
return m.webClient.Do(method, contentType, serviceUrl, path, urlValues, bodyValue)
}
func (m *ServiceClient) GetServiceUrl(serviceName string) (string, error) {
service, err := m.namingClient.GetService(vo.GetServiceParam{ServiceName: serviceName})
if err != nil {
return "", err
}
if !service.Valid {
return "", fmt.Errorf("服务(%s)不存在", serviceName)
}
urls := make([]string, 0, len(service.Hosts))
for _, instance := range service.Hosts {
if instance.Enable && instance.Healthy {
urls = append(urls, fmt.Sprintf("http://%s:%d", instance.Ip, instance.Port))
}
}
if len(urls) == 0 {
return "", fmt.Errorf("服务(%s)没有可用的实例", serviceName)
}
if len(urls) == 1 {
return urls[0], nil
}
return urls[rand.IntN(len(urls))], nil
}
Http请求客户端
package util
import (
"bytes"
"encoding/json"
"io"
"net/http"
"net/url"
"strings"
)
type WebClient struct {
Client *http.Client
}
func NewWebClient(client *http.Client) *WebClient {
return &WebClient{Client: client}
}
func (m *WebClient) Get(baseUrl string, path string, urlValues url.Values) (int, []byte, error) {
_, code, bytees, err := m.Do("GET", "application/json;charset=UTF-8", baseUrl, path, urlValues, nil)
return code, bytees, err
}
func (m *WebClient) GetRes(baseUrl string, path string, urlValues url.Values) (*http.Response, int, []byte, error) {
res, code, bytees, err := m.Do("GET", "application/json;charset=UTF-8", baseUrl, path, urlValues, nil)
return res, code, bytees, err
}
func (m *WebClient) Post(baseUrl string, path string, bodyValue interface{}) (int, []byte, error) {
_, code, bytees, err := m.Do("POST", "application/json;charset=UTF-8", baseUrl, path, nil, bodyValue)
return code, bytees, err
}
func (m *WebClient) Put(baseUrl string, path string, urlValues url.Values, bodyValue interface{}) (int, []byte, error) {
_, code, bytees, err := m.Do("PUT", "application/json;charset=UTF-8", baseUrl, path, urlValues, bodyValue)
return code, bytees, err
}
func (m *WebClient) Delete(baseUrl string, path string, urlValues url.Values, bodyValue interface{}) (int, []byte, error) {
_, code, bytees, err := m.Do("DELETE", "application/json;charset=UTF-8", baseUrl, path, urlValues, bodyValue)
return code, bytees, err
}
func (m *WebClient) Do(method string, contentType string, baseUrl string, path string, urlValues url.Values, bodyValue interface{}) (*http.Response, int, []byte, error) {
bodyValueBytes, err1 := json.Marshal(bodyValue)
if err1 != nil {
return nil, 0, nil, err1
}
if req, err := http.NewRequest(method, m.url(baseUrl, path, urlValues), bytes.NewReader(bodyValueBytes)); err != nil {
return nil, 0, nil, err
} else {
return m.doRequest(req, contentType)
}
}
func (m *WebClient) url(baseUrl string, path string, urlValues url.Values) string {
result, _ := url.JoinPath(baseUrl, path)
sb := new(strings.Builder)
sb.WriteString(result)
if len(urlValues) > 0 {
sb.WriteString("?")
sb.WriteString(urlValues.Encode())
}
return sb.String()
}
func (m *WebClient) doRequest(req *http.Request, contentType string) (*http.Response, int, []byte, error) {
req.Header.Set("Content-Type", contentType)
if res, err := m.Client.Do(req); err != nil {
return res, res.StatusCode, nil, err
} else {
if resBytes, err := io.ReadAll(res.Body); err != nil {
return res, res.StatusCode, nil, err
} else {
return res, res.StatusCode, resBytes, nil
}
}
}