阿里云环境部署Hyperledger Fabric之SIGSEGV问题分析和解决经验分享

简介: 引言 最近收到Hyperledger社区的一些朋友反馈在阿里云环境上部署开源区块链项目Hyperledger Fabric的过程中遇到了和SIGSEV相关的fatal error,正好我此前也遇到并解决过类似的问题,因此这里分享一下当时问题的分析过程和解决的经验,希望能带来一点启发和帮助。

最近收到Hyperledger社区的一些朋友反馈在阿里云环境上部署开源区块链项目Hyperledger Fabric的过程中遇到了和SIGSEV相关的fatal error,正好笔者此前也遇到并解决过类似的问题,因此这里分享一下当时问题的分析过程和解决的经验,希望能为大家带来一点启发和帮助。


问题描述

在部署Hyperledger Fabric过程中,peer、orderer服务启动失败,同时cli容器上执行cli-test.sh测试时也报错。错误类型均是signal SIGSEGV: segmentation violation。错误日志示例如下:

2017-11-01 02:44:04.247 UTC [peer] updateTrustedRoots -> DEBU 2a0 Updating trusted root authorities for channel mychannel
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x63 pc=0x7f9d15ded259]
runtime stack:
runtime.throw(0xdc37a7, 0x2a)
        /opt/go/src/runtime/panic.go:566 +0x95
runtime.sigpanic()
        /opt/go/src/runtime/sigpanic_unix.go:12 +0x2cc
goroutine 64 [syscall, locked to thread]:
runtime.cgocall(0xb08d50, 0xc4203bcdf8, 0xc400000000)
        /opt/go/src/runtime/cgocall.go:131 +0x110 fp=0xc4203bcdb0 sp=0xc4203bcd70
net._C2func_getaddrinfo(0x7f9d000008c0, 0x0, 0xc420323110, 0xc4201a01e8, 0x0, 0x0, 0x0)

分析过程

我们进行了深入分析和试验,在Hyperledger Fabric这个bug https://jira.hyperledger.org/browse/FAB-5822的启发下,采用了如下workaround可以解决这个问题:

  • 在docker compose yaml里对peer、orderer、cli的环境变量加入GODEBUG=netdns=go

这个设置的作用是不采用cgo resolver (从错误日志里可看到是cgo resolver抛出的错误)而采用pure go resolver。

进一步分析golang在什么情况下会在cgo resolver和pure go resolver之间切换:

  • golang的官方文档说明:https://golang.org/pkg/net/

    Name Resolution
    The method for resolving domain names, whether indirectly with functions like Dial or directly with functions like LookupHost and LookupAddr, varies by operating system.
    On Unix systems, the resolver has two options for resolving names. It can use a pure Go resolver that sends DNS requests directly to the servers listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C library routines such as getaddrinfo and getnameinfo.
    By default the pure Go resolver is used, because a blocked DNS request consumes only a goroutine, while a blocked C call consumes an operating system thread. When cgo is available, the cgo-based resolver is used instead under a variety of conditions: on systems that do not let programs make direct DNS requests (OS X), when the LOCALDOMAIN environment variable is present (even if empty), when the RES_OPTIONS or HOSTALIASES environment variable is non-empty, when the ASR_CONFIG environment variable is non-empty (OpenBSD only), when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the Go resolver does not implement, and when the name being looked up ends in .local or is an mDNS name.
    The resolver decision can be overridden by setting the netdns value of the GODEBUG environment variable (see package runtime) to go or cgo, as in:
    export GODEBUG=netdns=go # force pure Go resolver
    export GODEBUG=netdns=cgo # force cgo resolver*

根据这一线索,我们对比了此前部署成功环境和最近部署失败环境各自的底层配置文件,最终找到了不同之处:

  • 在老环境(区块链部署成功)上的容器里,查看

    # cat /etc/resolv.conf 
    nameserver 127.0.0.11
    options ndots:0
    
  • 在新环境(区块链部署失败)上的容器里,查看

    # cat /etc/resolv.conf 
    nameserver 127.0.0.11
    options timeout:2 attempts:3 rotate single-request-reopen ndots:0
    

这个差异导致了老的成功环境是采用pure Go resolver的,而在新的失败环境被切换到cgo resolver, 这是因为含有pure Go resolver不支持的options single-request-reopen。

注:Pure Go resolver目前仅支持ndots, timeout, attempts, rotate
https://github.com/golang/go/blob/964639cc338db650ccadeafb7424bc8ebb2c0f6c/src/net/dnsconfig_unix.go

       case "options": // magic options
            for _, s := range f[1:] {
                switch {
                case hasPrefix(s, "ndots:"):
                    n, _, _ := dtoi(s[6:])
                    if n < 0 {
                        n = 0
                    } else if n > 15 {
                        n = 15
                    }
                    conf.ndots = n
                case hasPrefix(s, "timeout:"):
                    n, _, _ := dtoi(s[8:])
                    if n < 1 {
                        n = 1
                    }
                    conf.timeout = time.Duration(n) * time.Second
                case hasPrefix(s, "attempts:"):
                    n, _, _ := dtoi(s[9:])
                    if n < 1 {
                        n = 1
                    }
                    conf.attempts = n
                case s == "rotate":
                    conf.rotate = true
                default:
                    conf.unknownOpt = true
                }
            }

进一步的,我们尝试分析是什么原因导致了新老容器内的resolv.conf的内容变化,发现了原来是最近宿主机ECS的配置文件发生了变化:

  • 失败的环境 - 新创建的ECS:

    # cat /etc/resolv.conf
    # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
    #     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
    nameserver 100.100.2.138
    nameserver 100.100.2.136
    options timeout:2 attempts:3 rotate single-request-reopen
    
  • 成功的环境 - 原来的ECS:

    # cat /etc/resolv.conf
    # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
    #     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
    nameserver 100.100.2.136
    nameserver 100.100.2.138
    

另一方面,我们也尝试分析为什么切换到cgo resolver之后会产生SIGSEGV的错误,以下这篇文章解释了static link cgo会导致SIGSEGV的错误:

而这个Hyperledger Fabric的bug则指出了Hyperledger Fabric的build(尤其是和getaddrinfo相关方法)正是static link的:
https://jira.hyperledger.org/browse/FAB-6403

至此,我们找到了问题的根源和复盘了整个问题发生的逻辑:

  • 近期新创建的ECS主机中的resolv.conf内容发生了变化 -> 导致Hyperledger Fabric的容器内域名解析从pure Go resolver切换至cgo resolver -> 触发了一个已知的由静态链接cgo导致的SIGSEGV错误 -> 导致Hyperledger Fabric部署失败。

解决方法建议

更新Hyperledger Fabric的docker compose yaml模板,为所有Hyperledger Fabric的节点(如orderer, peer, ca, cli等)添加环境变量GODEBUG=netdns=go以强制使用pure Go resolver。

相关实践学习
使用操作系统智能助手OS Copilot解锁操作系统运维与编程
在本实验场景中,将在阿里云ECS上体验OS Copilot产品。OS Copilot是阿里云操作系统团队基于大模型构建的OS智能助手。它具有自然语言问答、辅助命令执行、系统运维调优等功能,帮助用户更好地使用Linux,提升阿里云的使用体验。
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
目录
相关文章
非华为笔记本安装华为电脑管家
非华为笔记本安装华为电脑管家
|
测试技术 Go 区块链
Hyperledger fabric 测试环境部署
Hyperledger fabric 测试环境部署及相关问题解答
950 3
Hyperledger fabric 测试环境部署
|
机器学习/深度学习 人工智能 安全
一篇关于DeepSeek模型先进性的阅读理解
本文以DeepSeek模型为核心,探讨了其技术先进性、训练过程及行业影响。首先介绍DeepSeek的快速崛起及其对AI行业的颠覆作用。DeepSeek通过强化学习(RL)实现Time Scaling Law的新范式,突破了传统大模型依赖算力和数据的限制,展现了集成式创新的优势。文章还提到开源的重要性以及数据作为制胜法宝的关键地位,同时警示了业务发展中安全滞后的问题。
1578 176
一篇关于DeepSeek模型先进性的阅读理解
|
机器学习/深度学习 人工智能 开发者
阿里云支持DeepSeek-V3和DeepSeek-R1全自动安装部署,小白也能轻松上手!
阿里云PAI平台支持DeepSeek-V3和DeepSeek-R1大模型的全自动安装部署,零代码一键完成从训练到推理的全流程。用户只需开通PAI服务,在Model Gallery中选择所需模型并点击部署,即可快速生成PAI-EAS服务,获取调用信息。整个过程简单快捷,适合各水平开发者轻松上手。
3499 80
|
10月前
|
Oracle 关系型数据库 Linux
MyEMS开源系统安装之CentOS/RHEL/Rocky/AlmaLinux/Oracle Linux
本指南介绍如何在CentOS/RHEL/Rocky/AlmaLinux/Oracle Linux服务器上部署MyEMS开源能源管理系统。内容涵盖系统准备、数据库配置、多个MyEMS服务(如myems-api、myems-admin、myems-modbus-tcp等)的安装与配置,以及Nginx服务器设置和防火墙规则调整。通过完成所有步骤,您将能够访问MyEMS Admin UI和Web UI,默认端口分别为8001和80,初始登录凭据已提供。
651 0
|
JavaScript 测试技术 Go
Hyperledger fabric部署链码(一)打包链码
fabric部署chaincode-go(智能合约)系列之一
716 0
|
数据安全/隐私保护
思科模拟器Cisco Packet Tracer 8.2.1注册、下载和安装教程(正确+详细)
本文详细总结了思科模拟器Cisco Packet Tracer 8.2.1注册、下载和安装教程(正确+详细),看这一篇就够啦~
49141 6
思科模拟器Cisco Packet Tracer 8.2.1注册、下载和安装教程(正确+详细)
|
人工智能 架构师 自动驾驶
期待已久,真正的 AI 程序员来了
6 月 21 日,在阿里云上海 AI 峰会上,阿里云推出首个“AI 程序员”,它具备架构师、开发工程师、测试工程师等多种岗位的技能,能一站式自主完成任务分解、代码编写、测试、问题修复、代码提交整个过程,最快分钟级即可完成应用开发,大幅提升研发效率。
1930 115
|
应用服务中间件 nginx Docker
本地通过域名访问虚拟机上nginx的服务、搭建域名访问环境一(反向代理配置)
这篇文章介绍了如何通过域名在本地访问虚拟机上的nginx服务,包括创建nginx容器、修改配置文件、修改本地host文件以及进行访问测试的详细步骤。文章提供了具体的Docker命令来创建并配置nginx容器,展示了配置文件的修改示例,说明了如何在本地系统的hosts文件中添加虚拟机IP和自定义域名,以及如何通过浏览器进行测试访问。
本地通过域名访问虚拟机上nginx的服务、搭建域名访问环境一(反向代理配置)
|
缓存 负载均衡 安全
如何应对DDoS攻击:技术策略与实践
【8月更文挑战第20天】DDoS攻击作为一种常见的网络威胁,对信息系统的安全稳定运行构成了严峻挑战。通过采用流量清洗、CDN、负载均衡、防火墙与IPS、协议与连接限制、强化网络基础设施、实时监测与响应以及专业DDoS防护服务等策略,企业可以构建更加健壮的防御体系,有效应对DDoS攻击。然而,防御DDoS攻击的最佳方法是预防,企业应定期进行风险评估和安全演练,及时更新和强化安全措施,以提高网络的抵御能力和应对能力。