feat: 添加微服务模板基础架构
- 创建基于 CloudWego Hertz 的 Go 微服务脚手架 - 集成 Nacos 服务注册/发现功能 - 添加 gRPC 客户端支持 - 实现环境变量配置管理 (.env.example) - 添加 HTTP 中间件 (Recovery, AccessLog, CORS) - 配置 Gitea CI/CD 构建部署流程 BREAKING CHANGE: 项目结构调整,从简单的 API 服务升级为完整的微服务架构
This commit is contained in:
+58
-37
@@ -1,66 +1,87 @@
|
||||
package nacos
|
||||
|
||||
import (
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
)
|
||||
|
||||
var (
|
||||
cc *constant.ClientConfig
|
||||
sc []constant.ServerConfig
|
||||
cc *constant.ClientConfig
|
||||
sc []constant.ServerConfig
|
||||
initMu sync.Once
|
||||
)
|
||||
|
||||
func GetIP(domain string) string {
|
||||
// 确保域名不为空
|
||||
if domain == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 使用 net.LookupIP 查找域名的 IP 地址
|
||||
ips, err := net.LookupIP(domain)
|
||||
if err != nil {
|
||||
if err != nil || len(ips) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 检查是否找到了 IP
|
||||
if len(ips) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 返回第一个 IPv4 地址(如果有)
|
||||
for _, ip := range ips {
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
return ipv4.String()
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有 IPv4,返回第一个 IP(可能是 IPv6)
|
||||
return ips[0].String()
|
||||
}
|
||||
|
||||
func InitNacosRegistryConfig() {
|
||||
if cc != nil && sc != nil {
|
||||
return
|
||||
}
|
||||
nacosHosts := strings.Split(os.Getenv("NACOS_HOSTS"), ",")
|
||||
nacosPort, _ := strconv.Atoi(os.Getenv("NACOS_PORT"))
|
||||
for _, host := range nacosHosts {
|
||||
serverConfig := constant.NewServerConfig(GetIP(host), uint64(nacosPort))
|
||||
sc = append(sc, *serverConfig)
|
||||
}
|
||||
func InitNacosRegistryConfig() error {
|
||||
var initErr error
|
||||
initMu.Do(func() {
|
||||
hostsStr := os.Getenv("NACOS_HOSTS")
|
||||
portStr := os.Getenv("NACOS_PORT")
|
||||
if hostsStr == "" || portStr == "" {
|
||||
initErr = errors.New("NACOS_HOSTS 和 NACOS_PORT 必须配置")
|
||||
return
|
||||
}
|
||||
|
||||
LogDir := os.Getenv("LOG_SAVE_PATH")
|
||||
cc = &constant.ClientConfig{
|
||||
NamespaceId: os.Getenv("NACOS_NAMESPACE"),
|
||||
TimeoutMs: 5000,
|
||||
NotLoadCacheAtStart: true,
|
||||
LogDir: LogDir,
|
||||
//CacheDir: "/tmp/nacos/cache",
|
||||
LogLevel: "debug",
|
||||
Username: os.Getenv("NACOS_USER"),
|
||||
Password: os.Getenv("NACOS_PASSWORD"),
|
||||
}
|
||||
nacosPort, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
initErr = errors.New("NACOS_PORT 格式错误")
|
||||
return
|
||||
}
|
||||
|
||||
nacosHosts := strings.Split(hostsStr, ",")
|
||||
for _, host := range nacosHosts {
|
||||
host = strings.TrimSpace(host)
|
||||
if host == "" {
|
||||
continue
|
||||
}
|
||||
ip := GetIP(host)
|
||||
if ip == "" {
|
||||
ip = host
|
||||
}
|
||||
serverConfig := constant.NewServerConfig(ip, uint64(nacosPort))
|
||||
sc = append(sc, *serverConfig)
|
||||
}
|
||||
|
||||
if len(sc) == 0 {
|
||||
initErr = errors.New("无有效的 Nacos 服务器地址")
|
||||
return
|
||||
}
|
||||
|
||||
logDir := os.Getenv("LOG_SAVE_PATH")
|
||||
if logDir == "" {
|
||||
logDir = "/tmp/nacos/log"
|
||||
}
|
||||
|
||||
cc = &constant.ClientConfig{
|
||||
NamespaceId: os.Getenv("NACOS_NAMESPACE"),
|
||||
TimeoutMs: 5000,
|
||||
NotLoadCacheAtStart: true,
|
||||
LogDir: logDir,
|
||||
LogLevel: "warn",
|
||||
Username: os.Getenv("NACOS_USER"),
|
||||
Password: os.Getenv("NACOS_PASSWORD"),
|
||||
}
|
||||
})
|
||||
return initErr
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package nacos
|
||||
|
||||
import (
|
||||
"apiServer_service/utils/loger"
|
||||
"apiServer_service/utils/logger"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/vo"
|
||||
)
|
||||
|
||||
// NewNacosConfigClient 创建一个 Nacos 配置服务
|
||||
func NewNacosConfigClient() (*config_client.IConfigClient, error) {
|
||||
func NewNacosConfigClient() (config_client.IConfigClient, error) {
|
||||
InitNacosRegistryConfig()
|
||||
cli, err := clients.NewConfigClient(
|
||||
vo.NacosClientParam{
|
||||
@@ -19,39 +18,34 @@ func NewNacosConfigClient() (*config_client.IConfigClient, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cli, nil
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
// AddConfig 新增配置
|
||||
func AddConfig(dataId, group, content string) error {
|
||||
client, err := NewNacosConfigClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = (*client).PublishConfig(vo.ConfigParam{
|
||||
_, err = client.PublishConfig(vo.ConfigParam{
|
||||
DataId: dataId,
|
||||
Group: group,
|
||||
Content: content,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func GetConfig(dataId, group string) string {
|
||||
client, err := NewNacosConfigClient()
|
||||
if err != nil {
|
||||
loger.Error("获取配置客户端失败", err)
|
||||
logger.Error("获取配置客户端失败", err)
|
||||
return ""
|
||||
}
|
||||
content, err := (*client).GetConfig(vo.ConfigParam{
|
||||
content, err := client.GetConfig(vo.ConfigParam{
|
||||
DataId: dataId,
|
||||
Group: group,
|
||||
})
|
||||
if err != nil {
|
||||
loger.Error("获取配置失败", err)
|
||||
logger.Error("获取配置失败", err)
|
||||
return ""
|
||||
}
|
||||
return content
|
||||
|
||||
+53
-31
@@ -1,29 +1,39 @@
|
||||
package nacos
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/vo"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
cli naming_client.INamingClient
|
||||
groupName string
|
||||
ServerUriCache = make(map[string]model.Instance)
|
||||
namingClient naming_client.INamingClient
|
||||
namingMu sync.Mutex
|
||||
groupName string
|
||||
serviceCache sync.Map
|
||||
)
|
||||
|
||||
// NewNacosRegistry 创建一个nacos注册中心
|
||||
func NewNacosRegistry() (*naming_client.INamingClient, error) {
|
||||
InitNacosRegistryConfig()
|
||||
if cli != nil {
|
||||
return &cli, nil
|
||||
func NewNacosRegistry() (naming_client.INamingClient, error) {
|
||||
namingMu.Lock()
|
||||
defer namingMu.Unlock()
|
||||
|
||||
if namingClient != nil {
|
||||
return namingClient, nil
|
||||
}
|
||||
|
||||
if err := InitNacosRegistryConfig(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
groupName = os.Getenv("NACOS_GROUP_NAME")
|
||||
var err error
|
||||
cli, err = clients.NewNamingClient(
|
||||
namingClient, err = clients.NewNamingClient(
|
||||
vo.NacosClientParam{
|
||||
ClientConfig: cc,
|
||||
ServerConfigs: sc,
|
||||
@@ -32,17 +42,21 @@ func NewNacosRegistry() (*naming_client.INamingClient, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cli, nil
|
||||
return namingClient, nil
|
||||
}
|
||||
|
||||
// RegisterService 注册当前服务到nacos中
|
||||
func RegisterService() error {
|
||||
client, err := NewNacosRegistry()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceName := os.Getenv("NACOS_SERVICE_NAME")
|
||||
host := os.Getenv("NACOS_SERVICE_HOST")
|
||||
if serviceName == "" || host == "" {
|
||||
return errors.New("NACOS_SERVICE_NAME 和 NACOS_SERVICE_HOST 必须配置")
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(os.Getenv("NACOS_SERVICE_PORT"))
|
||||
if err != nil {
|
||||
port = 8848
|
||||
@@ -51,7 +65,8 @@ func RegisterService() error {
|
||||
if err != nil {
|
||||
weight = 10
|
||||
}
|
||||
_, err = (*client).RegisterInstance(vo.RegisterInstanceParam{
|
||||
|
||||
_, err = client.RegisterInstance(vo.RegisterInstanceParam{
|
||||
Ip: host,
|
||||
Port: uint64(port),
|
||||
ServiceName: serviceName,
|
||||
@@ -61,43 +76,50 @@ func RegisterService() error {
|
||||
Ephemeral: false,
|
||||
GroupName: groupName,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// DiscoverServiceList 发现服务列表
|
||||
func DiscoverServiceList(serviceName string) ([]model.Instance, error) {
|
||||
client, err := NewNacosRegistry()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
instances, err := (*client).SelectInstances(vo.SelectInstancesParam{
|
||||
return client.SelectInstances(vo.SelectInstancesParam{
|
||||
ServiceName: serviceName,
|
||||
HealthyOnly: false,
|
||||
GroupName: groupName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return instances, nil
|
||||
}
|
||||
|
||||
// DiscoverService 发现一个服务
|
||||
func DiscoverService(serviceName string) (model.Instance, error) {
|
||||
ServiceCache := ServerUriCache[serviceName]
|
||||
if cached, ok := serviceCache.Load(serviceName); ok {
|
||||
cachedInstance := cached.(model.Instance)
|
||||
client, err := NewNacosRegistry()
|
||||
if err != nil {
|
||||
return cachedInstance, err
|
||||
}
|
||||
instance, err := client.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
|
||||
ServiceName: serviceName,
|
||||
GroupName: groupName,
|
||||
})
|
||||
if err != nil {
|
||||
return cachedInstance, err
|
||||
}
|
||||
serviceCache.Store(serviceName, *instance)
|
||||
return *instance, nil
|
||||
}
|
||||
|
||||
client, err := NewNacosRegistry()
|
||||
if err != nil {
|
||||
return ServiceCache, err
|
||||
return model.Instance{}, err
|
||||
}
|
||||
instances, err := (*client).SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
|
||||
instance, err := client.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
|
||||
ServiceName: serviceName,
|
||||
GroupName: groupName,
|
||||
})
|
||||
if err != nil {
|
||||
return ServiceCache, err
|
||||
return model.Instance{}, err
|
||||
}
|
||||
ServerUriCache[serviceName] = *instances
|
||||
return *instances, nil
|
||||
serviceCache.Store(serviceName, *instance)
|
||||
return *instance, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user