【达梦数据库】golang使用域名连接数据库报错踩坑

文章较长,如果需要解决方案

问题简述

最近在golang项目中连接达梦数据库的时候遇到了如下报错:

2023-12-28 10:05:50,302 [ERROR] 1:common.InitDb initcnf.go:166   
QueryAppInfo fail, err = Error 6001: 网络通信异常	dial address: localhost:5236
stack info:
1).  github.com/mzky/dm.dm_build_348\n    	/home/user/go/pkg/mod/github.com/mzky/dm@v0.0.0-20210201024716-58aaa968f460/a.go:55\n   

驱动是官网驱动,连接方式使用的是官网demo中的连接方式

dbuser:="root"
dbPassWd:="password"
dbAddrs:="NORMAL"
port:=5236
dbName:="test"
dataSource = fmt.Sprintf("dm://%s:%s@%s:%d?schema=%s", dbUser, dbPassWd, dbAddrs, port, dbName)

这里的地址使用了别名,但是报错的时候却说是连接到localhost:5236网络错误,这个就很神奇了。手头正好有达梦golang驱动的代码,就进去搜索了一下。

dm驱动校验host的逻辑

if group, ok := ServerGroupMap[strings.ToLower(host)]; ok {
		c.group = group
	} else {
		host, port, err := net.SplitHostPort(host)
		if err != nil || net.ParseIP(host) == nil {
			c.host = hostDef //hostDef先前定义为了“localhost”
		} else {
			c.host = host
		}
		tmpPort, err := strconv.Atoi(port)
		if err != nil {
			c.port = portDef
		} else {
			c.port = int32(tmpPort)
		}

		c.group = newEPGroup(c.host+":"+strconv.Itoa(int(c.port)), []*ep{newEP(c.host, c.port)})
	}

这里就大概明白了,驱动中会校验传入的host是否为合法的ip地址(这个函数ParseIP,甚至还能校验ipv6),对于非法的host,就会被强制替换为localhost。这个设计很难评价。

配置服务组及踩坑

不过上面有个ServerGroupMap,如果host在里面就不会走这个逻辑了,进一步往下看。这个ServerGroupMap是读取了指定目录下的dm_svc.conf,从代码逻辑看应该是解析了这个文件。

// filePath: dm_svc.conf 文件路径
func load(filePath string) {
	if filePath == "" {
		switch runtime.GOOS {
		case "windows":
			filePath = os.Getenv("SystemRoot") + "\\system32\\dm_svc.conf"
		case "linux":
			filePath = "/etc/dm_svc.conf"
		default:
			return
		}
	}
	file, err := os.Open(filePath)
	defer file.Close()
	if err != nil {
		return
	}
	fileReader := bufio.NewReader(file)

	// GlobalProperties = NewProperties()
	var groupProps *Properties
	var line string //dm_svc.conf读取到的一行

	for line, err = fileReader.ReadString('\n'); line != "" && (err == nil || err == io.EOF); line, err = fileReader.ReadString('\n') {
		// 去除#标记的注释
		if notesIndex := strings.IndexByte(line, '#'); notesIndex != -1 {
			line = line[:notesIndex]
		}
		// 去除前后多余的空格
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}

		if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
			groupName := strings.ToLower(line[1 : len(line)-1])
			dbGroup, ok := ServerGroupMap[groupName]
			if groupName == "" || !ok {
				continue
			}
...

连接时用host匹配解析出的服务组,匹配到了就按照匹配的服务组连接数据库。于是就去配置文件/etc/dm_svc.conf里面按照官网写上了服务组的配置:

NORMAL=(192.168.0.1:5000,192.168.0.2:5236)

结果还是解析到了localhost,最后发现这个host应该是截取连接里面“@”到“?”这部分

dm://%s:%s@%s:%d?schema=%s

按照目前的方式,程序会先匹配NORMAL:5236,发现配置文件里面只有NORMAL,不匹配。然后继续走校验ip的流程。

解决方案

使用别名连接,需要去修改配置文件(没有则新建)
地址:

  • windows :%SystemRoot%\system32\dm_svc.conf
  • linux :filePath = "/etc/dm_svc.conf

填写方式

连接别名=(IP1:PORT1,IP2:PORT2)

在连接时只允许这种

dm://用户名:密码@IP:端口?schema=库名
dm://用户名:密码@连接别名?schema=库名


参考资料:https://eco.dameng.com/community/question/c8ba0b48062bd35401edb388e41ab598

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值