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

最近收到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的错误:
https://tschottdorf.github.io/golang-static-linking-bug

而这个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。


阿里云容器服务区块链解决方案

我们在阿里云容器服务上为开发者提供了Hyperledger Fabric的自动化配置和部署的基础解决方案,帮助开发者屏蔽底层复杂的操作、更加专注于区块链业务应用的创新,如有兴趣进一步了解,可参考:

  • 阿里云容器服务区块链解决方案介绍
  • 阿里云容器服务区块链解决方案产品文档
时间: 2025-01-31 05:49:21

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

在阿里云上部署生产级别Kubernetes集群

阿里云是国内非常受欢迎的基础云平台,随着Kubernetes的普及,越来越多的企业开始筹划在阿里云上部署自己的Kubernetes集群.本文将结合实战中总结的经验,分析和归纳一套在阿里云上部署生产级别Kubernetes集群的方法.文中所采取的技术方案具有一定的主观性,供各位读者参考.在实践中可以根据具体使用场景进行优化. 目标 当我们刚接触Kubernetes进行测试集群的搭建时,往往会选择一篇已有的教程,照着教程完成集群搭建.我们很少去质疑教程作者每一步操作的合理性,只想快点把集群搭建起来,

【DockerCon2017最新技术解读】如何在阿里云一键部署高可用的Kubernetes集群

摘要:在云栖TechDay34期:DockerCon2017最新的技术解读中,阿里云的容器服务团队技术专家谢瑶瑶做了题为<Kubernetes on Alibaba Cloud>的分享,主要介绍了Kubernetes的基本概念,如何在阿里云快速一键部署高可用安全的Kubernetes集群以及阿里云的Cloud Provider所提供的能力. 以下内容根据演讲嘉宾现场视频以及速记整理而成. 今天主要会分享三个方面的问题: Kubernetes的基本概念介绍 如何在阿里云快速一键部署高可用安全的K

阿里云上部署开源PaaS平台Cloud Foundry实战

Cloud Foundry介绍 Cloud Foundry是业界第一个开源的PaaS,号称工业界唯一的云应用平台. 本文重点讲述Cloud Foundry在阿里云上的部署方案,对于Cloud Foundry介绍的部分简单略过. Cloud Foundry解决了什么问题? 关键词:PaaS.开源 Cloud Foundry是一种平台即服务(PaaS),兼容多种基础设施云,提供多种开发框架和应用服务.目前开源支持部署Cloud Foundry的基础设施云包括AWS.Azure.OpenStack等等

开源PaaS平台Cloud Foundry在阿里云上部署实战

Cloud Foundry介绍 Cloud Foundry是业界第一个开源的PaaS,号称工业界唯一的云应用平台. 本文重点讲述Cloud Foundry在阿里云上的部署方案,对于Cloud Foundry介绍的部分简单略过. Cloud Foundry解决了什么问题? 关键词:PaaS.开源 Cloud Foundry是一种平台即服务(PaaS),兼容多种基础设施云,提供多种开发框架和应用服务.目前开源支持部署Cloud Foundry的基础设施云包括AWS.Azure.OpenStack等等

阿里云ECS部署zabbix v3.2.3

阿里云ECS部署zabbix v3.2.3 阿里云ECS部署zabbix 3.2:并接入RDS 关于zabbix及相关服务软件版本: Linux: ECS_CentOS 7.2 nginx: 1.9.15 mysql: RDS或自建MySQL PHP:5.5.35 一.购买ECS & RDS 这里购买ECS和RDS最好买在一个区域,这样RDS就不用申请公网访问地址了,直接添加安装zabbix的ECS_IP白名单就OK了. 如果购买ECS和RDS都不会,那就不用往下看了. 二.安装Nginx 安装

阿里云一键部署 Spark 分布式集群

Apache Spark是专为大规模数据处理而设计的快速通用的计算引擎,可以完成各种各样的运算,包括 SQL 查询.文本处理.机器学习等,而在 Spark 出现之前,我们一般需要学习各种各样的引擎来分别处理这些需求.本文主要目的是为大家提供一种非常简单的方法,在阿里云上部署Spark集群. 通过<阿里云ROS资源编排服务>,将VPC.NAT Gateway.ECS创建,Hadoop和Spark部署过程自动化,使大家能够非常方便地部署一个Spark集群.本文创建的Spark集群包含三个节点:ma

阿里云一键部署LNMP(Linux+Nginx+MySQL+PHP)栈

LNMP代表Linux+Nginx+MySQL+PHP网站服务器架构.本文主要目的是为大家提供一种非常简单的方法,在阿里云上部署LNMP栈. 通过<阿里云ROS资源编排服务>,将VPC.NAT Gateway.ECS创建,LNMP栈部署过程自动化,使大家能够非常方便地部署一个LNMP栈. 急速部署LNMP栈 一键部署LNMP栈>> 注意: 必须确保可以正确下载nginx-.rpm安装包,我们可以选择类似如下的URL: http://nginx.org/packages/centos

如何在阿里云上部署Nginx实现反向代理?

如何在阿里云上部署Nginx实现反向代理? 云中沙箱实验"在阿里云上部署Nginx实现反向代理",教您如何在阿里云上部署Nginx实现反向代理? 云中沙箱,阿里云官方实验平台.网址:http://lab.aliyunedu.net   一.基本概念 业务背景     在很多情况下,可能只有一个公网IP地址,但是内部有多个服务需要映射出去,如:www.domain.com,oa.domain.com,并且,相关的服务不在同一台服务器上面的时候,那直接做端口映射就无法达到要求了.这时设置反

阿里云服务器经常CPU跑满,服务器宕机彻底解决方法

阿里云服务器经常CPU跑满,服务器宕机彻底解决方法 要解决这个问题首先先要知道问题出在哪里下面给大家介绍一下CPU跑满的一个案例 解决方法在文章最下方 CPU跑满的问题出现过很多次,最多的时候一天跑满四五次,整个网站在这样的环境下运营如何使得,发工单处理过几次,都是让重启服务器好的.改过端口.安装了防护软件检查,现在都没有任何的问题,5M带宽平均用不到2M,最大时也不过3M.之前服务器被黑过进行了快照回滚之后好了,但后来接二连三出现相同的问题,检查了服务器和网站程序,挂马已经都被清除,网站检查出