HLF 网络因未知原因关闭导致网关失败

HLF network closed for unknown reason causes Gateway to fail

这是我看到的异常:

Exception in thread "main" org.hyperledger.fabric.gateway.GatewayRuntimeException: org.hyperledger.fabric.sdk.exception.ProposalException: org.hyperledger.fabric.sdk.exception.TransactionException: org.hyperledger.fabric.sdk.exception.ProposalException: getConfigBlock for channel isprintchannel failed with peer peer1.org1.isprint.com.  Status FAILURE, details: Channel Channel{id: 1, name: isprintchannel} Sending proposal with transaction: 31101a32ee94cdb3ec65abaca86f0cf828d6b48cd4453257cd7270f94d192b93 to Peer{ id: 2, name: peer1.org1.isprint.com, channelName: isprintchannel, url: grpc://127.0.0.1:7051, mspid: Org1MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=Network closed for unknown reason, cause=null}
    at org.hyperledger.fabric.gateway.impl.TransactionImpl.submit(TransactionImpl.java:121)
    at org.hyperledger.fabric.gateway.impl.ContractImpl.submitTransaction(ContractImpl.java:50)
    at com.isprint.axr.ext.hyperledger.isprint_fabric.isprint_chaincode.ChaincodeEventTester.main(ChaincodeEventTester.java:39)
Caused by: org.hyperledger.fabric.sdk.exception.ProposalException: org.hyperledger.fabric.sdk.exception.TransactionException: org.hyperledger.fabric.sdk.exception.ProposalException: getConfigBlock for channel isprintchannel failed with peer peer1.org1.isprint.com.  Status FAILURE, details: Channel Channel{id: 1, name: isprintchannel} Sending proposal with transaction: 31101a32ee94cdb3ec65abaca86f0cf828d6b48cd4453257cd7270f94d192b93 to Peer{ id: 2, name: peer1.org1.isprint.com, channelName: isprintchannel, url: grpc://127.0.0.1:7051, mspid: Org1MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=Network closed for unknown reason, cause=null}
    at org.hyperledger.fabric.sdk.Channel.sendProposalToPeers(Channel.java:4387)
    at org.hyperledger.fabric.sdk.Channel.sendProposal(Channel.java:4358)
    at org.hyperledger.fabric.sdk.Channel.sendTransactionProposal(Channel.java:3908)
    at org.hyperledger.fabric.gateway.impl.TransactionImpl.sendTransactionProposal(TransactionImpl.java:161)
    at org.hyperledger.fabric.gateway.impl.TransactionImpl.submit(TransactionImpl.java:94)
    ... 2 more
Caused by: org.hyperledger.fabric.sdk.exception.TransactionException: org.hyperledger.fabric.sdk.exception.ProposalException: getConfigBlock for channel isprintchannel failed with peer peer1.org1.isprint.com.  Status FAILURE, details: Channel Channel{id: 1, name: isprintchannel} Sending proposal with transaction: 31101a32ee94cdb3ec65abaca86f0cf828d6b48cd4453257cd7270f94d192b93 to Peer{ id: 2, name: peer1.org1.isprint.com, channelName: isprintchannel, url: grpc://127.0.0.1:7051, mspid: Org1MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=Network closed for unknown reason, cause=null}
    at org.hyperledger.fabric.sdk.Channel.parseConfigBlock(Channel.java:2023)
    at org.hyperledger.fabric.sdk.Channel.loadCACertificates(Channel.java:1843)
    at org.hyperledger.fabric.sdk.Channel.sendProposalToPeers(Channel.java:4385)
    ... 6 more
Caused by: org.hyperledger.fabric.sdk.exception.ProposalException: getConfigBlock for channel isprintchannel failed with peer peer1.org1.isprint.com.  Status FAILURE, details: Channel Channel{id: 1, name: isprintchannel} Sending proposal with transaction: 31101a32ee94cdb3ec65abaca86f0cf828d6b48cd4453257cd7270f94d192b93 to Peer{ id: 2, name: peer1.org1.isprint.com, channelName: isprintchannel, url: grpc://127.0.0.1:7051, mspid: Org1MSP} failed because of: gRPC failure=Status{code=UNAVAILABLE, description=Network closed for unknown reason, cause=null}
    at org.hyperledger.fabric.sdk.Channel.getConfigBlock(Channel.java:962)
    at org.hyperledger.fabric.sdk.Channel.getConfigBlock(Channel.java:917)
    at org.hyperledger.fabric.sdk.Channel.parseConfigBlock(Channel.java:2006)
    ... 8 more

这是我的网关代码(与样板代码几乎没有变化):

public class Tester {

    public static void main(String[] args) throws IOException {

        // Load an existing wallet holding identities used to access the network.
        Path wdir = Paths.get("wallet");
        Wallet wallet = Wallet.createFileSystemWallet(wdir);

        // Path to a common connection profile describing the network.
        Path cfg = Paths.get("config","local","connection.json");

        // Configure the gateway connection used to access the network.
        Gateway.Builder builder = Gateway.createBuilder().identity(wallet, "myteareserve_app").networkConfig(cfg);

        // Create a gateway connection
        try (Gateway gateway = builder.connect()) {

            Network network = gateway.getNetwork("isprintchannel");
            Contract contract = network.getContract("myteacc");

            // this next line throws the above exception
            byte[] createProductResult = contract.submitTransaction("createProduct", "tea001", "red");
            System.out.println(new String(createProductResult, StandardCharsets.UTF_8));

        } catch (ContractException | TimeoutException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

connection.json定义如下:

{
    "name": "myteareserve",
    "x-type": "hlfv1",
    "x-commitTimeout": 1000,
    "version": "1.0.0",
    "client": {
        "organization": "Org1",
        "connection": {
            "timeout": {
                "peer": {
                    "endorser": "1000",
                    "eventHub": "1000",
                    "eventReg": "1000"
                },
                "orderer": "1000"
            }
        }
    },
    "channels": {
        "myteachannel": {
            "orderers": [
                "orderer1.isprint.com",
                "orderer2.isprint.com",
                "orderer3.isprint.com"
            ],
            "peers": {
                "peer1.org1.isprint.com": {
                    "endorsingPeer": true,
                    "chaincodeQuery": true,
                    "ledgerQuery": true,
                    "eventSource": true
                },
                "peer2.org1.isprint.com": {
                    "endorsingPeer": true,
                    "chaincodeQuery": true,
                    "ledgerQuery": true,
                    "eventSource": true
                }
            }
        }
    },
    "organizations": {
        "Org1": {
            "mspid": "Org1MSP",
            "peers": [
                "peer1.org1.isprint.com",
                "peer2.org1.isprint.com"
            ],
            "certificateAuthorities": [
                "ca.org1.isprint.com"
            ]
        }
    },
    "orderers": {
        "orderer1.isprint.com": {
            "url": "grpc://127.0.0.1:7050"
        },
        "orderer2.isprint.com": {
            "url": "grpc://127.0.0.1:8050"
        },
        "orderer3.isprint.com": {
            "url": "grpc://127.0.0.1:9050"
        }
    },
    "peers": {
        "peer1.org1.isprint.com": {
            "url": "grpc://127.0.0.1:7051"
        },
        "peer2.org1.isprint.com": {
            "url": "grpc://127.0.0.1:8051"
        }
    },
    "certificateAuthorities": {
        "ca.org1.isprint.com": {
            "url": "http://127.0.0.1:7054",
            "caName": "ca.org1.isprint.com"
        }
    }
}

这是我在关注同行日志时看到的(我必须将调试设置为 INFO,否则八卦 DEBUG 太多):

iamuser@isprintdev:~/shared$ docker logs --tail 0 -f eeb970c52a36
2020-05-05 20:38:59.841 UTC [core.comm] ServerHandshake -> ERRO 080 TLS handshake failed with error tls: first record does not look like a TLS handshake server=PeerServer remoteaddress=10.0.2.2:61852
2020-05-05 20:38:59.926 UTC [core.comm] ServerHandshake -> ERRO 081 TLS handshake failed with error tls: first record does not look like a TLS handshake server=PeerServer remoteaddress=10.0.2.2:61853

为了完整起见,这里是我的 Docker compose yaml for peers:

version: '3.4'

volumes:
  peer1.org1.isprint.com:
  peer2.org1.isprint.com:
  couchdb1.org1.isprint.com:
  couchdb2.org1.isprint.com:

networks:
  isprint:
    external:
      name: fabric

services:
  org1couchdb1:
    image: hyperledger/fabric-couchdb
    environment:
      - COUCHDB_USER= couchdb
      - COUCHDB_PASSWORD=couchdb123
    volumes:
        - couchdb1.org1.isprint.com:/opt/couchdb/data
    deploy:
            mode: replicated
            replicas: 1
            restart_policy:
              condition: on-failure
            placement:
                constraints:
                    - node.hostname == isprintdev
    ports:
     - published: 5984
       target: 5984
       mode: host
    networks:
      isprint:
        aliases:
          - couchdb1.org1.isprint.com

  org1couchdb2:
    image: hyperledger/fabric-couchdb
    environment:
      - COUCHDB_USER= couchdb
      - COUCHDB_PASSWORD=couchdb123
    volumes:
        - couchdb2.org1.isprint.com:/opt/couchdb/data
    deploy:
            mode: replicated
            replicas: 1
            restart_policy:
              condition: on-failure
            placement:
                constraints:
                    - node.hostname == isprintdev
    ports:
     - published: 6984
       target: 5984
       mode: host
    networks:
      isprint:
        aliases:
          - couchdb2.org1.isprint.com

  org1peer1:
    image: hyperledger/fabric-peer:latest
    environment:
      # couchdb params
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1.org1.isprint.com:5984
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=couchdb
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=couchdb123
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
      #- CORE_LOGGING_LEVEL=INFO
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_TLS_ENABLED=true
      - 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_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
      - CORE_PEER_ID=peer1.org1.isprint.com
      - CORE_PEER_ADDRESS=peer1.org1.isprint.com:7051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer2.org1.isprint.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.isprint.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_VM_DOCKER_ATTACHSTDOUT=true
      - CORE_CHAINCODE_STARTUPTIMEOUT=1200s
      - CORE_CHAINCODE_EXECUTETIMEOUT=800s
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    volumes:
        - /var/run/:/host/var/run/
        - ./crypto-config/peerOrganizations/org1.isprint.com/peers/peer1.org1.isprint.com/msp:/etc/hyperledger/fabric/msp
        - ./crypto-config/peerOrganizations/org1.isprint.com/peers/peer1.org1.isprint.com/tls:/etc/hyperledger/fabric/tls
        - peer1.org1.isprint.com:/var/hyperledger/production
    deploy:
            mode: replicated
            replicas: 1
            restart_policy:
              condition: on-failure
            placement:
                constraints:
                    - node.hostname == isprintdev
    ports:
            - published: 7051
              target: 7051
              mode: host
            - published: 7053
              target: 7053
              mode: host
    networks:
      isprint:
        aliases:
          - peer1.org1.isprint.com


  org1peer2:
    image: hyperledger/fabric-peer:latest
    environment:
      # couchdb params
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb2.org1.isprint.com:5984
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=couchdb
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=couchdb123
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
      #- CORE_LOGGING_LEVEL=INFO
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_TLS_ENABLED=true
      - 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_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
      - CORE_PEER_ID=peer1.org1.isprint.com
      - CORE_PEER_ADDRESS=peer2.org1.isprint.com:8051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.isprint.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer2.org1.isprint.com:8051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_VM_DOCKER_ATTACHSTDOUT=true
      - CORE_CHAINCODE_STARTUPTIMEOUT=1200s
      - CORE_CHAINCODE_EXECUTETIMEOUT=800s
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start

    volumes:
        - /var/run/:/host/var/run/
        - ./crypto-config/peerOrganizations/org1.isprint.com/peers/peer2.org1.isprint.com/msp:/etc/hyperledger/fabric/msp
        - ./crypto-config/peerOrganizations/org1.isprint.com/peers/peer2.org1.isprint.com/tls:/etc/hyperledger/fabric/tls
        - peer2.org1.isprint.com:/var/hyperledger/production
    deploy:
            mode: replicated
            replicas: 1
            restart_policy:
              condition: on-failure
            placement:
                constraints:
                    - node.hostname == isprintdev
    ports:
            - published: 8051
              target: 7051
              mode: host
            - published: 8053
              target: 7053
              mode: host
    networks:
      isprint:
        aliases:
          - peer2.org1.isprint.com

如果我需要提供更多信息,请告诉我。

Connection.json 似乎缺少证书。请参阅 "fabric-samples" 下的 "first-network/connection-org1.json" 了解如何在连接到网关时使用证书。

我能看到的一个问题是您使用的是 grpc:// 而不是 grpcs://。如果您使用的是 TLS,则需要使用 grpcs:// 访问 orderer/peers ... 就像您通过 HTTP 使用 TLS 时需要 https://(而不是 http://).更新后,您应该会收到一条更有意义的错误消息。