精华内容
下载资源
问答
  • 本文配置结构为3台kafka,2个orderer,4个peer 其中kafka需要安装jdk, peer需要安装go和docker 因为实际环境需要,本文全部都是离线安装,安装详见附件 系统 Ubuntu 16.04.3 ## hosts 将hosts复制到所有主机中 ...

    ## 引言

    文章写了块两年了,一直在公司内部分享,今天存放在这里,也算做个记录吧

    本文配置结构为3台kafka,2个orderer,4个peer

    其中kafka需要安装jdk,

    peer需要安装go和docker

    因为实际环境需要,本文全部都是离线安装,安装详见附件

    系统  Ubuntu 16.04.3 

    ## hosts

    将hosts复制到所有主机中 

    ```shell
    vim /etc/hosts

    192.168.3.181  node1  orderer1.local
    192.168.3.183  node2  orderer2.local
    192.168.3.185  node3  peer0.org1.local


    192.168.3.184  kafka1 
    192.168.3.186  kafka2
    192.168.3.119  kafka3

    # 分发到其他机器上
    scp /etc/hosts root@xxx.xxx.x.IP:/etc/
    ```

    ##kafka zookeeper集群配置

    kafka1、kafka2、kafka3

    ### 安装jdk

    ```shell
    mkdir /usr/local/software 
    # 将安装工具上传到/usr/local/software/目录下,为了分发方便,我将所有安装工具都放到这里了,后续的安装也会根据这个路径来

    # 分别将software分发到其他服务器上
    scp -r /usr/local/software root@XXX.XXX.XIP /usr/local/software
    # 解压jdk文件到/usr/local/目录下
    tar zxf /usr/local/software/jdk-8u144-linux-x64.tar.gz -C /usr/local/
    # 设置环境变量,这里偷了个懒,将其他服务器所需的kafka和go都设置了,后续就不再说明了,避免后续遗漏,最好所有服务器都执行
    echo "export JAVA_HOME=/usr/local/jdk1.8.0_144" >> ~/.profile
    echo 'export JRE_HOME=${JAVA_HOME}/jre' >>  ~/.profile
    echo 'export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib' >> ~/.profile
    echo 'export PATH=${JAVA_HOME}/bin:$PATH' >> ~/.profile
    echo 'export KAFKA_HOME=/usr/local/kafka_2.10-0.10.2.0' >> ~/.profile
    echo 'export PATH=$KAFKA_HOME/bin:$PATH' >> ~/.profile
    echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
    echo 'export GOPATH=/root/go' >> ~/.profile

    # 使环境变量生效
    source ~/.profile
    ```

    ### kafka zookeeper 安装

    ```shell
    # 解压zookeeper文件到/usr/local/目录下
    tar zxf /usr/local/software/zookeeper-3.4.10.tar.gz -C /usr/local/
    # 解压kafka文件到/usr/local/目录下
    tar zxf /usr/local/software/kafka_2.10-0.10.2.0.tgz -C /usr/local/
    # 修改server.properties配置文件,有就修改,没有则添加
    # 我已经将命令语句整理出,对应机器分别执行以下命令
    ```

    kafka1 server.properties

    ```shell
    sed -i 's/broker.id=0/broker.id=1/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    sed -i 's/zookeeper.connect=localhost:2181
    /zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    sed -i 's/tmp/data/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'listeners=PLAINTEXT://kafka1:9092' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'unclean.leader.election.enable=false' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'min.insync.replicas=1' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'default.replication.factor=2' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties

    #################以上命令修改和添加的变量################
    ## broker.id=1
    ## log.dirs=/data/kafka-logs
    ## zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181

    ## listeners=PLAINTEXT://kafka1:9092
    ## unclean.leader.election.enable=false
    ## min.insync.replicas=1
    ## default.replication.factor=2
    ```

    kafka2 server.properties

    ```shell
    sed -i 's/broker.id=0/broker.id=2/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    sed -i 's/zookeeper.connect=localhost:2181
    /zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    sed -i 's/tmp/data/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'listeners=PLAINTEXT://kafka2:9092' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'unclean.leader.election.enable=false' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'min.insync.replicas=1' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'default.replication.factor=2' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties

    #################以上命令修改和添加的变量################
    ## broker.id=2
    ## log.dirs=/data/kafka-logs
    ## zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181

    ## listeners=PLAINTEXT://kafka2:9092
    ## unclean.leader.election.enable=false
    ## min.insync.replicas=1
    ## default.replication.factor=2
    ```

    kafka3 server.properties

    ```shell
    sed -i 's/broker.id=0/broker.id=3/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    sed -i 's/zookeeper.connect=localhost:2181
    /zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    sed -i 's/tmp/data/g' /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'listeners=PLAINTEXT://kafka3:9092' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'unclean.leader.election.enable=false' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'min.insync.replicas=1' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties
    echo 'default.replication.factor=2' >> /usr/local/kafka_2.10-0.10.2.0/config/server.properties

    #################以上命令修改和添加的变量#################
    ## broker.id=2
    ## log.dirs=/data/kafka-logs
    ## zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181

    ## listeners=PLAINTEXT://kafka2:9092
    ## unclean.leader.election.enable=false
    ## min.insync.replicas=1
    ## default.replication.factor=2
    ```

    修改kafka里zookeeper配置文件,新增myid

    这里同样整理除了命令语句,对应机器分别执行即可

    ```shell
    #创建kafka和zookeeper相关文件夹,只要和properties文件中的log.dirs一致就行
    mkdir -p /data/kafka-logs
    mkdir -p /data/zookeeper
    ```

    zookeeper 1

    ```shell
    sed -i 's/tmp/data/g' /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'initLimit=5' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'syncLimit=2' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.1=kafka1:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.2=kafka2:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.3=kafka3:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 1 > /data/zookeeper/myid

    #################以上命令修改和添加的变量#################
    ## zookeeper.properties

    ### clientPort=2181
    ### initLimit=5
    ### syncLimit=2
    ### server.1=kafka1:2888:3888
    ### server.2=kafka2:2888:3888
    ### server.3=kafka3:2888:3888

    ## 新增myid,并设置值为1
    ```

    zookeeper 2

    ```shell
    sed -i 's/tmp/data/g' /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'initLimit=5' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'syncLimit=2' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.1=kafka1:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.2=kafka2:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.3=kafka3:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 2 > /data/zookeeper/myid

    #################以上命令修改和添加的变量#################
    ## zookeeper.properties

    ### clientPort=2181
    ### initLimit=5
    ### syncLimit=2
    ### server.1=kafka1:2888:3888
    ### server.2=kafka2:2888:3888
    ### server.3=kafka3:2888:3888

    ## 新增myid,并设置值为2
    ```

    zookeeper 3

    ```shell
    sed -i 's/tmp/data/g' /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'initLimit=5' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'syncLimit=2' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.1=kafka1:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.2=kafka2:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 'server.3=kafka3:2888:3888' >>  /usr/local/kafka_2.10-0.10.2.0/config/zookeeper.properties
    echo 3 > /data/zookeeper/myid

    #################以上命令修改和添加的变量#################
    ## zookeeper.properties

    ### clientPort=2181
    ### initLimit=5
    ### syncLimit=2
    ### server.1=kafka1:2888:3888
    ### server.2=kafka2:2888:3888
    ### server.3=kafka3:2888:3888

    ## 新增myid,并设置值为3
    ```

    补充:server.properties可选参数如下

    ```shell
    broker.id=0  #当前机器在集群中的唯一标识,和zookeeper的myid性质一样
    port=19092 #当前kafka对外提供服务的端口默认是9092
    host.name=192.168.7.100 #这个参数默认是关闭的,在0.8.1有个bug,DNS解析问题,失败率的问题。
    num.network.threads=3 #这个是borker进行网络处理的线程数
    num.io.threads=8 #这个是borker进行I/O处理的线程数
    log.dirs=/opt/kafka/kafkalogs/ #消息存放的目录,这个目录可以配置为“,”逗号分割的表达式,上面的num.io.threads要大于这个目录的个数这个目录,如果配置多个目录,新创建的topic他把消息持久化的地方是,当前以逗号分割的目录中,那个分区数最少就放那一个
    socket.send.buffer.bytes=102400 #发送缓冲区buffer大小,数据不是一下子就发送的,先回存储到缓冲区了到达一定的大小后在发送,能提高性能
    socket.receive.buffer.bytes=102400 #kafka接收缓冲区大小,当数据到达一定大小后在序列化到磁盘
    socket.request.max.bytes=104857600 #这个参数是向kafka请求消息或者向kafka发送消息的请请求的最大数,这个值不能超过java的堆栈大小
    num.partitions=1 #默认的分区数,一个topic默认1个分区数
    log.retention.hours=168 #默认消息的最大持久化时间,168小时,7天
    message.max.byte=5242880  #消息保存的最大值5M
    default.replication.factor=2  #kafka保存消息的副本数,如果一个副本失效了,另一个还可以继续提供服务
    replica.fetch.max.bytes=5242880  #取消息的最大直接数
    log.segment.bytes=1073741824 #这个参数是:因为kafka的消息是以追加的形式落地到文件,当超过这个值的时候,kafka会新起一个文件
    log.retention.check.interval.ms=300000 #每隔300000毫秒去检查上面配置的log失效时间(log.retention.hours=168 ),到目录查看是否有过期的消息如果有,删除
    log.cleaner.enable=false #是否启用log压缩,一般不用启用,启用的话可以提高性能
    zookeeper.connect=192.168.7.100:12181,192.168.7.101:12181,192.168.7.107:1218 #设置zookeeper的连接端口
    ```

    启动

    ```shell
    # 启动zookeeper
    nohup zookeeper-server-start.sh $KAFKA_HOME/config/zookeeper.properties >> ~/zookeeper.log 2>&1 &
    # 启动kafka
    nohup kafka-server-start.sh $KAFKA_HOME/config/server.properties  >> ~/kafka.log 2>&1 &

    jps
    # 查看kafka和zookeeper进程是否启动起来
    1462 Jps
    1193 Kafka
    937 QuorumPeerMain

    # kafka测试:
    #(1)一台机器上创建主题和生产者:
    $KAFKA_HOME/bin/./kafka-topics.sh --create --zookeeper kafka1:2181 --replication-factor 2 --partition 1 --topic test

    $KAFKA_HOME/bin/./kafka-console-producer.sh --broker-list kafka1:9092 --topic test

    #(2)另外2台接收消息
    $KAFKA_HOME/bin/./kafka-console-consumer.sh --zookeeper kafka1:2181 --topic test --from beginning
    ```

    kafka部署错误

    ```shell
    # 查看kafka server.properties 中的listener是否已设置
    # 查看log.dirs目录是否存在,是否拥有读写权限
    # 查看myid文件初始值是否写入
    # 查看内存是否够用

    # kafka和zookeeper其他相关命令

    # 查看所有主题
    $KAFKA_HOME/bin/kafka-topics.sh --zookeeper kafka1:2181 --list
    # 查看单个主题(test)详情
    $KAFKA_HOME/bin/kafka-topics.sh --describe --zookeeper kafka1:2181 --topic test

    # 关闭kafka 
    kafka-server-stop.sh
    # 关闭zookeeper
    zookeeper-server-stop.sh
    ```

    node3、node4、node5、node6

    ##安装GO

    ```shell
    # 解压go相关软件
    tar zxf /usr/local/software/go1.9.linux-amd64.tar.gz -C /usr/local/
    ```

    ##安装Docker

    ```shell
    # 安装deb版Docker,这里为ubunt deb安装文件
    dpkg -i /usr/local/software/*.deb

    # 启动 docker
    service docker start
    # 查看安装版本号  
    docker version

    Client:
     Version:      17.05.0-ce
     API version:  1.29
     Go version:   go1.7.5
     Git commit:   89658be
     Built:        Thu May  4 22:06:06 2017
     OS/Arch:      linux/amd64

    Server:
     Version:      17.05.0-ce
     API version:  1.29 (minimum version 1.12)
     Go version:   go1.7.5
     Git commit:   89658be
     Built:        Thu May  4 22:06:06 2017
     OS/Arch:      linux/amd64
     Experimental: false
     
    # load 镜像
    docker load -i /usr/local/software/fabric-javaenv.tar.gz
    docker load -i /usr/local/software/fabric-ccenv.tar.gz
    docker load -i /usr/local/software/fabric-baseimage.tar.gz
    docker load -i /usr/local/software/fabric-baseos.tar.gz
    ```

    ## fabric配置

    ### 配置文件说明

    ####orderer.yaml

        orderer启动读取的配置文件

    ```yaml
    ---
     ################################################################################
     #
     #   Orderer Configuration
     #
     #   - This controls the type and configuration of the orderer.
     #
     ################################################################################
    General:

         # Ledger Type: The ledger type to provide to the orderer.
         # Two non-production ledger types are provided for test purposes only:
         #  - ram: An in-memory ledger whose contents are lost on restart.
         #  - json: A simple file ledger that writes blocks to disk in JSON format.
         # Only one production ledger type is provided:
         #  - file: A production file-based ledger.
        LedgerType: file

         # Listen address: The IP on which to bind to listen.
        ListenAddress: 127.0.0.1

         # Listen port: The port on which to bind to listen.
        ListenPort: 7050

         # TLS: TLS settings for the GRPC server.
        TLS:
            Enabled: false
            PrivateKey: tls/server.key
            Certificate: tls/server.crt
            RootCAs:
              - tls/ca.crt
            ClientAuthEnabled: false
            ClientRootCAs:

         # Log Level: The level at which to log. This accepts logging specifications
         # per: fabric/docs/Setup/logging-control.md
        LogLevel: info

         # Genesis method: The method by which the genesis block for the orderer
         # system channel is specified. Available options are "provisional", "file":
         #  - provisional: Utilizes a genesis profile, specified by GenesisProfile,
         #                 to dynamically generate a new genesis block.
         #  - file: Uses the file provided by GenesisFile as the genesis block.
        GenesisMethod: provisional

         # Genesis profile: The profile to use to dynamically generate the genesis
         # block to use when initializing the orderer system channel and
         # GenesisMethod is set to "provisional". See the configtx.yaml file for the
         # descriptions of the available profiles. Ignored if GenesisMethod is set to
         # "file".
        GenesisProfile: SampleInsecureSolo

         # Genesis file: The file containing the genesis block to use when
         # initializing the orderer system channel and GenesisMethod is set to
         # "file". Ignored if GenesisMethod is set to "provisional".
        GenesisFile: genesisblock

         # LocalMSPDir is where to find the private crypto material needed by the
         # orderer. It is set relative here as a default for dev environments but
         # should be changed to the real location in production.
        LocalMSPDir: msp

         # LocalMSPID is the identity to register the local MSP material with the MSP
         # manager. IMPORTANT: The local MSP ID of an orderer needs to match the MSP
         # ID of one of the organizations defined in the orderer system channel's
         # /Channel/Orderer configuration. The sample organization defined in the
         # sample configuration provided has an MSP ID of "DEFAULT".
        LocalMSPID: DEFAULT

         # Enable an HTTP service for Go "pprof" profiling as documented at:
         # https://golang.org/pkg/net/http/pprof
        Profile:
            Enabled: false
            Address: 0.0.0.0:6060

         # BCCSP configures the blockchain crypto service providers.
        BCCSP:
             # Default specifies the preferred blockchain crypto service provider
             # to use. If the preferred provider is not available, the software
             # based provider ("SW") will be used.
             # Valid providers are:
             #  - SW: a software based crypto provider
             #  - PKCS11: a CA hardware security module crypto provider.
            Default: SW

             # SW configures the software based blockchain crypto provider.
            SW:
                 # TODO: The default Hash and Security level needs refactoring to be
                 # fully configurable. Changing these defaults requires coordination
                 # SHA2 is hardcoded in several places, not only BCCSP
                Hash: SHA2
                Security: 256
                 # Location of key store. If this is unset, a location will be
                 # chosen using: 'LocalMSPDir'/keystore
                FileKeyStore:
                    KeyStore:

     ################################################################################
     #
     #   SECTION: File Ledger
     #
     #   - This section applies to the configuration of the file or json ledgers.
     #
     ################################################################################
    FileLedger:

         # Location: The directory to store the blocks in.
         # NOTE: If this is unset, a new temporary location will be chosen every time
         # the orderer is restarted, using the prefix specified by Prefix.
        Location: /var/hyperledger/production/orderer

         # The prefix to use when generating a ledger directory in temporary space.
         # Otherwise, this value is ignored.
        Prefix: hyperledger-fabric-ordererledger

     ################################################################################
     #
     #   SECTION: RAM Ledger
     #
     #   - This section applies to the configuration of the RAM ledger.
     #
     ################################################################################
    RAMLedger:

         # History Size: The number of blocks that the RAM ledger is set to retain.
         # WARNING: Appending a block to the ledger might cause the oldest block in
         # the ledger to be dropped in order to limit the number total number blocks
         # to HistorySize. For example, if history size is 10, when appending block
         # 10, block 0 (the genesis block!) will be dropped to make room for block 10.
        HistorySize: 1000

     ################################################################################
     #
     #   SECTION: Kafka
     #
     #   - This section applies to the configuration of the Kafka-based orderer, and
     #     its interaction with the Kafka cluster.
     #
     ################################################################################
    Kafka:

         # Retry: What do if a connection to the Kafka cluster cannot be established,
         # or if a metadata request to the Kafka cluster needs to be repeated.
        Retry:
             # When a new channel is created, or when an existing channel is reloaded
             # (in case of a just-restarted orderer), the orderer interacts with the
             # Kafka cluster in the following ways:
             # 1. It creates a Kafka producer (writer) for the Kafka partition that
             # corresponds to the channel.
             # 2. It uses that producer to post a no-op CONNECT message to that
             # partition
             # 3. It creates a Kafka consumer (reader) for that partition.
             # If any of these steps fail, they will be re-attempted every
             # <ShortInterval> for a total of <ShortTotal>, and then every
             # <LongInterval> for a total of <LongTotal> until they succeed.
             # Note that the orderer will be unable to write to or read from a
             # channel until all of the steps above have been completed successfully.
            ShortInterval: 5s
            ShortTotal: 10m
            LongInterval: 5m
            LongTotal: 12h
             # Affects the socket timeouts when waiting for an initial connection, a
             # response, or a transmission. See Config.Net for more info:
             # https://godoc.org/github.com/Shopify/sarama#Config
            NetworkTimeouts:
                DialTimeout: 10s
                ReadTimeout: 10s
                WriteTimeout: 10s
             # Affects the metadata requests when the Kafka cluster is in the middle
             # of a leader election.See Config.Metadata for more info:
             # https://godoc.org/github.com/Shopify/sarama#Config
            Metadata:
                RetryBackoff: 250ms
                RetryMax: 3
             # What to do if posting a message to the Kafka cluster fails. See
             # Config.Producer for more info:
             # https://godoc.org/github.com/Shopify/sarama#Config
            Producer:
                RetryBackoff: 100ms
                RetryMax: 3
            # What to do if reading from the Kafka cluster fails. See
             # Config.Consumer for more info:
             # https://godoc.org/github.com/Shopify/sarama#Config
            Consumer:
                RetryBackoff: 2s

         # Verbose: Enable logging for interactions with the Kafka cluster.
        Verbose: false

         # TLS: TLS settings for the orderer's connection to the Kafka cluster.
        TLS:

           # Enabled: Use TLS when connecting to the Kafka cluster.
          Enabled: false

           # PrivateKey: PEM-encoded private key the orderer will use for
           # authentication.
          PrivateKey:
             # As an alternative to specifying the PrivateKey here, uncomment the
             # following "File" key and specify the file name from which to load the
             # value of PrivateKey.
             #File: path/to/PrivateKey

           # Certificate: PEM-encoded signed public key certificate the orderer will
           # use for authentication.
          Certificate:
             # As an alternative to specifying the Certificate here, uncomment the
             # following "File" key and specify the file name from which to load the
             # value of Certificate.
             #File: path/to/Certificate

           # RootCAs: PEM-encoded trusted root certificates used to validate
           # certificates from the Kafka cluster.
          RootCAs:
             # As an alternative to specifying the RootCAs here, uncomment the
             # following "File" key and specify the file name from which to load the
             # value of RootCAs.
             #File: path/to/RootCAs

         # Kafka version of the Kafka cluster brokers (defaults to 0.9.0.1)
        Version:
    ```

    #### crypto-config.yaml

        生成网络拓扑和证书

        文件可以帮我们为每个组织和组织中的成员生成证书库。每个组织分配一个根证书(ca-cert),这个根证书会绑定一些peers和orders到这个组织。fabric中的交易和通信都会被一个参与者的私钥(keystore)签名,并会被公钥(signcerts)验证。最后Users Count=1是说每个Template下面会有几个普通User(注意,Admin是Admin,不包含在这个计数中),这里配置了1,也就是说我们只需要一个普通用户User1@org2.local 我们可以根据实际需要调整这个配置文件,增删Org Users等

    ```yaml
    # ---------------------------------------------------------------------------
    # "OrdererOrgs" - Definition of organizations managing orderer nodes
    # ---------------------------------------------------------------------------
    OrdererOrgs:
      # ---------------------------------------------------------------------------
      # Orderer
      # ---------------------------------------------------------------------------
      - Name: Orderer
        Domain: orderer.local
        # ---------------------------------------------------------------------------
        # "Specs" - See PeerOrgs below for complete description
        # ---------------------------------------------------------------------------
        Specs:
          - Hostname: orderer1.local
            CommonName: orderer1.local
          - Hostname: orderer2.local
            CommonName: orderer2.local
    # ---------------------------------------------------------------------------
    # "PeerOrgs" - Definition of organizations managing peer nodes
    # ---------------------------------------------------------------------------
    PeerOrgs:
      # ---------------------------------------------------------------------------
      # Org1
      # ---------------------------------------------------------------------------
      - Name: Org1
        Domain: org1.local
        # ---------------------------------------------------------------------------
        # "Specs"
        # ---------------------------------------------------------------------------
        # Uncomment this section to enable the explicit definition of hosts in your
        # configuration.  Most users will want to use Template, below
        #
        # Specs is an array of Spec entries.  Each Spec entry consists of two fields:
        #   - Hostname:   (Required) The desired hostname, sans the domain.
        #   - CommonName: (Optional) Specifies the template or explicit override for
        #                 the CN.  By default, this is the template:
        #
        #                              "{{.Hostname}}.{{.Domain}}"
        #
        #                 which obtains its values from the Spec.Hostname and
        #                 Org.Domain, respectively.
        # ---------------------------------------------------------------------------
        # Specs:
        #   - Hostname: foo # implicitly "foo.org1.example.com"
        #     CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
        #   - Hostname: bar
        #   - Hostname: baz
        Specs:
          - Hostname: peer0.org1.local
            CommonName: peer0.org1.local
        # ---------------------------------------------------------------------------
        # "Template"
        # ---------------------------------------------------------------------------
        # Allows for the definition of 1 or more hosts that are created sequentially
        # from a template. By default, this looks like "peer%d" from 0 to Count-1.
        # You may override the number of nodes (Count), the starting index (Start)
        # or the template used to construct the name (Hostname).
        #
        # Note: Template and Specs are not mutually exclusive.  You may define both
        # sections and the aggregate nodes will be created for you.  Take care with
        # name collisions
        # ---------------------------------------------------------------------------
        Template:
          Count: 2
          # Start: 5
          # Hostname: {{.Prefix}}{{.Index}} # default
        # ---------------------------------------------------------------------------
        # "Users"
        # ---------------------------------------------------------------------------
        # Count: The number of user accounts _in addition_ to Admin
        # ---------------------------------------------------------------------------
        Users:
          Count: 1
      # ---------------------------------------------------------------------------
      # Org2: See "Org1" for full specification
      # ---------------------------------------------------------------------------
      - Name: Org2
        Domain: org2.local
        Specs:
          - Hostname: peer0.org2.local
            CommonName: peer0.org2.local
        Template:
          Count: 2
        Users:
          Count: 1
    ```

    core.yaml peer启动读取的配置文件

    ```yaml
    ###############################################################################
     #
     #    LOGGING section
     #
     ###############################################################################
    logging:

         # Default logging levels are specified here.

         # Valid logging levels are case-insensitive strings chosen from

         #     CRITICAL | ERROR | WARNING | NOTICE | INFO | DEBUG

         # The overall default logging level can be specified in various ways,
         # listed below from strongest to weakest:
         #
         # 1. The --logging-level=<level> command line option overrides all other
         #    default specifications.
         #
         # 2. The environment variable CORE_LOGGING_LEVEL otherwise applies to
         #    all peer commands if defined as a non-empty string.
         #
         # 3. The value of peer that directly follows in this file. It can also
         #    be set via the environment variable CORE_LOGGING_PEER.
         #
         # If no overall default level is provided via any of the above methods,
         # the peer will default to INFO (the value of defaultLevel in
         # common/flogging/logging.go)

         # Default for all modules running within the scope of a peer.
         # Note: this value is only used when --logging-level or CORE_LOGGING_LEVEL
         #       are not set
        peer:       info

         # The overall default values mentioned above can be overridden for the
         # specific components listed in the override section below.

         # Override levels for various peer modules. These levels will be
         # applied once the peer has completely started. They are applied at this
         # time in order to be sure every logger has been registered with the
         # logging package.
         # Note: the modules listed below are the only acceptable modules at this
         #       time.
        cauthdsl:   warning
        gossip:     warning
        ledger:     info
        msp:        warning
        policies:   warning
        grpc:       error

         # Message format for the peer logs
        format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'

     ###############################################################################
     #
     #    Peer section
     #
     ###############################################################################
    peer:

         # The Peer id is used for identifying this Peer instance.
        id: jdoe

         # The networkId allows for logical seperation of networks
        networkId: dev

         # The Address at local network interface this Peer will listen on.
         # By default, it will listen on all network interfaces
        listenAddress: 0.0.0.0:7051

         # The endpoint this peer uses to listen for inbound chaincode connections.
         #
         # The chaincode connection does not support TLS-mutual auth. Having a
         # separate listener for the chaincode helps isolate the chaincode
         # environment for enhanced security, so it is strongly recommended to
         # uncomment chaincodeListenAddress and specify a protected endpoint.
         #
         # If chaincodeListenAddress is not configured or equals to the listenAddress,
         # listenAddress will be used for chaincode connections. This is not
         # recommended for production.
         #
         # chaincodeListenAddress: 127.0.0.1:7052

         # When used as peer config, this represents the endpoint to other peers
         # in the same organization for peers in other organization, see
         # gossip.externalEndpoint for more info.
         # When used as CLI config, this means the peer's endpoint to interact with
        address: 0.0.0.0:7051

         # Whether the Peer should programmatically determine its address
         # This case is useful for docker containers.
        addressAutoDetect: false

         # Setting for runtime.GOMAXPROCS(n). If n < 1, it does not change the
         # current setting
        gomaxprocs: -1

         # Gossip related configuration
        gossip:
             # Bootstrap set to initialize gossip with.
             # This is a list of other peers that this peer reaches out to at startup.
             # Important: The endpoints here have to be endpoints of peers in the same
             # organization, because the peer would refuse connecting to these endpoints
             # unless they are in the same organization as the peer.
            bootstrap: 127.0.0.1:7051

             # NOTE: orgLeader and useLeaderElection parameters are mutual exclusive.
             # Setting both to true would result in the termination of the peer
             # since this is undefined state. If the peers are configured with
             # useLeaderElection=false, make sure there is at least 1 peer in the
             # organization that its orgLeader is set to true.

             # Defines whenever peer will initialize dynamic algorithm for
             # "leader" selection, where leader is the peer to establish
             # connection with ordering service and use delivery protocol
             # to pull ledger blocks from ordering service. It is recommended to
             # use leader election for large networks of peers.
            useLeaderElection: false
             # Statically defines peer to be an organization "leader",
             # where this means that current peer will maintain connection
             # with ordering service and disseminate block across peers in
             # its own organization
            orgLeader: true

             # Overrides the endpoint that the peer publishes to peers
             # in its organization. For peers in foreign organizations
             # see 'externalEndpoint'
            endpoint:
             # Maximum count of blocks stored in memory
            maxBlockCountToStore: 100
             # Max time between consecutive message pushes(unit: millisecond)
            maxPropagationBurstLatency: 10ms
             # Max number of messages stored until a push is triggered to remote peers
            maxPropagationBurstSize: 10
             # Number of times a message is pushed to remote peers
            propagateIterations: 1
             # Number of peers selected to push messages to
            propagatePeerNum: 3
             # Determines frequency of pull phases(unit: second)
            pullInterval: 4s
             # Number of peers to pull from
            pullPeerNum: 3
             # Determines frequency of pulling state info messages from peers(unit: second)
            requestStateInfoInterval: 4s
             # Determines frequency of pushing state info messages to peers(unit: second)
            publishStateInfoInterval: 4s
             # Maximum time a stateInfo message is kept until expired
            stateInfoRetentionInterval:
             # Time from startup certificates are included in Alive messages(unit: second)
            publishCertPeriod: 10s
             # Should we skip verifying block messages or not (currently not in use)
            skipBlockVerification: false
             # Dial timeout(unit: second)
            dialTimeout: 3s
             # Connection timeout(unit: second)
            connTimeout: 2s
             # Buffer size of received messages
            recvBuffSize: 20
             # Buffer size of sending messages
            sendBuffSize: 200
             # Time to wait before pull engine processes incoming digests (unit: second)
            digestWaitTime: 1s
             # Time to wait before pull engine removes incoming nonce (unit: second)
            requestWaitTime: 1s
             # Time to wait before pull engine ends pull (unit: second)
            responseWaitTime: 2s
             # Alive check interval(unit: second)
            aliveTimeInterval: 5s
             # Alive expiration timeout(unit: second)
            aliveExpirationTimeout: 25s
             # Reconnect interval(unit: second)
            reconnectInterval: 25s
             # This is an endpoint that is published to peers outside of the organization.
             # If this isn't set, the peer will not be known to other organizations.
            externalEndpoint:
             # Leader election service configuration
            election:
                 # Longest time peer waits for stable membership during leader election startup (unit: second)
                startupGracePeriod: 15s
                 # Interval gossip membership samples to check its stability (unit: second)
                membershipSampleInterval: 1s
                 # Time passes since last declaration message before peer decides to perform leader election (unit: second)
                leaderAliveThreshold: 10s
                 # Time between peer sends propose message and declares itself as a leader (sends declaration message) (unit: second)
                leaderElectionDuration: 5s

         # EventHub related configuration
        events:
             # The address that the Event service will be enabled on the peer
            address: 0.0.0.0:7053

             # total number of events that could be buffered without blocking send
            buffersize: 100

             # timeout duration for producer to send an event.
             # if < 0, if buffer full, unblocks immediately and not send
             # if 0, if buffer full, will block and guarantee the event will be sent out
             # if > 0, if buffer full, blocks till timeout
            timeout: 10ms

         # TLS Settings
         # Note that peer-chaincode connections through chaincodeListenAddress is
         # not mutual TLS auth. See comments on chaincodeListenAddress for more info
        tls:
            enabled:  false
            cert:
                file: tls/server.crt
            key:
                file: tls/server.key
            rootcert:
                file: tls/ca.crt

             # The server name use to verify the hostname returned by TLS handshake
            serverhostoverride:

         # Path on the file system where peer will store data (eg ledger). This
         # location must be access control protected to prevent unintended
         # modification that might corrupt the peer operations.
        fileSystemPath: /var/hyperledger/production

         # BCCSP (Blockchain crypto provider): Select which crypto implementation or
         # library to use
        BCCSP:
            Default: SW
            SW:
                 # TODO: The default Hash and Security level needs refactoring to be
                 # fully configurable. Changing these defaults requires coordination
                 # SHA2 is hardcoded in several places, not only BCCSP
                Hash: SHA2
                Security: 256
                 # Location of Key Store
                FileKeyStore:
                     # If "", defaults to 'mspConfigPath'/keystore
                     # TODO: Ensure this is read with fabric/core/config.GetPath() once ready
                    KeyStore:

         # Path on the file system where peer will find MSP local configurations
        mspConfigPath: msp

         # Identifier of the local MSP
         # ----!!!!IMPORTANT!!!-!!!IMPORTANT!!!-!!!IMPORTANT!!!!----
         # Deployers need to change the value of the localMspId string.
         # In particular, the name of the local MSP ID of a peer needs
         # to match the name of one of the MSPs in each of the channel
         # that this peer is a member of. Otherwise this peer's messages
         # will not be identified as valid by other nodes.
        localMspId: DEFAULT

         # Used with Go profiling tools only in none production environment. In
         # production, it should be disabled (eg enabled: false)
        profile:
            enabled:     false
            listenAddress: 0.0.0.0:6060

     ###############################################################################
     #
     #    VM section
     #
     ###############################################################################
    vm:

         # Endpoint of the vm management system.  For docker can be one of the following in general
         # unix:///var/run/docker.sock
         # http://localhost:2375
         # https://localhost:2376
        endpoint: unix:///var/run/docker.sock

         # settings for docker vms
        docker:
            tls:
                enabled: false
                ca:
                    file: docker/ca.crt
                cert:
                    file: docker/tls.crt
                key:
                    file: docker/tls.key

             # Enables/disables the standard out/err from chaincode containers for
             # debugging purposes
            attachStdout: false

             # Parameters on creating docker container.
             # Container may be efficiently created using ipam & dns-server for cluster
             # NetworkMode - sets the networking mode for the container. Supported
             # standard values are: `host`(default),`bridge`,`ipvlan`,`none`.
             # Dns - a list of DNS servers for the container to use.
             # Note:  `Privileged` `Binds` `Links` and `PortBindings` properties of
             # Docker Host Config are not supported and will not be used if set.
             # LogConfig - sets the logging driver (Type) and related options
             # (Config) for Docker. For more info,
             # https://docs.docker.com/engine/admin/logging/overview/
             # Note: Set LogConfig using Environment Variables is not supported.
            hostConfig:
                NetworkMode: host
                Dns:
                    # - 192.168.0.1
                LogConfig:
                    Type: json-file
                    Config:
                        max-size: "50m"
                        max-file: "5"
                Memory: 2147483648

     ###############################################################################
     #
     #    Chaincode section
     #
     ###############################################################################
    chaincode:
         # This is used if chaincode endpoint resolution fails with the
         # chaincodeListenAddress property
        peerAddress:

         # The id is used by the Chaincode stub to register the executing Chaincode
         # ID with the Peer and is generally supplied through ENV variables
         # the `path` form of ID is provided when installing the chaincode.
         # The `name` is used for all other requests and can be any string.
        id:
            path:
            name:

         # Generic builder environment, suitable for most chaincode types
        builder: $(DOCKER_NS)/fabric-ccenv:$(ARCH)-$(PROJECT_VERSION)

        golang:
             # golang will never need more than baseos
            runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)

        car:
             # car may need more facilities (JVM, etc) in the future as the catalog
             # of platforms are expanded.  For now, we can just use baseos
            runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)

        java:
             # This is an image based on java:openjdk-8 with addition compiler
             # tools added for java shim layer packaging.
             # This image is packed with shim layer libraries that are necessary
             # for Java chaincode runtime.
            Dockerfile:  |
                from $(DOCKER_NS)/fabric-javaenv:$(ARCH)-$(PROJECT_VERSION)

         # Timeout duration for starting up a container and waiting for Register
         # to come through. 1sec should be plenty for chaincode unit tests
        startuptimeout: 300s

         # Timeout duration for Invoke and Init calls to prevent runaway.
         # This timeout is used by all chaincodes in all the channels, including
         # system chaincodes.
         # Note that during Invoke, if the image is not available (e.g. being
         # cleaned up when in development environment), the peer will automatically
         # build the image, which might take more time. In production environment,
         # the chaincode image is unlikely to be deleted, so the timeout could be
         # reduced accordingly.
        executetimeout: 30s

         # There are 2 modes: "dev" and "net".
         # In dev mode, user runs the chaincode after starting peer from
         # command line on local machine.
         # In net mode, peer will run chaincode in a docker container.
        mode: net

         # keepalive in seconds. In situations where the communiction goes through a
         # proxy that does not support keep-alive, this parameter will maintain connection
         # between peer and chaincode.
         # A value <= 0 turns keepalive off
        keepalive: 0

         # system chaincodes whitelist. To add system chaincode "myscc" to the
         # whitelist, add "myscc: enable" to the list below, and register in
         # chaincode/importsysccs.go
        system:
            cscc: enable
            lscc: enable
            escc: enable
            vscc: enable
            qscc: enable

         # Logging section for the chaincode container
        logging:
           # Default level for all loggers within the chaincode container
          level:  info
           # Override default level for the 'shim' module
          shim:   warning
           # Format for the chaincode container logs
          format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'

     ###############################################################################
     #
     #    Ledger section - ledger configuration encompases both the blockchain
     #    and the state
     #
     ###############################################################################
    ledger:

      blockchain:

      state:
         # stateDatabase - options are "goleveldb", "CouchDB"
         # goleveldb - default state database stored in goleveldb.
         # CouchDB - store state database in CouchDB
        stateDatabase: goleveldb
        couchDBConfig:
            # It is recommended to run CouchDB on the same server as the peer, and
            # not map the CouchDB container port to a server port in docker-compose.
            # Otherwise proper security must be provided on the connection between
            # CouchDB client (on the peer) and server.
           couchDBAddress: 127.0.0.1:5984
            # This username must have read and write authority on CouchDB
           username:
            # The password is recommended to pass as an environment variable
            # during start up (eg LEDGER_COUCHDBCONFIG_PASSWORD).
            # If it is stored here, the file must be access control protected
            # to prevent unintended users from discovering the password.
           password:
            # Number of retries for CouchDB errors
           maxRetries: 3
            # Number of retries for CouchDB errors during peer startup
           maxRetriesOnStartup: 10
            # CouchDB request timeout (unit: duration, e.g. 20s)
           requestTimeout: 35s
            # Limit on the number of records to return per query
           queryLimit: 10000


      history:
         # enableHistoryDatabase - options are true or false
         # Indicates if the history of key updates should be stored.
         # All history 'index' will be stored in goleveldb, regardless if using
         # CouchDB or alternate database for the state.
    enableHistoryDatabase: true
    ```

    ####configtx.yaml 

        生成网络拓扑和证书

        文件包含网络的定义,网络中有2个成员(Org1和Org2)分别管理维护2个peer。 在文件最上方 “Profile”段落中,有两个header,一个是orderer genesis block - TwoOrgsOrdererGenesis ,另一个是channel - TwoOrgsChannel。这两个header十分重要,我们创建artifacts是我们会把他们作为参数传入。文件中还包含每个成员的MSP 目录位置.crypto目录包含每个实体的admin证书、ca证书、签名证书和私钥

    ```yaml
    ---
    ################################################################################
    #
    #   Profile
    #
    #   - Different configuration profiles may be encoded here to be specified
    #   as parameters to the configtxgen tool
    #
    ################################################################################
    Profiles:

     TwoOrgsOrdererGenesis:
         Orderer:
             <<: *OrdererDefaults
             Organizations:
                 - *OrdererOrg
         Consortiums:
             SampleConsortium:
                 Organizations:
                     - *Org1
                     - *Org2
     TwoOrgsChannel:
         Consortium: SampleConsortium
         Application:
             <<: *ApplicationDefaults
             Organizations:
                 - *Org1
                 - *Org2

    ################################################################################
    #
    #   Section: Organizations
    #
    #   - This section defines the different organizational identities which will
    #   be referenced later in the configuration.
    #
    ################################################################################
    Organizations:

     # SampleOrg defines an MSP using the sampleconfig.  It should never be used
     # in production but may be used as a template for other definitions
     - &OrdererOrg
         # DefaultOrg defines the organization which is used in the sampleconfig
         # of the fabric.git development environment
         Name: OrdererOrg

         # ID to load the MSP definition as
         ID: OrdererMSP

         # MSPDir is the filesystem path which contains the MSP configuration
         MSPDir: crypto-config/ordererOrganizations/orderer.local/msp


     - &Org1
         # DefaultOrg defines the organization which is used in the sampleconfig
         # of the fabric.git development environment
         Name: Org1MSP

         # ID to load the MSP definition as
         ID: Org1MSP

         MSPDir: crypto-config/peerOrganizations/org1.local/msp

         AnchorPeers:
             # AnchorPeers defines the location of peers which can be used
             # for cross org gossip communication.  Note, this value is only
             # encoded in the genesis block in the Application section context
    #         - Host: peer0.org1.local
    #           Port: 7051
    #         - Host: peer1.org1.local
    #           Port: 7051

     - &Org2
         # DefaultOrg defines the organization which is used in the sampleconfig
         # of the fabric.git development environment
         Name: Org2MSP

         # ID to load the MSP definition as
         ID: Org2MSP

         MSPDir: crypto-config/peerOrganizations/org2.local/msp

         AnchorPeers:
             # AnchorPeers defines the location of peers which can be used
             # for cross org gossip communication.  Note, this value is only
             # encoded in the genesis block in the Application section context
    #         - Host: peer0.org2.local
    #           Port: 7051
    #         - Host: peer1.org2.local
    #           Port: 7051
    ################################################################################
    #
    #   SECTION: Orderer
    #
    #   - This section defines the values to encode into a config transaction or
    #   genesis block for orderer related parameters
    #
    ################################################################################
    Orderer: &OrdererDefaults

     # Orderer Type: The orderer implementation to start
     # Available types are "solo" and "kafka"
     OrdererType: kafka

     Addresses:
         - orderer1.local:7050
         - orderer2.local:7050
         #- orderer3.local:7050
     # Batch Timeout: The amount of time to wait before creating a batch
     BatchTimeout: 2s

     # Batch Size: Controls the number of messages batched into a block
     BatchSize:

         # Max Message Count: The maximum number of messages to permit in a batch
         MaxMessageCount: 10

         # Absolute Max Bytes: The absolute maximum number of bytes allowed for
         # the serialized messages in a batch.
         AbsoluteMaxBytes: 99 MB

         # Preferred Max Bytes: The preferred maximum number of bytes allowed for
         # the serialized messages in a batch. A message larger than the preferred
         # max bytes will result in a batch larger than preferred max bytes.
         PreferredMaxBytes: 512 KB

     Kafka:
         # Brokers: A list of Kafka brokers to which the orderer connects
         # NOTE: Use IP:port notation
         Brokers:
             - kafka1:9092
             - kafka2:9092
             - kafka3:9092

     # Organizations is the list of orgs which are defined as participants on
     # the orderer side of the network
     Organizations:

    ################################################################################
    #
    #   SECTION: Application
    #
    #   - This section defines the values to encode into a config transaction or
    #   genesis block for application related parameters
    #
    ################################################################################
    Application: &ApplicationDefaults

        # Organizations is the list of orgs which are defined as participants on
        # the application side of the network
        Organizations:
    ```

    ####core.yaml 

        peer启动读取的配置文件

    ```yaml
    ###############################################################################
    #
    #    LOGGING section
    #
    ###############################################################################
    logging:

        # Default logging levels are specified here.

        # Valid logging levels are case-insensitive strings chosen from

        #     CRITICAL | ERROR | WARNING | NOTICE | INFO | DEBUG

        # The overall default logging level can be specified in various ways,
        # listed below from strongest to weakest:
        #
        # 1. The --logging-level=<level> command line option overrides all other
        #    default specifications.
        #
        # 2. The environment variable CORE_LOGGING_LEVEL otherwise applies to
        #    all peer commands if defined as a non-empty string.
        #
        # 3. The value of peer that directly follows in this file. It can also
        #    be set via the environment variable CORE_LOGGING_PEER.
        #
        # If no overall default level is provided via any of the above methods,
        # the peer will default to INFO (the value of defaultLevel in
        # common/flogging/logging.go)

        # Default for all modules running within the scope of a peer.
        # Note: this value is only used when --logging-level or CORE_LOGGING_LEVEL
        #       are not set
        peer:       info

        # The overall default values mentioned above can be overridden for the
        # specific components listed in the override section below.

        # Override levels for various peer modules. These levels will be
        # applied once the peer has completely started. They are applied at this
        # time in order to be sure every logger has been registered with the
        # logging package.
        # Note: the modules listed below are the only acceptable modules at this
        #       time.
        cauthdsl:   warning
        gossip:     warning
        ledger:     info
        msp:        warning
        policies:   warning
        grpc:       error

        # Message format for the peer logs
        format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'

    ###############################################################################
    #
    #    Peer section
    #
    ###############################################################################
    peer:

        # The Peer id is used for identifying this Peer instance.
        id: jdoe

        # The networkId allows for logical seperation of networks
        networkId: dev

        # The Address at local network interface this Peer will listen on.
        # By default, it will listen on all network interfaces
        listenAddress: 0.0.0.0:7051

        # The endpoint this peer uses to listen for inbound chaincode connections.
        #
        # The chaincode connection does not support TLS-mutual auth. Having a
        # separate listener for the chaincode helps isolate the chaincode
        # environment for enhanced security, so it is strongly recommended to
        # uncomment chaincodeListenAddress and specify a protected endpoint.
        #
        # If chaincodeListenAddress is not configured or equals to the listenAddress,
        # listenAddress will be used for chaincode connections. This is not
        # recommended for production.
        #
        # chaincodeListenAddress: 127.0.0.1:7052

        # When used as peer config, this represents the endpoint to other peers
        # in the same organization for peers in other organization, see
        # gossip.externalEndpoint for more info.
        # When used as CLI config, this means the peer's endpoint to interact with
        address: 0.0.0.0:7051

        # Whether the Peer should programmatically determine its address
        # This case is useful for docker containers.
        addressAutoDetect: false

        # Setting for runtime.GOMAXPROCS(n). If n < 1, it does not change the
        # current setting
        gomaxprocs: -1

        # Gossip related configuration
        gossip:
            # Bootstrap set to initialize gossip with.
            # This is a list of other peers that this peer reaches out to at startup.
            # Important: The endpoints here have to be endpoints of peers in the same
            # organization, because the peer would refuse connecting to these endpoints
            # unless they are in the same organization as the peer.
            bootstrap: 127.0.0.1:7051

            # NOTE: orgLeader and useLeaderElection parameters are mutual exclusive.
            # Setting both to true would result in the termination of the peer
            # since this is undefined state. If the peers are configured with
            # useLeaderElection=false, make sure there is at least 1 peer in the
            # organization that its orgLeader is set to true.

            # Defines whenever peer will initialize dynamic algorithm for
            # "leader" selection, where leader is the peer to establish
            # connection with ordering service and use delivery protocol
            # to pull ledger blocks from ordering service. It is recommended to
            # use leader election for large networks of peers.
            useLeaderElection: false
            # Statically defines peer to be an organization "leader",
            # where this means that current peer will maintain connection
            # with ordering service and disseminate block across peers in
            # its own organization
            orgLeader: true

            # Overrides the endpoint that the peer publishes to peers
            # in its organization. For peers in foreign organizations
            # see 'externalEndpoint'
            endpoint:
            # Maximum count of blocks stored in memory
            maxBlockCountToStore: 100
            # Max time between consecutive message pushes(unit: millisecond)
            maxPropagationBurstLatency: 10ms
            # Max number of messages stored until a push is triggered to remote peers
            maxPropagationBurstSize: 10
            # Number of times a message is pushed to remote peers
            propagateIterations: 1
            # Number of peers selected to push messages to
            propagatePeerNum: 3
            # Determines frequency of pull phases(unit: second)
            pullInterval: 4s
            # Number of peers to pull from
            pullPeerNum: 3
            # Determines frequency of pulling state info messages from peers(unit: second)
            requestStateInfoInterval: 4s
            # Determines frequency of pushing state info messages to peers(unit: second)
            publishStateInfoInterval: 4s
            # Maximum time a stateInfo message is kept until expired
            stateInfoRetentionInterval:
            # Time from startup certificates are included in Alive messages(unit: second)
            publishCertPeriod: 10s
            # Should we skip verifying block messages or not (currently not in use)
            skipBlockVerification: false
            # Dial timeout(unit: second)
            dialTimeout: 3s
            # Connection timeout(unit: second)
            connTimeout: 2s
            # Buffer size of received messages
            recvBuffSize: 20
            # Buffer size of sending messages
            sendBuffSize: 200
            # Time to wait before pull engine processes incoming digests (unit: second)
            digestWaitTime: 1s
            # Time to wait before pull engine removes incoming nonce (unit: second)
            requestWaitTime: 1s
            # Time to wait before pull engine ends pull (unit: second)
            responseWaitTime: 2s
            # Alive check interval(unit: second)
            aliveTimeInterval: 5s
            # Alive expiration timeout(unit: second)
            aliveExpirationTimeout: 25s
            # Reconnect interval(unit: second)
            reconnectInterval: 25s
            # This is an endpoint that is published to peers outside of the organization.
            # If this isn't set, the peer will not be known to other organizations.
            externalEndpoint:
            # Leader election service configuration
            election:
                # Longest time peer waits for stable membership during leader election startup (unit: second)
                startupGracePeriod: 15s
                # Interval gossip membership samples to check its stability (unit: second)
                membershipSampleInterval: 1s
                # Time passes since last declaration message before peer decides to perform leader election (unit: second)
                leaderAliveThreshold: 10s
                # Time between peer sends propose message and declares itself as a leader (sends declaration message) (unit: second)
                leaderElectionDuration: 5s

        # EventHub related configuration
        events:
            # The address that the Event service will be enabled on the peer
            address: 0.0.0.0:7053

            # total number of events that could be buffered without blocking send
            buffersize: 100

            # timeout duration for producer to send an event.
            # if < 0, if buffer full, unblocks immediately and not send
            # if 0, if buffer full, will block and guarantee the event will be sent out
            # if > 0, if buffer full, blocks till timeout
            timeout: 10ms

        # TLS Settings
        # Note that peer-chaincode connections through chaincodeListenAddress is
        # not mutual TLS auth. See comments on chaincodeListenAddress for more info
        tls:
            enabled:  false
            cert:
                file: tls/server.crt
            key:
                file: tls/server.key
            rootcert:
                file: tls/ca.crt

            # The server name use to verify the hostname returned by TLS handshake
            serverhostoverride:

        # Path on the file system where peer will store data (eg ledger). This
        # location must be access control protected to prevent unintended
        # modification that might corrupt the peer operations.
        fileSystemPath: /var/hyperledger/production

        # BCCSP (Blockchain crypto provider): Select which crypto implementation or
        # library to use
        BCCSP:
            Default: SW
            SW:
                # TODO: The default Hash and Security level needs refactoring to be
                # fully configurable. Changing these defaults requires coordination
                # SHA2 is hardcoded in several places, not only BCCSP
                Hash: SHA2
                Security: 256
                # Location of Key Store
                FileKeyStore:
                    # If "", defaults to 'mspConfigPath'/keystore
                    # TODO: Ensure this is read with fabric/core/config.GetPath() once ready
                    KeyStore:

        # Path on the file system where peer will find MSP local configurations
        mspConfigPath: msp

        # Identifier of the local MSP
        # ----!!!!IMPORTANT!!!-!!!IMPORTANT!!!-!!!IMPORTANT!!!!----
        # Deployers need to change the value of the localMspId string.
        # In particular, the name of the local MSP ID of a peer needs
        # to match the name of one of the MSPs in each of the channel
        # that this peer is a member of. Otherwise this peer's messages
        # will not be identified as valid by other nodes.
        localMspId: DEFAULT

        # Used with Go profiling tools only in none production environment. In
        # production, it should be disabled (eg enabled: false)
        profile:
            enabled:     false
            listenAddress: 0.0.0.0:6060

    ###############################################################################
    #
    #    VM section
    #
    ###############################################################################
    vm:

        # Endpoint of the vm management system.  For docker can be one of the following in general
        # unix:///var/run/docker.sock
        # http://localhost:2375
        # https://localhost:2376
        endpoint: unix:///var/run/docker.sock

        # settings for docker vms
        docker:
            tls:
                enabled: false
                ca:
                    file: docker/ca.crt
                cert:
                    file: docker/tls.crt
                key:
                    file: docker/tls.key

            # Enables/disables the standard out/err from chaincode containers for
            # debugging purposes
            attachStdout: false

            # Parameters on creating docker container.
            # Container may be efficiently created using ipam & dns-server for cluster
            # NetworkMode - sets the networking mode for the container. Supported
            # standard values are: `host`(default),`bridge`,`ipvlan`,`none`.
            # Dns - a list of DNS servers for the container to use.
            # Note:  `Privileged` `Binds` `Links` and `PortBindings` properties of
            # Docker Host Config are not supported and will not be used if set.
            # LogConfig - sets the logging driver (Type) and related options
            # (Config) for Docker. For more info,
            # https://docs.docker.com/engine/admin/logging/overview/
            # Note: Set LogConfig using Environment Variables is not supported.
            hostConfig:
                NetworkMode: host
                Dns:
                   # - 192.168.0.1
                LogConfig:
                    Type: json-file
                    Config:
                        max-size: "50m"
                        max-file: "5"
                Memory: 2147483648

    ###############################################################################
    #
    #    Chaincode section
    #
    ###############################################################################
    chaincode:
        # This is used if chaincode endpoint resolution fails with the
        # chaincodeListenAddress property
        peerAddress:

        # The id is used by the Chaincode stub to register the executing Chaincode
        # ID with the Peer and is generally supplied through ENV variables
        # the `path` form of ID is provided when installing the chaincode.
        # The `name` is used for all other requests and can be any string.
        id:
            path:
            name:

        # Generic builder environment, suitable for most chaincode types
        builder: $(DOCKER_NS)/fabric-ccenv:$(ARCH)-$(PROJECT_VERSION)

        golang:
            # golang will never need more than baseos
            runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)

        car:
            # car may need more facilities (JVM, etc) in the future as the catalog
            # of platforms are expanded.  For now, we can just use baseos
            runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)

        java:
            # This is an image based on java:openjdk-8 with addition compiler
            # tools added for java shim layer packaging.
            # This image is packed with shim layer libraries that are necessary
            # for Java chaincode runtime.
            Dockerfile:  |
                from $(DOCKER_NS)/fabric-javaenv:$(ARCH)-$(PROJECT_VERSION)

        # Timeout duration for starting up a container and waiting for Register
        # to come through. 1sec should be plenty for chaincode unit tests
        startuptimeout: 300s

        # Timeout duration for Invoke and Init calls to prevent runaway.
        # This timeout is used by all chaincodes in all the channels, including
        # system chaincodes.
        # Note that during Invoke, if the image is not available (e.g. being
        # cleaned up when in development environment), the peer will automatically
        # build the image, which might take more time. In production environment,
        # the chaincode image is unlikely to be deleted, so the timeout could be
        # reduced accordingly.
        executetimeout: 30s

        # There are 2 modes: "dev" and "net".
        # In dev mode, user runs the chaincode after starting peer from
        # command line on local machine.
        # In net mode, peer will run chaincode in a docker container.
        mode: net

        # keepalive in seconds. In situations where the communiction goes through a
        # proxy that does not support keep-alive, this parameter will maintain connection
        # between peer and chaincode.
        # A value <= 0 turns keepalive off
        keepalive: 0

        # system chaincodes whitelist. To add system chaincode "myscc" to the
        # whitelist, add "myscc: enable" to the list below, and register in
        # chaincode/importsysccs.go
        system:
            cscc: enable
            lscc: enable
            escc: enable
            vscc: enable
            qscc: enable

        # Logging section for the chaincode container
        logging:
          # Default level for all loggers within the chaincode container
          level:  info
          # Override default level for the 'shim' module
          shim:   warning
          # Format for the chaincode container logs
          format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'

    ###############################################################################
    #
    #    Ledger section - ledger configuration encompases both the blockchain
    #    and the state
    #
    ###############################################################################
    ledger:

      blockchain:

      state:
        # stateDatabase - options are "goleveldb", "CouchDB"
        # goleveldb - default state database stored in goleveldb.
        # CouchDB - store state database in CouchDB
        stateDatabase: goleveldb
        couchDBConfig:
           # It is recommended to run CouchDB on the same server as the peer, and
           # not map the CouchDB container port to a server port in docker-compose.
           # Otherwise proper security must be provided on the connection between
           # CouchDB client (on the peer) and server.
           couchDBAddress: 127.0.0.1:5984
           # This username must have read and write authority on CouchDB
           username:
           # The password is recommended to pass as an environment variable
           # during start up (eg LEDGER_COUCHDBCONFIG_PASSWORD).
           # If it is stored here, the file must be access control protected
           # to prevent unintended users from discovering the password.
           password:
           # Number of retries for CouchDB errors
           maxRetries: 3
           # Number of retries for CouchDB errors during peer startup
           maxRetriesOnStartup: 10
           # CouchDB request timeout (unit: duration, e.g. 20s)
           requestTimeout: 35s
           # Limit on the number of records to return per query
           queryLimit: 10000


      history:
        # enableHistoryDatabase - options are true or false
        # Indicates if the history of key updates should be stored.
        # All history 'index' will be stored in goleveldb, regardless if using
        # CouchDB or alternate database for the state.
    enableHistoryDatabase: true
    ```

    ### 生成配置

        上文是fabirc核心的四个文件,主要调整config文件中的相关参数即可

        下面我们通过脚本生成配置文件

    ```shell
    # 创建fabric目录
    mkdir -p /opt/fabric
    # 解压相关文件
    tar zxf /usr/local/software/hyperledger-fabric-linux-amd64-1.0.3.tar.gz -C /opt/fabric/

    tar zxf /usr/local/software/fabric.tar.gz -C /opt/

    ######### 因为要保证证书和秘钥相同,以下步骤在一台电脑上执行,然后再分发到其他机器,begin

    # 进入fabric configs目录,
    cd /opt/fabric/configs/
    # 执行generateArtifacts.sh 脚本
    ../scripts/generateArtifacts.sh
    # 这个做了以下操作
    # 1.基于crypto-config.yaml生成公私钥和证书信息,并保存在当前路径生成的crypto-config文件夹中
    # 2.生成创世区块和通道相关信息,并保存在当前生成的channel-artifacts文件夹
    # 感兴趣的小伙伴可以自己看下生成后的文档结构,这里就不再列出了

    # 将整个fabric文件分发到所有orderer和peer服务器中
    scp -r /opt/fabric root@node"X":/opt/

    ######### end #########

    # chaincode所需文件
    mkdir -p ~/go/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

    cp /usr/local/software/chaincode_example02.go ~/go/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02/
    ```

    peer启动脚本默认是peer0.org1.local的,所以这里我们要修改另外三台

    node4  peer1.org1.local

    ```shell
    sed -i 's/peer0/peer1/g' /opt/fabric/start-peer.sh
    ```

    node5  peer0.org2.local

    ```shell
    sed -i 's/org1/org2/g' /opt/fabric/start-peer.sh
    sed -i 's/Org1/Org2/g' /opt/fabric/start-peer.sh
    ```

    node6  peer1.org2.local

    ```shell
    sed -i 's/peer0/peer1/g' /opt/fabric/start-peer.sh
    sed -i 's/org1/org2/g' /opt/fabric/start-peer.sh
    sed -i 's/Org1/Org2/g' /opt/fabric/start-peer.sh
    ```

    至此,peer环境已搭建完毕,我们暂不启动peer,等orderer完成并启动后再启动peer。

    ## 安装orderer

    node1、node2

    ```shell
    # 因为文件默认是node1(orderer1)的启动脚本,这里需要对node2(orderer2)的启动脚本进行修改
    # 在node2服务器执行后面命令 sed -i 's/orderer1/orderer2/g' /opt/fabric/start-orderer.sh
    # 启动orderer
    /opt/fabric/start-orderer.sh
    # 查看日志
    tail -99f ~/orderer.log
    ```

    由于前面我们已经启动了kafka和orderer,这里再启动peer

    ```
    # 启动四台peer
    /opt/fabric/start-peer.sh
    # 查看日志
    tail -99f ~/peer.log
    ```

    ## 链上代码的安装与运行

        以上,整个Fabric网络都准备完毕,接下来我们创建Channel、安装和运行ChainCode。这个例子实现了a,b两个账户,相互之间可以转账。

    我们先在其中一个节点(peer0.org1.local)执行以下命令

    ```shell
    cd ~

    # 设置CLI的环境变量
    export FABRIC_ROOT=/opt/fabric
    export FABRIC_CFG_PATH=/opt/fabric/configs

    export CORE_LOGGING_LEVEL=DEBUG
    export CORE_LOGGING_PEER=debug
    export CORE_LOGGING_FORMAT='%{color}%{time:15:04:05.000} [%{module}] [%{longfile}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
    export CORE_CHAINCODE_LOGGING_LEVEL=DEBUG

    export CORE_PEER_ID=peer0.org1.local
    export CORE_PEER_LOCALMSPID=Org1MSP
    export CORE_PEER_MSPCONFIGPATH=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org1.local/users/Admin@org1.local/msp
    export CORE_PEER_ADDRESS=peer0.org1.local:7051

    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_TLS_ROOTCERT_FILE=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org1.local/peers/peer0.org1.local/tls/ca.crt
    export CORE_PEER_TLS_KEY_FILE=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org1.local/peers/peer0.org1.local/tls/server.key
    export CORE_PEER_TLS_CERT_FILE=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org1.local/peers/peer0.org1.local/tls/server.crt

    export ordererCa=$FABRIC_CFG_PATH/crypto-config/ordererOrganizations/orderer.local/orderers/orderer1.local/msp/tlscacerts/tlsca.orderer.local-cert.pem


    # 创建Channel
    # 系统会在当前目录创建一个mychannel.block文件,这个文件非常重要,接下来其他节点要加入这个Channel就必须使用这个文件,要将这个文件分发到其他peer当中。
    $FABRIC_ROOT/bin/peer channel create -o orderer1.local:7050 -f $FABRIC_CFG_PATH/channel-artifacts/channel.tx -c mychannel -t 30 --tls true --cafile $ordererCa

    # 加入通道
    $FABRIC_ROOT/bin/peer channel join -b mychannel.block

    # 更新锚节点,这个我还是没太理解,即使没有设置锚节点,也不会影响整个网络
    $FABRIC_ROOT/bin/peer channel update -o orderer1.local:7050 -c mychannel -f $FABRIC_CFG_PATH/channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls true --cafile $ordererCa

    # 安装 chaincode
    # 链上代码的安装需要在各个相关的Peer上进行,对于现在这种Fabric网络,如果4个Peer都想对Example02进行操作,那么就需要安装4次
    $FABRIC_ROOT/bin/peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

    # Instantiate ChainCode
    # 实例化链上代码主要是在Peer所在的机器上对前面安装好的链上代码进行包装,生成对应Channel的Docker镜像和Docker容器。并且在实例化时我们可以指定背书策略。
    $FABRIC_ROOT/bin/peer chaincode instantiate -o orderer1.local:7050 --tls true --cafile $ordererCa -C mychannel -n mycc -v 2.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR  ('Org1MSP.member','Org2MSP.member')"

    # 现在链上代码的实例也有了,并且在实例化的时候指定了a账户100,b账户200,我们可以试着调用ChainCode的查询代码,验证一下
    $FABRIC_ROOT/bin/peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

    # 返回结果:Query Result: 100

    # 把a账户的10元转给b
    $FABRIC_ROOT/bin/peer chaincode invoke -o orderer1.local:7050  --tls true --cafile $ordererCa -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'
    ```

    在另一个节点(peer0.org2.local)上查询

        前面的操作都是在org1下面做的,那么加入同一个区块链(mychannel)的org2,是否会看org1的更改呢?我们试着给peer0.org2.local加入mychannel、安装链上代码

    ```shell
    # 设置CLI的环境变量

    export FABRIC_ROOT=/opt/fabric
    export FABRIC_CFG_PATH=/opt/fabric/configs

    export CORE_LOGGING_LEVEL=DEBUG
    export CORE_LOGGING_PEER=debug
    export CORE_LOGGING_FORMAT='%{color}%{time:15:04:05.000} [%{module}] [%{longfile}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
    export CORE_CHAINCODE_LOGGING_LEVEL=DEBUG

    export CORE_PEER_ID=peer0.org2.local
    export CORE_PEER_LOCALMSPID=Org2MSP
    export CORE_PEER_MSPCONFIGPATH=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org2.local/users/Admin@org2.local/msp
    export CORE_PEER_ADDRESS=peer0.org2.local:7051

    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_TLS_ROOTCERT_FILE=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org2.local/peers/peer0.org2.local/tls/ca.crt
    export CORE_PEER_TLS_KEY_FILE=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org2.local/peers/peer0.org2.local/tls/server.key
    export CORE_PEER_TLS_CERT_FILE=$FABRIC_CFG_PATH/crypto-config/peerOrganizations/org2.local/peers/peer0.org2.local/tls/server.crt

    export ordererCa=$FABRIC_CFG_PATH/crypto-config/ordererOrganizations/orderer.local/orderers/orderer2.local/msp/tlscacerts/tlsca.orderer.local-cert.pem

    # 进入分发过来mychannel.block所在目录,执行以下命令加入通道
    $FABRIC_ROOT/bin/peer channel join -b mychannel.block

    # 安装 chaincode
    $FABRIC_ROOT/bin/peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

    # org1的时候实例化了,也就是说对应的区块已经生成了,所以在org2不能再次初始化,直接查询
    $FABRIC_ROOT/bin/peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

    # 运行该命令后要等很久才返回结果:
    Query Result: 90
    # 这是因为peer0.org2也需要生成Docker镜像,创建对应的容器,才能通过容器返回结果。我们执行docker ps -a,可以看到又多了一个容器;
    ```

    其他节点也同样如此,记得改环境变量

    ## 清除

    ```shell
    # 清理pper数据
    # 删除docker容器和镜像 
    docker rm 节点所生成的容器id(通过docker ps -a 查询)
    docker rmi 节点生成的镜像id (通过docker images 查询)

    rm -rf /var/hyperledger/*

    # 清理orderer数据
    /opt/fabric/stop-orderer.sh
    rm -rf /var/hyperledger/*

    # 清理kafka数据
    # 关闭kafka 
    kafka-server-stop.sh
    rm -rf /data/kafka-logs/*
    # 清理zookeeper数据(zookeeper 必须为启动状态):
    /usr/local/zookeeper-3.4.10/bin/./zkCli.sh

    rmr /brokers
    rmr /admin
    rmr /config
    rmr /isr_change_notification
    quit

    # 关闭zookeeper
    zookeeper-server-stop.sh
    #kafka经常会出现无法停止的现象,可通过jps查看进程,再通过kill杀掉
    rm -rf /data/zookeeper/version*
    ```

    展开全文
  • Hyperledger Fabric笔记--kafka共识的多orderer集群部署

    万次阅读 热门讨论 2018-03-09 00:10:49
    Hyperledger Fabric 1.0默认的共识是solo,即单节点共识。本文主要介绍基于kafka...orderer节点:3 peer节点:4 cli节点:1 环境准备 配置本机GOPATH 下载hyperledger/fabric到本地:$GOPATH/src/git...

    Hyperledger Fabric 1.0默认的共识是solo,即单节点共识。本文主要介绍基于kafka共识的orderer集群部署方案。

    部署方案

    • zookeeper节点:3个
    • kafka节点:4个
    • orderer节点:3个
    • peer节点:4个
    • cli节点:1个

    环境准备

    • 配置本机GOPATH
    • 下载hyperledger/fabric到本地:$GOPATH/src/github.com/hyperledger/fabric
    • 下载hyperledger/fabric-samples到本地:$GOPATH/src/github.com/hyperledger/fabric-samples
    • 打开fabric项目,在examples中创建文件夹:kafka,即$GOPATH/src/github.com/hyperledger/fabric/examples/kafka。下文相关的所有配置或脚本均在此目录下。
    • 思路:参照fabric-samples/first-network和fabric/examples/e2e_cli以及orderer相关配置文档在本机docker下模拟部署
    • 相关资源:YAML配置和脚本(默认系统最低2积分)

    生成MSP证书

    在crypto-config.yaml中配置orderer节点信息:

    OrdererOrgs:
      - Name: Orderer
        Domain: example.com
        Specs:
          - Hostname: orderer1
          - Hostname: orderer2
          - Hostname: orderer3

    使用cryptogen工具生成MSP证书:

    kafka $ cryptogen generate --config=./crypto-config.yaml
    org1.example.com
    org2.example.com

    生成创世区块

    结合crypto-config.yaml配置内容定义Orderer配置信息,具体参考如下:

    Orderer: &OrdererExample
        OrdererType: kafka
        Addresses:
            - orderer1.example.com:7050
            - orderer2.example.com:7050
            - orderer3.example.com:7050
        BatchTimeout: 2s
        BatchSize:
            MaxMessageCount: 10
            AbsoluteMaxBytes: 99 MB
            PreferredMaxBytes: 512 KB
        Kafka:
            Brokers:
                - k1:9092
                - k3:9092

    使用configtxgen工具生成创世区块:

    # 生成排序服务创世区块
    export FABRIC_CFG_PATH=$PWD
    configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
    
    # 生成通道配置创世区块
    export CHANNEL_NAME=mychannel
    configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
    

    定义组织锚节点

    configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
    configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP

    创建YAML文件

    参考fabric-samples/first-network和fabric/examples/e2e_cli项目编写自己的docker-compose.yaml。

    当前目录结构:

    kafka $ ls
    channel-artifacts   kafka-base.yaml
    configtx.yaml       orderer-base.yaml
    crypto-config       peer-base.yaml
    crypto-config.yaml  scripts
    dc-kafka.yaml

    备注:
    cp ../e2e_cli/scripts/script.sh scripts/script.sh

    启动整个网络

    docker-compose -f dc-kafka.yaml up -d

    创建并加入通道

    docker exec -it cli bash
    
    export CHANNEL_NAME=mychannel
    peer channel create -o orderer1.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx
    peer channel join -b mychannel.block

    切换环境变量,将peer1.org1.example.com加入通道

    export CORE_PEER_ADDRESS=peer1.org1.example.com:7051
    export CORE_PEER_LOCALMSPID="Org1MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin\@org1.example.com/msp
    peer channel join -b mychannel.block

    然后,参考上述操作逐步将其他节点加入该通道。

    安装和实例化链码

    在peer0.org.example.com上安装链码:

    export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
    export CORE_PEER_LOCALMSPID="Org1MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin\@org1.example.com/msp
    peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
    
    # 重新打开一个终端,确认安装是否成功
    docker exec peer0.org1.example.com ls /var/hyperledger/production/chaincodes

    然后,参考上述操作逐步在其他节点安装链码。
    安装完成后,任意选择一个peer节点实例化链码:

    peer chaincode instantiate -o orderer1.example.com:7050 -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init", "a", "100", "b", "200"]}' -P "OR('Org1MSP.member', 'Org2MSP.member')"

    链码调用或查询

    切换至任意节点的环境,然后可以执行调用或查询。

    export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
    export CORE_PEER_LOCALMSPID="Org2MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin\@org2.example.com/msp
    
    peer chaincode invoke -o orderer1.example.com:7050 -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke", "a", "b", "10"]}'
    peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

    使用脚本自动执行

    打开cli容器的command参数。注意此处的sleep 30,预留各容器的服务启动时间,否则可能运行出错。

    相关文件

    你可以参考如下文件编写及生成自己需要的配置,也可以直接下载本资源:YAML配置和脚本

    1. crypto-config.yaml

    # Copyright IBM Corp. All Rights Reserved.
    #
    # SPDX-License-Identifier: Apache-2.0
    #
    
    # ---------------------------------------------------------------------------
    # "OrdererOrgs" - Definition of organizations managing orderer nodes
    # ---------------------------------------------------------------------------
    OrdererOrgs:
      # ---------------------------------------------------------------------------
      # Orderer
      # ---------------------------------------------------------------------------
      - Name: Orderer
        Domain: example.com
        # ---------------------------------------------------------------------------
        # "Specs" - See PeerOrgs below for complete description
        # ---------------------------------------------------------------------------
        Specs:
          - Hostname: orderer1
          - Hostname: orderer2
          - Hostname: orderer3
    
    # ---------------------------------------------------------------------------
    # "PeerOrgs" - Definition of organizations managing peer nodes
    # ---------------------------------------------------------------------------
    PeerOrgs:
      # ---------------------------------------------------------------------------
      # Org1
      # ---------------------------------------------------------------------------
      - Name: Org1
        Domain: org1.example.com
        # ---------------------------------------------------------------------------
        # "Specs"
        # ---------------------------------------------------------------------------
        # Uncomment this section to enable the explicit definition of hosts in your
        # configuration.  Most users will want to use Template, below
        #
        # Specs is an array of Spec entries.  Each Spec entry consists of two fields:
        #   - Hostname:   (Required) The desired hostname, sans the domain.
        #   - CommonName: (Optional) Specifies the template or explicit override for
        #                 the CN.  By default, this is the template:
        #
        #                              "{{.Hostname}}.{{.Domain}}"
        #
        #                 which obtains its values from the Spec.Hostname and
        #                 Org.Domain, respectively.
        # ---------------------------------------------------------------------------
        # Specs:
        #   - Hostname: foo # implicitly "foo.org1.example.com"
        #     CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
        #   - Hostname: bar
        #   - Hostname: baz
        # ---------------------------------------------------------------------------
        # "Template"
        # ---------------------------------------------------------------------------
        # Allows for the definition of 1 or more hosts that are created sequentially
        # from a template. By default, this looks like "peer%d" from 0 to Count-1.
        # You may override the number of nodes (Count), the starting index (Start)
        # or the template used to construct the name (Hostname).
        #
        # Note: Template and Specs are not mutually exclusive.  You may define both
        # sections and the aggregate nodes will be created for you.  Take care with
        # name collisions
        # ---------------------------------------------------------------------------
        Template:
          Count: 2
          # Start: 5
          # Hostname: {{.Prefix}}{{.Index}} # default
        # ---------------------------------------------------------------------------
        # "Users"
        # ---------------------------------------------------------------------------
        # Count: The number of user accounts _in addition_ to Admin
        # ---------------------------------------------------------------------------
        Users:
          Count: 1
      # ---------------------------------------------------------------------------
      # Org2: See "Org1" for full specification
      # ---------------------------------------------------------------------------
      - Name: Org2
        Domain: org2.example.com
        Template:
          Count: 2
        Users:
          Count: 1

    2. configtx.yaml

    # Copyright IBM Corp. All Rights Reserved.
    #
    # SPDX-License-Identifier: Apache-2.0
    #
    
    ---
    ################################################################################
    #
    #   Profile
    #
    #   - Different configuration profiles may be encoded here to be specified
    #   as parameters to the configtxgen tool
    #
    ################################################################################
    Profiles:
    
        TwoOrgsOrdererGenesis:
            Orderer:
                <<: *OrdererExample
                Organizations:
                    - *OrdererOrg
            Consortiums:
                SampleConsortium:
                    Organizations:
                        - *Org1
                        - *Org2
        TwoOrgsChannel:
            Consortium: SampleConsortium
            Application:
                <<: *ApplicationDefaults
                Organizations:
                    - *Org1
                    - *Org2
    
    ################################################################################
    #
    #   Section: Organizations
    #
    #   - This section defines the different organizational identities which will
    #   be referenced later in the configuration.
    #
    ################################################################################
    Organizations:
    
        # SampleOrg defines an MSP using the sampleconfig.  It should never be used
        # in production but may be used as a template for other definitions
        - &OrdererOrg
            # DefaultOrg defines the organization which is used in the sampleconfig
            # of the fabric.git development environment
            Name: OrdererOrg
    
            # ID to load the MSP definition as
            ID: OrdererMSP
    
            # MSPDir is the filesystem path which contains the MSP configuration
            MSPDir: crypto-config/ordererOrganizations/example.com/msp
    
        - &Org1
            # DefaultOrg defines the organization which is used in the sampleconfig
            # of the fabric.git development environment
            Name: Org1MSP
    
            # ID to load the MSP definition as
            ID: Org1MSP
    
            MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
    
            AnchorPeers:
                # AnchorPeers defines the location of peers which can be used
                # for cross org gossip communication.  Note, this value is only
                # encoded in the genesis block in the Application section context
                - Host: peer0.org1.example.com
                  Port: 7051
    
        - &Org2
            # DefaultOrg defines the organization which is used in the sampleconfig
            # of the fabric.git development environment
            Name: Org2MSP
    
            # ID to load the MSP definition as
            ID: Org2MSP
    
            MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
    
            AnchorPeers:
                # AnchorPeers defines the location of peers which can be used
                # for cross org gossip communication.  Note, this value is only
                # encoded in the genesis block in the Application section context
                - Host: peer0.org2.example.com
                  Port: 7051
    
    ################################################################################
    #
    #   SECTION: Orderer
    #
    #   - This section defines the values to encode into a config transaction or
    #   genesis block for orderer related parameters
    #
    ################################################################################
    Orderer: &OrdererExample
    
        # Orderer Type: The orderer implementation to start
        # Available types are "solo" and "kafka"
        OrdererType: kafka
    
        Addresses:
            - orderer1.example.com:7050
            - orderer2.example.com:7050
            - orderer3.example.com:7050
    
        # Batch Timeout: The amount of time to wait before creating a batch
        BatchTimeout: 2s
    
        # Batch Size: Controls the number of messages batched into a block
        BatchSize:
    
            # Max Message Count: The maximum number of messages to permit in a batch
            MaxMessageCount: 10
    
            # Absolute Max Bytes: The absolute maximum number of bytes allowed for
            # the serialized messages in a batch.
            # 设置最大的区块大小。每个区块最大有Orderer.AbsoluteMaxBytes个字节(不包括头部)。
            # 假定这里设置的值为A,记住这个值,这会影响怎样配置Kafka代理。
            AbsoluteMaxBytes: 99 MB
    
            # Preferred Max Bytes: The preferred maximum number of bytes allowed for
            # the serialized messages in a batch. A message larger than the preferred
            # max bytes will result in a batch larger than preferred max bytes.
            # 设置每个区块建议的大小。Kafka对于相对小的消息提供更高的吞吐量;区块大小最好不要超过1MB。
            PreferredMaxBytes: 512 KB
    
        Kafka:
            # Brokers: A list of Kafka brokers to which the orderer connects
            # NOTE: Use IP:port notation
            # 包括Kafka集群中至少两个代理的地址信息(IP:port)
            # 这个List不需要是完全的(这些是你的种子代理)
            # 这个代理表示当前Orderer所要连接的Kafka代理
            Brokers:
                - k1:9092
                - k3:9092
    
        # Organizations is the list of orgs which are defined as participants on
        # the orderer side of the network
        Organizations:
    
    ################################################################################
    #
    #   SECTION: Application
    #
    #   - This section defines the values to encode into a config transaction or
    #   genesis block for application related parameters
    #
    ################################################################################
    Application: &ApplicationDefaults
    
        # Organizations is the list of orgs which are defined as participants on
        # the application side of the network
        Organizations:

    3. peer-base.yaml

    # COPYRIGHT Hello Corp. All Rights Reserved.
    #
    # Author: Haley
    # 
    
    version: '2'
    services:
      peer-base:
        image: hyperledger/fabric-peer
        environment:
          - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
          - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=kafka_default
          - CORE_LOGGING_LEVEL=DEBUG
          - CORE_PEER_TLS_ENABLED=false
          - CORE_PEER_GOSSIP_USELEADERELECTION=true
          - CORE_PEER_GOSSIP_ORGLEADER=false
          - CORE_PEER_PROFILE_ENABLED=true
          - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
          - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
          - CORE_PEER_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
        working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
        command: peer node start
    

    4. kafka-base.yaml

    # COPYRIGHT Hello Corp. All Rights Reserved.
    # 
    # Author: Haley
    #
    
    version: '2'
    
    services:
    
      zookeeper:
        image: hyperledger/fabric-zookeeper
        restart: always
        environment:
          - quorumListenOnAllIPs=true
        ports:
          - '2181'
          - '2888'
          - '3888'
    
      kafka:
        image: hyperledger/fabric-kafka
        restart: always
        environment:
          # message.max.bytes
          # The maximum size of envelope that the broker can receive.
          - KAFKA_MESSAGE_MAX_BYTES=103809024 # 99 * 1024 * 1024 B
          - KAFKA_REPLICA_FETCH_MAX_BYTES=103809024 # 99 * 1024 * 1024 B
          - KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false
          - KAFKA_LOG_RETENTION_MS=-1
        ports:
          - '9092'
    

    5. orderer-base.yaml

    # COPYRIGHT Hello Corp. All Rights Reserved.
    #
    # Author: Haley
    # 
    
    version: '2'
    
    services:
      orderer.example.com:
        image: hyperledger/fabric-orderer
        environment:
          - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=example_default
          - ORDERER_GENERAL_LOGLEVEL=error
          - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
          - ORDERER_GENERAL_LISTENPORT=7050
          - ORDERER_GENERAL_GENESISMETHOD=file
          - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
          - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
          - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
          # enabled TLS
          - ORDERER_GENERAL_TLS_ENABLED=false
          - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
          - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
          - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
          - ORDERER_KAFKA_RETRY_LONGINTERVAL=10s
          - ORDERER_KAFKA_RETRY_LONGTOTAL=100s
          - ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s
          - ORDERER_KAFKA_RETRY_SHORTTOTAL=30s
          - ORDERER_KAFKA_VERBOSE=true
          - ORDERER_KAFKA_BROKERS=[k1:9092,k2:9092,k3:9092,k4:9092]
        working_dir: /opt/gopath/src/github.com/hyperledger/fabric
        command: orderer
        volumes:
          - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
        networks:
          default:
            aliases:
              - example
        ports:
          - "7050"
    

    6. dc-kafka.yaml

    # COPYRIGHT Hello Corp. All Rights Reserved.
    #
    # Author: Haley
    #
    
    version: '2'
    
    services:
      z1:
        extends:
          file: kafka-base.yaml
          service: zookeeper
        container_name: z1
        hostname: z1
        environment:
          # ID在集合中必须是唯一的并且应该有一个值在1-255之间。
          - ZOO_MY_ID=1
          # 组成ZK集合的服务器列表。客户端使用的列表必须与ZooKeeper服务器列表所拥有的每一个ZK服务器相匹配。
          # 有两个端口号:第一个是追随者用来连接领导者的,第二个是领导人选举。
          - ZOO_SERVERS=server.1=z1:2888:3888 server.2=z2:2888:3888 server.3=z3:2888:3888
    #    volumes:
    #        - /var/run/:/host/var/run/
    
      z2:
        extends:
          file: kafka-base.yaml
          service: zookeeper
        container_name: z2
        hostname: z2
        environment:
          - ZOO_MY_ID=2
          - ZOO_SERVERS=server.1=z1:2888:3888 server.2=z2:2888:3888 server.3=z3:2888:3888
    
      z3:
        extends:
          file: kafka-base.yaml
          service: zookeeper
        container_name: z3
        hostname: z3
        environment:
          - ZOO_MY_ID=3
          - ZOO_SERVERS=server.1=z1:2888:3888 server.2=z2:2888:3888 server.3=z3:2888:3888
    
      k1:
        extends:
          file: kafka-base.yaml
          service: kafka
        container_name: k1
        hostname: k1
        environment:
          - KAFKA_BROKER_ID=1
          # min.insync.replicas=M --- 设置一个M值(例如1<M<N,查看下面的default.replication.factor)
          # 数据提交时会写入至少M个副本(这些数据然后会被同步并且归属到in-sync副本集合或ISR)。
          # 其它情况,写入操作会返回一个错误。接下来:
          # 1. 如果channel写入的数据多达N-M个副本变的不可用,操作可以正常执行。
          # 2. 如果有更多的副本不可用,Kafka不可以维护一个有M数量的ISR集合,因此Kafka停止接收写操作。Channel只有当同步M个副本后才可以重新可以写。
          - KAFKA_MIN_INSYNC_REPLICAS=2
          - KAFKA_DEFAULT_REPLICATION_FACTOR=3
          # 指向Zookeeper节点的集合,其中包含ZK的集合。
          - KAFKA_ZOOKEEPER_CONNECT=z1:2181,z2:2181,z3:2181
        depends_on:
          - z1
          - z2
          - z3
    
      k2:
        extends:
          file: kafka-base.yaml
          service: kafka
        container_name: k2
        hostname: k2
        environment:
          - KAFKA_BROKER_ID=2
          - KAFKA_MIN_INSYNC_REPLICAS=2
          - KAFKA_DEFAULT_REPLICATION_FACTOR=3
          - KAFKA_ZOOKEEPER_CONNECT=z1:2181,z2:2181,z3:2181
        depends_on:
          - z1
          - z2
          - z3
    
      k3:
        extends:
          file: kafka-base.yaml
          service: kafka
        container_name: k3
        hostname: k3
        environment:
          - KAFKA_BROKER_ID=3
          - KAFKA_MIN_INSYNC_REPLICAS=2
          - KAFKA_DEFAULT_REPLICATION_FACTOR=3
          - KAFKA_ZOOKEEPER_CONNECT=z1:2181,z2:2181,z3:2181
        depends_on:
          - z1
          - z2
          - z3
    
      k4:
        extends:
          file: kafka-base.yaml
          service: kafka
        container_name: k4
        hostname: k4
        environment:
          - KAFKA_BROKER_ID=4
          - KAFKA_MIN_INSYNC_REPLICAS=2
          - KAFKA_DEFAULT_REPLICATION_FACTOR=3
          - KAFKA_ZOOKEEPER_CONNECT=z1:2181,z2:2181,z3:2181
        depends_on:
          - z1
          - z2
          - z3
    
      orderer1.example.com:
        extends:
          file: orderer-base.yaml
          service: orderer.example.com
        container_name: orderer1.example.com
        #environment:
          #- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
          #- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
          #- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
          #- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
          #- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
        volumes:
          - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp:/var/hyperledger/orderer/msp
          - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls:/var/hyperledger/orderer/tls
        depends_on:
          - z1
          - z2
          - z3
          - k1
          - k2
          - k3
          - k4
    
      orderer2.example.com:
        extends:
          file: orderer-base.yaml
          service: orderer.example.com
        container_name: orderer2.example.com
        #environment:
          #- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
          #- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
          #- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
          #- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
          #- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
        volumes:
          - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp:/var/hyperledger/orderer/msp
          - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls:/var/hyperledger/orderer/tls
        depends_on:
          - z1
          - z2
          - z3
          - k1
          - k2
          - k3
          - k4
    
      orderer3.example.com:
        extends:
          file: orderer-base.yaml
          service: orderer.example.com
        container_name: orderer3.example.com
        #environment:
          #- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
          #- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
          #- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
          #- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
          #- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
        volumes:
          - ./crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/msp:/var/hyperledger/orderer/msp
          - ./crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls:/var/hyperledger/orderer/tls
        depends_on:
          - z1
          - z2
          - z3
          - k1
          - k2
          - k3
          - k4
    
      peer0.org1.example.com:
        extends:
          file: peer-base.yaml
          service: peer-base
        container_name: peer0.org1.example.com
        environment:
          - CORE_PEER_ID=peer0.org1.example.com
          - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
          - CORE_PEER_CHAINCODELISTENADDRESS=peer0.org1.example.com:7052
          - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
          - CORE_PEER_LOCALMSPID=Org1MSP
        volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
        ports:
          - 7051:7051
          - 7052:7052
          - 7053:7053
    
      peer1.org1.example.com:
        extends:
          file: peer-base.yaml
          service: peer-base
        container_name: peer1.org1.example.com
        environment:
          - CORE_PEER_ID=peer1.org1.example.com
          - CORE_PEER_ADDRESS=peer1.org1.example.com:7051
          - CORE_PEER_CHAINCODELISTENADDRESS=peer1.org1.example.com:7052
          - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7051
          - CORE_PEER_LOCALMSPID=Org1MSP
        volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls
        ports:
          - 8051:7051
          - 8052:7052
          - 8053:7053
    
      peer0.org2.example.com:
        extends:
          file: peer-base.yaml
          service: peer-base
        container_name: peer0.org2.example.com
        environment:
          - CORE_PEER_ID=peer0.org2.example.com
          - CORE_PEER_ADDRESS=peer0.org2.example.com:7051
          - CORE_PEER_CHAINCODELISTENADDRESS=peer0.org2.example.com:7052
          - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:7051
          - CORE_PEER_LOCALMSPID=Org2MSP
        volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls
        ports:
          - 9051:7051
          - 9052:7052
          - 9053:7053
    
      peer1.org2.example.com:
        extends:
          file: peer-base.yaml
          service: peer-base
        container_name: peer1.org2.example.com
        environment:
          - CORE_PEER_ID=peer1.org2.example.com
          - CORE_PEER_ADDRESS=peer1.org2.example.com:7051
          - CORE_PEER_CHAINCODELISTENADDRESS=peer1.org2.example.com:7052
          - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:7051
          - CORE_PEER_LOCALMSPID=Org2MSP
        volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls:/etc/hyperledger/fabric/tls
        ports:
          - 10051:7051
          - 10052:7052
          - 10053:7053
    
      cli:
        container_name: cli
        image: hyperledger/fabric-tools
        tty: true
        environment:
          - GOPATH=/opt/gopath
          - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
          - CORE_LOGGING_LEVEL=DEBUG
          - CORE_PEER_ID=cli
          - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
          - CORE_PEER_LOCALMSPID=Org1MSP
          - CORE_PEER_TLS_ENABLED=false
          - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
          - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
          - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
          - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
        working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
        #command: /bin/bash -c 'sleep 30; ./scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
        volumes:
            - /var/run/:/host/var/run/
            - ../chaincode/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode
            - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
            - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
            - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
        depends_on:
          - orderer1.example.com
          - orderer2.example.com
          - orderer3.example.com
          - peer0.org1.example.com
          - peer1.org1.example.com
          - peer0.org2.example.com
          - peer1.org2.example.com
    

    资源下载

    YAML配置和脚本

    参考

    展开全文
  • fabric基于kafka的多orderer的分布式部署脚本:3zookeeper+4kafka+3orderer+4peer+1cli,其中还包含了ca的配置:docker-compose-ca-org1.yaml和docker-compose-ca-org2.yaml,用的时候改下证书和路径就可以了。
  • 一、执行-排序-验证(Execute-Order-Validate...首先由client提出交易,发给peer仿真执行,产生读写集并签名后返回给client,client会把签名的读写集(proposal response)打包发送给ordererorderer会将所有从cli...

    一、执行-排序-验证(Execute-Order-Validate)

    Fabric采用的是先执行、后排序、最后验证的共识模型(Execute-Order-Validate),如下图所示:
    在这里插入图片描述
    首先由client提出交易,发给peer仿真执行,产生读写集并签名后返回给client,client会把签名的读写集(proposal response)打包发送给orderer,orderer会将所有从client接收的proposal response进行排序,并打包成区块,然后将区块发送给peer,最后由peer打开每个区块,并验证读写集的版本号和签名,满足条件便可将数据写入本地账本。peer还会给client发送event说明交易已经被提交到账本中了。以上就是Fabric交易的生命周期。

    二、Orderer的全排序

    Orderer的作用就是将Fabric网络中的交易进行全排序。Orderer是一个集群,将集群中每个节点接收到的所有交易进行全排序,然后通过一定的规则将交易打包成区块,如下图所示:
    在这里插入图片描述
    在Fabric中并不是所有人都可以参与排序的,由联盟里的核心企业运行orderer节点,因此只允许某几个组织参与排序工作。

    Orderer全排序需要实现了以下需求:

    2.1 产生相同的块(Produce identical blocks)

    Orderer各个节点需要通过一致性算法产生完全相同的区块,这样各个peer节点接收的区块也将是完全相同,如下图所示,各个orderer产生的区块哈希都是一致的:
    在这里插入图片描述

    2.2 崩溃容错(Crash Fault Tolerance)

    Orderer集群中某个节点停止服务后,剩下的节点依然能够完成排序功能,比如raft算法中只要超过半数的节点正常工作,就能完成正常的排序。
    在这里插入图片描述
    Orderer节点宕机后,被隔离的orderer节点可能还会继续运行,这时会产生网络分区(Network Partition),被隔离的orderer节点要能嗅探到自己被隔离了,拒绝产生新区块。
    在这里插入图片描述

    2.3 强一致性(Strong Consistency)

    公链中的“Po”系列共识算法只能达成概率上的一致性,而Fabric则需要强一致性,已被提交的交易被回滚是不能被接受的,因此也不存在临时性分叉,每个区块都是确定性的(Finality)。
    在这里插入图片描述

    2.4 拜占庭容错(Byzantine Fault Tolerance)

    拜占庭容错指的是一个节点不仅仅是停止服务,还可以作恶,提交一些恶意交易或拒绝响应别人的请求。Fabric1.4版本的Orderer本身是不支持拜占庭容错(BFT)的,仅支持崩溃容错(CFT),但是Fabric存在背书和验证的机制,整个Fabric是拜占庭容错(BFT)的,即使有一些攻击无法防范,使得无法出块,peer节点提交的交易不会写到账本里,但在Fabric里可以查看别的orderer的log,可以诊断出某个orderer在作恶,最然对网络造成了影响,但不会造成peer的数据丢失或篡改,因为没有peer的背书,交易永远不会被提交到账本中。
    在这里插入图片描述

    三、区块切割(Block Cutting)

    Orderer将交易排序后,每个Orderer节点还需要进行区块切割,只要满足BatchSize和BatchTimeout其中一个条件就将产生区块。

    3.1 BatchSize

    • MaxMessageCount 一个区块的最大交易个数
    • AbsoluteMaxBytes 限制单个交易大小
    • PreferredMaxBytes 期待的区块大小

    Orderer中一直在积累交易,当大小总额达到PreferredMaxBytes就可以出块,或者交易个数达到了MaxMessageCount同样可以出块。
    但是最后一个交易bytes可能较大,不能保证总大小一定小于PreferredMaxBytes ,这时仍然是可以将交易包含进去出块的。单个交易的大小通过AbsoluteMaxBytes进行限制,超过该限制的交易会被拒绝掉。

    3.2 BatchTimeout

    • Timeout

    区块可能一直达不到设置的大小,到了设置的“Timeout”时间后,只要有一个交易就会出块。

    展开全文
  • 纯自研的Hyperledger Fabric2.3的native部署方式(非docker)节点(3orderer2peer)源码。单机版 运行过程:请参考文件夹里面的log文件。过程覆盖了证书生成、通道建立、节点启动、链码部署、链码调用、链码升级等...
  • 架构问题:由于peer节点承担了太的功能,所以带来扩展性、可维护性、安全性、业务隔离等方面的诸多问题,所以0.6版本在推出后,并没有大规模被行业使用,只是在一些零星的案例中进行业务验证 Fabric 0.6 ...

    Fabric结构

    Fabric结构

    Fabric 0.6的特点

    1. 结构简单: 应用-成员管理-Peer的三角形关系,主要业务功能全部集中于Peer节点;
    2. 架构问题:由于peer节点承担了太多的功能,所以带来扩展性、可维护性、安全性、业务隔离等方面的诸多问题,所以0.6版本在推出后,并没有大规模被行业使用,只是在一些零星的案例中进行业务验证
    Fabric 0.6

    Fabric 1.0

    Fabric 1.0
    1. 分拆Peer的功能,将Blockchain的数据维护和共识服务进行分离,共识服务从Peer节点中完全分离出来,独立为Orderer节点提供共识服务;
    2. 基于新的架构,实现多通道(channel)的结构,实现了更为灵活的业务适应性(业务隔离、安全性等方面)
    3. 支持更强的配置功能和策略管理功能,进一步增强系统的灵活性和适应性;

    Fabric结构理解

    交易流程(数据传输流程)

    在交代Fabric各个关键之前,先理清发起一笔交易需要经历的整个数据流程是什么。

    总体流程如下图所示:

    总体流程
    生命周期中的流程
    生命周期
    完整生命周期
    完整生命周期

    流程步骤:

    1. 应用程序通过SDK发送请求到Peer节点(一个或多个) 即发起交易
      1. 客户A发起交易请求:合约设置的背书策略规定所有交易需要经过两个Peer节点的签名背书,因此请求需要被同时发往Peer A和Peer B.
      2. 客户端应用程序利用任意SDK(nodeJS,java,python)构造交易提案。该提案是一个调用智能合约功能函数的请求,用来确认哪些数据可以读取或写入账本(即更新资产的Key/Value)。
      3. SDK将交易提案打包为可识别的格式(如gRPC上的protocol buffer),并使用用户的加密凭证为该交易提案生成唯一的签名。
    2. peer节点(Committer节点)通过chaincode分别执行交易,但是并不将执行结果提交到本地的账本中 (可以认为是模拟执行,交易处于挂起状态,放置于候选池)
      1. 参与背书的peer将执行结果返回给应用程序(其中包括自身对背书结果的签名)
      2. 背书节点(使用MSP)验证签名(ProcessPropsal()->preProcess()-->Verify()验证签名)并确定提交者是否有权执行操作(使用通道的ACL)。
      3. 背书节点将交易提案的参数作为输入,在当前状态数据库上执行交易,生成包含执行返回值、读操作集合和写操作集合的交易结果(此时不会更新账本),这些值的集合、背书节点的签名和背书结果(YES / NO)作为“提案的结果”返回给SDK
      4. SDK解析这些信息判断是否应用于后续的交易。
    3. 应用程序收集背书结果并将结果提交给Ordering服务节点
      1. 应用程序(SDK)验证背书节点签名,并比较各节点返回的提案结果,判断提案结果是否一致以及是否参照指定的背书策略执行。
      2. 应用程序(SDK)将交易提案和结果以消息形式广播到排序服务(Orderers/Consenter)。交易包含读/写操作集合、背书节点的签名和通道ID。
      3. 排序服务不读取交易的详细信息,它从整个区块链网络接收交易信息,按通道分类进行排序,并为每个通道创建包含交易的区块。
    4. Ordering服务节点执行共识过程并生成block,通过消息通道发布给Peer节点(所有节点包括committer, submitter, endorser),由peer节点各自验证交易并提交到本地的ledger中(包括state状态的变化)
      1. 排序服务将区块发送到通道上的所有节点,所有交易需要被验证,确保满足背书策略
      2. 同时,需要确保全部读操作集合在交易生成之后,账本上的状态值没有改变。
      3. 经过验证,区块中的交易会被标记为有效或无效,通过Event通知客户端
    5. 所有节点账本更新
      1. 所有通道上的区块链节点将新区块加入区块链,并且对于所有有效的交易,将写操作集合提交更新到状态数据库中。
      2. 节点通过事件(Event)通知客户端交易是否已被加入区块链、以及交易是否有效。

    Fabric概念结构

    可以由下面的图大致概括:
    (Peers + Orderers + Channels)

    概念结构
    • Orderers: 即Consenter,共识插件,提供共识服务的网络节点,负责接受交易信息进行排序,以及对交易进行切割并打包,打包后返回批量交易。例如,使用Kafka或PBFT(SBFT),单节点使用solo单节点。
    • Peers: 维护账本的网络节点,通常在Hyperledger Fabric架构中存在各种角色,如endorser和committer。
    • 通道:通道是有共识服务(ordering)提供的一种通讯机制,类似于消息系统中的发布-订阅(PUB/SUB)中的topic;基于这种发布-订阅关系,将peer和orderer连接在一起,形成一个个具有保密性的通讯链路(虚拟),实现了业务隔离的要求;通道也与账本(ledger)-状态(worldstate)紧密相关; peer可以在订阅多个通道,并且只能访问订阅通道上的交易;且通道上的数据仅与peer有关,与order无关。
    • 账本:账本保存Orders提交经节点确认的交易记录。
    • 成员:访问和使用账本的网络节点。
    • 成员管理: 每个membership(MSP组织)可以有自己的fabric-ca作为第三方认证机构,与背书策略对应。成员都需要在MSP中注册
    • :基本上,一个链由1个通道+ 1个账本+ N个成员组成。非链的成员无法访问该链上的交易。链的成员可以由应用程序动态指定。

    我们这时候再看一下前面的流程图,回忆一下交易经过了哪些节点

    SDK --> Commiters --> Endorsers --> SDK --> Orderers --> Commiters&Endorsers --> SDK

    可参考下图:

    流程

    在节点Peers(Committer)提交到Endorsers时,会根据交易的需求,要求一部分背书节点进行交易所有权验证,背书签名并返回背书结果。

    下面我们了解一下背书策略

    背书策略与设计

    背书策略内容

    背书策略,用于指示区块链节点交易验证的规则。作为交易验证流程的一部分,当背书节点收到一个交易请求的时候, 该节点会调用 VSCC (验证用途的系统合约程序) 并与执行交易的合约相关联。

    为了确定交易的有效性,一个交易应该包含来自尽可能多的背书节点的一个或多个背书。VSCC用于判定下面的内容:

    • 所有背书是有效的 (即它们是来自预期消息上的有效证书的有效签名)
    • 得到一定数量的背书
    • 背书来自预期的来源(指定背书节点)

    背书策略设计

    背书策略有两个主要组成部分:

    • 主体principal
    • 阀门threshold gate

    P 标识期望背书的区块链节点,T有两个输入参数:整数t(背书数量)和n (背书节点列表),即满足t的条件,并得到n的背书
    例如:

    1. T(2, 'A', 'B', 'C') 请求来自'A'、'B'、'C'的任意2个背书节点的签名
    2. T(1, 'A', T(2, 'B', 'C')) 请求来自A或来自B和C中的一个签名

    命令行下的背书策略语法

    在Fabric CLI中,使用了一种简单的boolean表达式来解释Endorse节点的背书策略。
    Fabric 1.0使用MSP(成员管理服务)来描述主体principal,该MSP用于验证签名者的身份以及签名者在该MSP内所具有的权限

    目前支持两种角色:成员和管理员。主体Principals的通用表现形式是MSP.ROLE,其中MSP是指MSP 的ID,ROLE是 member 或admin。 一个有效主体的示例是“Org0.admin”(Org0 MSP的任意管理员)或“Org1.member”(Org1 MSP的任意成员)。

    示例:
    命令行语法是这样的:

    EXPR(E[, E...])
    

    其中EXPR可以是AND或OR,代表两个boolean表达式,E是主体或对EXPR的另一个嵌套调用。
    例如:

    AND('Org1.member', 'Org2.member', 'Org3.member') 请求三个背书节点的签名
    
    OR('Org1.member', 'Org2.member') 请求两个背书节点中的任意一个的签名
    
    OR('Org1.member', AND('Org2.member', 'Org3.member')) 
    请求来自Org1 MSP成员或来自Org2 MSP成员和来自Org3 MSP成员的任意一个签名
    

    指定智能合约的背书策略

    部署合约的开发人员可以指定背书策略来验证执行的合约。

    注,默认策略需要来自DEFAULT MSP成员的一个签名。如果未在CLI中指定策略,则默认使用此选项。
    背书策略可以在部署合约时使用"-P选项"指定,后面跟策略内容。
    例如:

    peer chaincode deploy -C testchainid -n mycc -p http://github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a","100","b","200"]}' -P "AND('Org1.member', 'Org2.member')"
    

    执行这条命令将在testchainid这条链上使用背书策略AND(‘Org1.member’, ‘Org2.member’).部署智能合约mycc

    Orderers共识(Consenter)

    共识机制

    Fabric 0.6采用的是PBFT共识机制,但已经暂时取消该机制改为了Kafka共识。原因如下:

    • 交易性能达不到要求
    • Fabric 面向的联盟链环境中,因为节点都是有准入控制的,拜赞庭容错的需求不是很强烈,反而是并发性能最重要

    在测试开发中较多使用SOLO共识机制

    SOLO机制是一个非常容易部署的非生产环境的共识排序节点。由一个为所有客户服务的单一节点组成,所以不需要“共识”,因为有一个中央权威机构。相应地没有高可用性或可扩展性。这使得独立开发和测试很理想,但不适合生产环境部署。order-solo模式作为单节点通信模式,所有从peer收到的消息都在本节点进行排序与生成数据块

    在Fabric 1.0往后版本中,采用的是Kafka共识机制,将来或采用SBFT(简化拜占庭容错共识)。

    基于 Kafka 实现的共识

    Kafka共识

    一个共识集群由多个 orderer 节点(OSN)和一个 kafka 集群组成。orderer 之间并不直接通信,他们仅仅和 Kafka 集群通信。

    在 orderer 的实现里,通道(Channel)在 kafka 中是以 主题topic 的形式隔离。
    每个 orderer 内部,针对每个通道都会建立与 kafka 集群对应 topic 的生产者及消费者。生产者将 orderer 节点收到的交易发送到 kafka 集群进行排序,在生产的同时,消费者也同步消费排序后的交易。

    如何鉴别某个交易属于哪个区块

    Fabric 的区块结块由两个条件决定,区块交易量区块时间间隔

    • 当配置的交易量达到阈值时,无论是否达到时间间隔,都会触发结块操作;
    • 另一方面,如果触发了设置的时间间隔阈值,只要有交易就会触发结块操作,也就是说 fabric 中不会有空块。
    • 结块操作是由 orderer 节点中的 kafka 生产者发送一条 TTC-X(Time to cut block x)消息到 kafka 集群,
    • 当任意 orderer 节点的 kafka 消费者接收到任意节点发出的 TTC-X 消息时,都会将之前收到的交易打包结块,保存在 orderer 本地,之后再分发到各 peer 节点。

    个人理解:OSN内部有每个通道对应topic的kafka生产者、kafka消费者,OSN里的生产者同时发送交易到集群,OSN同时消费来自集群的交易,共识的交易达到交易量或达到时间间隔后,OSN的kafka生产者会发送TTC-X到集群,OSN的kafka消费者收到后会将之前收到的交易结块,保存在OSN本地,然后分发到peers节点

    以上过程可由下图描述:

    共识过程

    Kafka共识集群结构

    Kafka简介

    注,Orderers(OSN)与Consenter(一致性)不一样,Consenter在kafka集群里,是真正实现共识的共识插件,而OSN是与集群cluster通信获得共识结果的节点

    Kafka是一种分布式的,基于发布/订阅的消息系统。主要设计目标如下:

    • 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能
    • 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输
    • 支持Kafka Server间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输
    • 同时支持离线数据处理和实时数据处理
    Kafka架构
    Kafka架构

    Kafka架构Partition

    一个典型的kafka集群中包含若干producer,若干broker,若干consumer group,以及一个Zookeeper集群。

    • Kafka通过Zookeeper管理集群配置,选举leader,以及在consumer group发生变化时进行rebalance
    • producer使用push模式将消息发布到broker
    • consumer使用pull模式从broker订阅并消费消息。

    各个角色的功能分别是:

    1. Brokers(经纪人)
      代理是负责维护发布数据的简单系统。
      • 每个代理可以每个主题具有零个或多个分区。
      • push模式的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,而pull模式下Broker则可以根据consumer的消费能力以适当的速率消费消息。
      • 假设,如果在一个主题和N个代理中有N个分区,每个代理将有一个分区。
    2. Producers(生产者)
      生产者是发送给一个或多个Kafka主题的消息的发布者。
      • 生产者向Kafka经纪人发送数据。
      • 每当生产者将消息发布给代理时,代理只需将消息附加到最后一个段文件。实际上,该消息将被附加到分区。
      • 生产者还可以向他们选择的分区发送消息。
    3. Consumers(消费者)
      Consumers从经纪人处读取数据。 消费者订阅一个或多个主题,并通过从代理中提取数据来使用已发布的消息。
      • Consumer自己维护消费到哪个offet,线性增加
      • 每个Consumer都有对应的group
      • group内是queue消费模型:各个Consumer消费不同的partition,因此一个消息在group内只消费一次
      • group间是publish-subscribe消费模型:各个group各自独立消费,互不影响,因此一个消息被每个group消费一次
    4. Topics(主题)
      属于特定类别的消息流称为主题。
      • 数据存储在主题中。Topic相当于Queue。
      • 主题被拆分成分区。
      • 每个这样的分区包含不可变有序序列的消息。
      • 分区被实现为具有相等大小的一组分段文件。
    5. Partition(分区)
      一个Topic可以分成多个Partition,这是为了平行化处理。
      • 每个Partition内部消息有序,其中每个消息都有一个offset序号
      • 一个Partition只对应一个Broker,一个Broker可以管理多个Partition
      • 因为每条消息都被append到该partition中,是顺序写磁盘。因此效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是Kafka高吞吐率的一个很重要的保证)
    6. Replicas of partition(分区备份)
      • 副本只是一个分区的备份。 副本从不读取或写入数据。 它们用于防止数据丢失。
      • 对于传统的message queue而言,一般会删除已经被消费的消息,而Kafka集群会保留所有的消息,无论其被消费与否。
      • 当然,因为磁盘限制,不可能永久保留所有数据(实际上也没必要),因此Kafka提供两种策略去删除旧数据。一是基于时间,二是基于partition文件大小。

    Ledger账本结构

    账本结构

    Peer节点负责维护区块链的账本(ledger)和状态(State),本地的账本称为PeerLedger。
    整个区块结构分为文件系统存储的Block结构和数据库维护的State状态,其中state的存储结构是可以替换的,可选的实现包括各种KV数据库(LEVELDB,CouchDB等)

    账本简单的说,是一系列有序的、不可篡改的状态转移记录日志

    • 状态转移是链码(chaincode)执行(交易)的结果,每个交易都是通过增删改操作提交一系列键值对到账本。一系列有序的交易被打包成块,这样就将账本串联成了区块链。
    • 同时,一个状态数据库维护账本当前的状态,因此也被叫做世界状态。

    在 1.0 版本的 Fabric 中,每个通道都有其账本,每个 peer 节点都保存着其加入的通道的账本,包含着交易日志(账本数据库)、状态数据库以及历史数据库。

    账本状态数据库实际上存储的是所有曾经在交易中出现的键值对的最新值

    • 调用链码执行交易可以改变状态数据,为了高效的执行链码调用,所有数据的最新值都被存放在状态数据库中。
    • 就逻辑上来说,状态数据库仅仅是有序交易日志的快照,因此在任何时候都可以根据交易日志重新生成。
    • 状态数据库会在peer节点启动的时候自动恢复或重构,未完备前,该节点不会接受新的交易。
    • 状态数据库可以使用 LevelDB 或者 CouchDB。
      • 跟 LevelDB 一样,CouchDB 也能够存储任意的二进制数据,
      • CouchDB 额外的支撑 JSON 富文本查询,如果链码的键值对存储的是 JSON,那么可以很好的利用 CouchDB 的富文本查询功能。

    Fabric 的账本结构中还有一个可选的历史状态数据库,用于查询某个 key 的历史修改记录,需要注意的是,历史数据库并不存储 key 具体的值,而只记录在某个区块的某个交易里,某 key 变动了一次。后续需要查询的时候,根据变动历史去查询实际变动的值。

    账本数据库是基于文件系统,将区块存储于文件块中,然后在 LevelDB 中存储区块交易对应的文件块及其偏移,也就是将 LevelDB 作为账本数据库的索引。
    现阶段支持的索引有:

    • 区块编号
    • 区块哈希
    • 交易 ID 索引交易
    • 区块交易编号
    • 交易 ID 索引区块
    • 交易 ID 索引交易验证码

    Chaincode链码系统

    前面我们提到,状态转移是链码(chaincode)执行(交易)的结果。实际上,链码(chaincode)是 Hyperledger Fabric 提供的智能合约,是上层应用与底层区块链平台交互的媒介。即,合约与交易都与链码相关。

    CSCC配置系统

    介绍一个新的系统chaincode,叫做配置系统chaincode(CSCC),主要负责处理所有的配置相关的事务。CSCC提供方法查询众多的配置数据,包括通道配置。

    链码的通道配置

    引导

    共识服务由1个或多个Orderers组成。 每个Orderer配置有匹配的创世区块,其由引导CLI命令生成,其提供了一些必要的数据,包括一系列可信根节点的列表,Order证书和IP地址的列表,一组特定的共识算法配置以及访问控制策略(谁可以创建信道)。

    要启动并连接到共识服务,peer至少需要以下配置:

    1. 准入网络的注册证书。 证书可以来自任意CA,只要CA是peer将连接到的共识服务的可信任根的一部分
    2. 来自共识服务管理CLI生成的Orderer证书和IP地址的列表
    3. 可信任根节点列表
    4. peer可以订阅的通道可选列表。 除非明确配置,否则peer在启动时不订阅任何通道

    注意,#2和#3来自引导的创世区块,我们可以从引导CLI命令获得。
    通过CLI或使用SDK API的应用程序,peer可以订阅已经存在的通道。 orderer通过在通道创建或重新配置期间收到的消息决定谁可以加入通道。

    例如,假设peer A和B属于2个不同成员Alice和Bob。 请注意,Alice和Bob可能在网络上有多个Peer,并且他们的任何Peer都可以加入通道。 以下是一个典型的序列:

    创建通道
    1. 应用程序/ SDK获得A和B的背书用于创建通道“foo”的配置交易。
    2. 应用程序/ SDK调用Broadcast RPC,将背书过的配置交易传递给order服务。
    3. 应用程序/ SDK然后调用在通道foo上deliver RPC。此RPC将返回一个错误,直到order服务成功创建通道。
    4. 当通道最终被创建后,Deliver RPC将返回通道的信息到应用程序/ SDK。在这一时点,通道foo应当仅具有包含相关订阅者的创世区块,并且与该配置交易一起被(或最近的重新配置交易)引导。
    5. 应用程序/ SDK在A和B上调用JoinChannel API,将通道foo的创世区块传递给A和B,添加CSCC到通道上。
    6. A和B上的CSCC检查创世区块,包括检查区块中的配置交易的背书。如果一切正确,他们调用在通道上的Deliver RPC来开始接收块。
      如果通道已经存在,则参与者列表将被替换。Orderers自动替换订阅者并且将该交易与该通道上的其他交易一起发送给新成员,新成员将会同步完整的块。
    关闭通道

    应用程序可以通过发送类似于创建通道的配置交易来关闭其创建的通道。 它需要根据应用程序设置的策略从通道参与方得到背书。

    peer不会自动销毁相关的账本,但是裁剪进程会在适当的时候处理。
    应用程序可以继续从已关闭的账本中读取数据,只要该账本尚未被删除,但由于通道已被销毁,因此不能执行交易了。

    查询通道

    通道只能被该通道的成员查询。也就是说,交易发起方的签名能够被存储在账本配置区块中的CA证书验证通过。这是通过发起一个查询交易到CSCC,同时附上链的ID,返回的结果是一个配置区块,里面包含了成员证书和一些其他的配置信息。

    链上的交易

    一个交易必须包含目标的链ID(链ID =通道ID =账本ID)。
    共识服务将把交易放置在由链ID标识的指定通道上,并且在该通道内被排序,而与其它通道上的交易无关。 最终在该通道上产生一个包含交易的区块并发送到订阅了该通道的那些peer。

    注意,每个链都是独立和并行的,因此一个peer可以同时接收和处理不同链上的区块。
    chaincode事务只能操作指定链中的状态变量

    chaincode限制
    1. 从交易调用chaincode总是在交易被发送的链上进行操作
    2. 只有系统链上的chaincode可以被私有链上的其他chaincode调用并且是只读的
    API 配置交易(通道与节点绑定)
    1. 在peer上增加一个新的gRPC API和一个新的顶层交易类型。API允许App / SDK通知peer已成功加入的通道。
      加入通道API的输入是由新创建的通道上的共识服务返回的创世区块,peer使用此区块设置与通道关联的账本。
    2. 新的交易类型称为配置交易,这种类型的交易可以由Orderer和peer处理。 创建或重新配置通道的交易都属于配置交易,其中背书请求是让peer批准和不批准它们创建或重新配置通道。 peer可以通过提案请求返回接受或拒绝。 为了保持灵活性,我们将提供一个系统chaincode来处理通道创建的背书请求,它将自动响应签名请求。
    3. chaincode还提供查询此通道上参与成员列表的功能。
    4. 新配置交易必须包含所有先前的配置条目,并且所有新/修改的配置条目必须用其包含配置包络的序列号和链ID标记。每个配置条目都具有枚举类型,唯一(按类型划分)ID以及由名称引用的修改策略。Order服务将根据现有配置策略验证配置交易,如果不满足全部修改策略,则拒绝它。
    5. SDK可以向API提供进一步的抽象。 例如,它可以提供1个API,创建通道(成员证书列表),它将执行在创建通道部分中讨论的所有6个步骤。
    6. 最后,SDK将调用应用程序上的回调,返回创建通道的状态。

    链码的合约作用

    链码(chaincode)是 Hyperledger Fabric 提供的智能合约,是上层应用与底层区块链平台交互的媒介。现阶段,Fabric 提供 Go、Java 等语言编写的链码

    所有的链码都实现两个接口,init 和 invoke。

    • init 接口用于初始化合约,在整个链码的生命周期里,该接口仅仅执行一次。
    • invoke 接口是编写业务逻辑的唯一入口,虽然只有一个入口,但是可以根据参数传递的不同自由区分不同业务逻辑,灵活性很高。比如应用开发者规定 Invoke 接口的第一个参数是合约方法名,剩余的 Invoke 参数列表是传递给该方法的参数,那么就可以在 Invoke 接口方法体中根据方法名的不同分流不同业务了。
    合约里能够获取的内容
    • 输入参数获取。这点很好理解,我们只有知道此次调用的输入,才能处理逻辑,推导输出;
    • 与状态数据库和历史数据库交互。在合约层,我们可以将区块链底层当做是一个键值对数据库,合约就是对数据库中键值的增删改查;
    • 与其他合约的交互。在合约执行的过程中,可以与其他合约交换数据,做到类似跨链的效果。有了这种形式的数据获取方式,其实就可以将联系不紧密的业务逻辑拆分为多个合约,只在必要的时候跨合约调用,非常类似于现在提倡的微服务架构。

    编写链码还有一个非常重要的原则:不要出现任何本地化和随机逻辑。此处的本地化,不是指语言本地化,而是执行环境本地化。区块链因为是去中心架构,业务逻辑不是只在某一个节点执行,而是在所有的共识节点都执行,如果链码输出与本地化数据相关,那么可能会导致结果差异,从而不能达成共识。

    链码部署

    Peers是独立实体,通道就是业务载体,链码就是业务;不同的通道即便是运行相同的链码,因为载体不同,可认为是两个不同业务。

    1. 创建业务载体通道;
    2. 将通道与 peer 节点绑定;
    3. 在通道上实例化链码。
    通道的管理

    通道只有创建,而没有删除功能。但是在使用 kafka 共识的过程中,如果数据操作不当,直接在 kafka 中删除数据,而 orderer 没有逻辑去处理这种异常删除,因此会不断的重试,在达到重试极限后直接崩溃整个进程

    没有完善的数据管理方案

    在我们的使用场景中,数据增长是很快的,如果使用 CouchDB 作为底层数据引擎,数据更是几何倍数的爆发。现有的解决方案只能是在云上部署节点,提供可持续扩充的云硬盘,再者使用 LevelDB 替换掉 CouchDB,避免使用模糊查询。

    Event事件流

    事件框架支持发出2种类型的event(事件)

    • Block event
    • 自定义/chaincode event(在events.proto中定义的ChaincodeEvent类型)
    基本思想

    client(event consumers\事件消费者)将注册event类型(block或chaincode)。在chaincode的情况下,它们可以指定附加的注册标准,即chaincodeID和eventname。

    • ChaincodeID标识client想要查看event的特定Chaincode。
    • eventname是Chaincode开发人员,在调用Chaincode中的SetEvent API时嵌入的字符串。

    调用transaction是当前唯一可以发出event的操作,并且每个调用,在每个transaction中只能发出一个event。

    一般Event类型与ChaincodeEvent的关系

    Event与event类型相关联。 客户注册他们想要接收event的event类型。
    event类型的生命周期由“block”event来说明

    1. 在启动peer时,在支持的event类型中添加“block”
    2. client可以与peer(或多个peers)一起注册感兴趣的“block” event类型
    3. 创建Block的Peers,向所有注册client发布event
    4. 客户收到“block” event并处理Block中的事务

    Chaincode event添加了额外的注册过滤级别。 Chaincode event不是注册给定event类型的所有event,而是允许client从特定Chaincode注册特定event。 对于目前的第一个版本,为了简单起见,没有在eventname上实现通配符或正则表达式匹配,但后续会提供该功能

    Fabric通信方式

    节点通信、client与节点Api通信:使用http/2下的gRPC

    • http: 基于TCP/IP协议,需要三次握手
    • rpc:远程进程调用,需要统一的序列化,不适用于频繁连接
    • gRPC: 使用HTTP/2协议并用ProtoBuf作为序列化工具
    与REST比较
    • 和REST一样遵循HTTP协议(明确的说是HTTP/2),但是gRPC提供了全双工流
    • 和传统的REST不同的是gRPC使用了静态路径,从而提高性能
    • 用一些格式化的错误码代替了HTTP的状态码更好的标示错误
    gRPC
    1. xxx.proto, 定义rpc,输入参数与返回参数的数据命名结构
    2. 命令行中protoc编译生成对应的xxx.pb.go源码,编写clientAPI for EventService供客户端使用的接口定义、接口实例、接口实例的初始化函数,和server API for EventService供服务端使用的接口定义,注册函数。
    HTTP/2特点
    1. 将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码。在HTTP/2中,数据流以消息的形式发送,而消息由一个或多个帧组成,帧可以在数据流上乱序发送,然后再根据每个帧首部的流标识符重新组装。二进制分帧是HTTP/2的基石,其他优化都是在这一基础上来实现的。我们先了解几个概念:

      • 帧(Frame):HTTP/2通信的最小单位,每个帧包含帧首部,至少也会标识出当前帧所属的流。
      • 消息(Message):由一个或多个帧组合而成,例如请求和响应。
      • 连接(Connection):与 HTTP/1 相同,都是指对应的 TCP 连接;
      • 流(Stream):已建立的连接上的双向字节流。
    2. 支持请求与响应的多路复用来减少延迟

      • 同域名下所有通信都在单个连接上完成。
      • 单个连接可以承载任意数量的双向数据流。
      • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

      这一特性,性能会有极大的提升,因为:

      • 同个域名只需要占用一个TCP连接,消除了因多个TCP连接而带来的延时和内存消耗。
      • 单个连接上可以并行交错的请求和响应,之间互不干扰。
    3. 压缩HTTP首部字段将协议开销降至最低

      • HTTP/2在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;
      • 首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
      • 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值。
    4. 对请求划分优先级

    5. 支持服务端Push消息到客户端

    ProtoBuf:

    1. 一套用于数据存储,网络通信时用于协议编解码的工具库.它和XML和Json数据差不多,把数据已某种形式保存起来.Protobuf相对与XML和Json的不同之处,它是一种二进制的数据格式,具有更高的传输,打包和解包效率.
    2. 如果使用protobuf实现,首先要写一个proto文件(不妨叫Order.proto),在该文件中添加一个名为"Order"的message结构,用来描述通讯协议中的结构化数据。使用protobuf内置的编译器编译 该proto。

    参考资料:

    Hyperledger文档:(详细研读)
    https://hyperledger-fabric.readthedocs.io/en/latest/whatis.html

    Hyperledger github文档
    https://github.com/hyperledger/fabric/tree/release-1.1/docs/source

    常用的Q&A
    https://hyperledger-fabric.readthedocs.io/en/latest/Fabric-FAQ.html?highlight=consenter

    知乎专栏翻译:
    https://zhuanlan.zhihu.com/p/23356616

    专栏-fabric生命周期
    https://zhuanlan.zhihu.com/p/25119939

    hyperledger-MSP event等侧面分析 图解
    https://blog.csdn.net/maixia24/article/category/7507736

    文章出处:https://www.jianshu.com/p/1d472586a3d5?from=timeline&isappinstalled=0
    展开全文
  • orderer集群机部署

    千次阅读 2018-05-17 19:36:19
    orderer节点的部署方式有两种:solo和kafka。单机很简单,这次重点记录kafka(分布式队列)的部署方式 首先规划好机器节点容器配置。 orderer: 3台 zookeeper: 3、5、7,此处简单设置,我们启动3台 kafka: 4...
  • 1.排序节点介绍 本节内容基于前几节介绍的hellowrold区块链环境...在创建区块链创世块以及通道的时候我们会用到一configtx.yaml文件,该配置文件中的Orderer配置信息中有一OrdererType参数, 该参数可配置为"so...
  • 配置 ...org1的peer0和peer1节点,orderer节点,三kafka和三zookeeper节点 前言 其实搭建的过程很简单,主要的时间都是耗费在了kafka的搭建上。因为机器资源不够,所以kafka都是搭建在同一...
  • fabric动态新增orderer

    2021-04-16 10:36:34
    关于raft模式下的orderer新增,官网给了大概流程 重新配置 Raft 排序节点支持动态地(意思是,当通道正在使用时)添加和移除节点,只是一次只能添加或移除一节点。在你尝试重新配置之前,请注意你的集群必须处于...
  • 原文地址: 超级账本HyperLedger的Fabric-CA的使用演示(两个组织一个Orderer三个Peer) 说明 启动fabric-ca 生成fabric-ca admin的凭证 创建联盟 为每个组织准备msp 注册example.com的管理员Admin@example.com...
  • 1.环境准备我们要部署4Peer+1Orderer架构,也是官方文档e2e_cli架构,那么就先准备5台虚拟机,保证五台网络畅通。分别在每一台服务器上安装以下环境,我这里是安装了一台然后克隆出来的另外4台虚拟机。下面以172.168...
  • Orderer在Fabric网络中的作用主要是原子广播(Atomic Broadcast)和全排序(Total Order )。 - orderer通过`broadcast`接口,接受client发送的交易,然后将这些Tx进行排序;排序的的原则为FIFS(First In First ...
  • 在阿里云服务器上部署solo机节点时遇到了一这样的问题: 在部署orderer节点时,编写好了docker-orderer.yaml文件之后上传到orderer服务器上,输入docker-compose -f docker-orderer.yaml up -d指令启动orderer...
  • 1.在crypto-config.yaml文件的 OrdererOrgs:  # ---------------------------------------------------------------------... # Orderer  # -----------------------------------------------------------------...
  • fabric动态增加orderer节点(raft) - 简书
  • IBM第五讲 Orderer解析 OUTLINE: Atomic Broadcast(Total Order) Channels Solo/Kafka/Raft Permission in Orderer Atomic Broadcast(Total Order): Execute-Order-Validate共识模型 交易过程: Client向Peer发送...
  • Fabric docker compose文件-orderer

    千次阅读 2018-06-11 09:08:54
    前提cryptogen生成的文件放置在./crypto-config内。... compose配置文件:docker-compose-ordererY.yaml|-base/orderer-base.yamlorderer-baseversion: '2'services:orderer-base:#orderer的镜像im...
  • 自定义机架构部署,包括1个orderer服务器+一个peer节点服务器,配置文件直接拷贝至不同服务器中,docker-compse运行即可。
  • Fabric源码流程分析之Orderer

    千次阅读 2019-08-02 16:32:13
    Fabric源码流程分析之Ordererorderer模块源码开始阅读目录:hyperledger\fabric\orderer\common\server\main.go一.首先通过kingpin技术(命令行解析工具)接收命令行命令,如果是 “version”则直接打印当前...
  •  HyperLedger Fabric作为一架构灵活的企业级区块链平台,正在被越来越的企业用于生产环境。上次我分享过一篇文章《HyperLedger Fabric在携程区块链服务平台的应用实战》介绍了一些我们对于HyperLedger Fabric的...
  • # Fabric 1.0源代码笔记 之 Orderer #localconfig(Orderer配置文件定义)## 1、配置文件定义```bashGeneral: #通用配置 LedgerType: file #账本类型,包括ram、json和file,其中ram保存在内存中,生产环境推荐使用...
  • 机器部署一样,官文对源码调试的描述较少,网上有些前辈已经写过但少有明确每一步的原因,本系列文尝试依据个人理解来描述构建fabric源码调试环境的步骤,去掉docker这层障碍,并给出思考过程。 ​ 之前有写过...
  • btlPullMargin: 10 events: address: 0.0.0.0:7053 # 指定事件服务的地址 buffersize: 100 # 可以在不阻塞发送的情况下缓冲的事件总数 # 将事件添加到一完整的缓冲区时要阻塞长时间 # 如果小于0,直接丢弃 # ...
  • 文章目录网络拓扑宏观视角单通道区块同步为何Peer从Orderer获取区块慢?为何不让Peer缓存所有未处理的区块? Peer与Orderer的交互主要是组织的Peer主节点从Orderer获取区块,本文就来介绍,Peer是如...
  • Orderer节点的启动命令是orderer start,用于启动主程序的main()函数。
  • Fabric-02Peer、Orderer以及CA

    千次阅读 2021-07-11 13:35:02
    五、Peer 5.1Fabric Peer ...每个channel维护自己的一个或多个账本,账本之间是隔离的; 每个peer可以安装不同的智能合约; 交易完成后,peer会发送event事件给client端; 每个channel都有local MSP,提
  • Kafka集群维护多个topic分区。Kafka通过共识算法来确保写入到分区后的消息的一致性。即一旦写入分区,任何Orderer节点看到的都是相同的消息队列; Orderer节点在启动后,默认对本地账本对应的Kafka分区数据进行监听...
  • 【3】peer1.1等节点,接入了多个通道,说明一个peer节点也可以参与到多个channel中。每个Channel之间是相互隔离,且是并行运行的。这一特性大大提高了系统的吞吐量。 从上图可以知道: 【1】一个链由1个通道+ 1个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,452
精华内容 980
关键字:

多个orderer