Fabric 1.0物理机集群如何部署
这篇文章主要为大家展示了"Fabric 1.0物理机集群如何部署",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Fabric 1.0物理机集群如何部署"这篇文章吧。
Fabric 1.0 物理机集群部署
部署环境
机器规划
编号 | 主机名 | IP地址 | 域名 | 备注 | 环境 |
---|---|---|---|---|---|
1 | Node-1 | 172.19.199.45 | kafka1.local | zk-kafka节点 | java |
2 | Node-2 | 172.19.199.46 | kafka2.local | zk-kafka节点 | java |
3 | Node-3 | 172.19.199.47 | kafka3.local | zk-kafka节点 | java |
4 | Node-4 | 172.19.199.48 | peer0.org1.local | peer节点 | docker, golang |
5 | Node-5 | 172.19.199.49 | peer1.org1.local | peer节点 | docker, golang |
6 | Node-6 | 172.19.199.50 | peer0.org2.local | peer节点 | docker, golang |
7 | Node-7 | 172.19.199.51 | peer1.org2.local | peer节点 | docker, golang |
8 | Node-9 | 172.19.199.52 | ca.org1.local | ca节点 | docker |
9 | Node-9 | 172.19.199.53 | ca.org2.local | ca节点 | docker |
10 | Node-10 | 172.19.199.54 | order.local | order节点 | docker |
Hosts配置
172.19.199.45 Node-1 kafka1.local 172.19.199.46 Node-2 kafka2.local 172.19.199.47 Node-3 kafka3.local 172.19.199.48 Node-4 peer0.org1.local 172.19.199.49 Node-5 peer1.org1.local 172.19.199.50 Node-6 peer0.org2.local 172.19.199.51 Node-7 peer1.org2.local 172.19.199.52 Node-8 ca.org1.local 172.19.199.53 Node-9 ca.org2.local 172.19.199.54 Node-10 orderer.local
系统环境
操作系统:
~# cat /proc/version Linux version 4.4.0-82-generic (buildd@lgw01-43) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) #105-Ubuntu SMP Tue Jun 20 15:23:02 UTC 2017
Docker:
~# docker -v Docker version 17.06.0-ce, build 02c1d87
Docker Compose
~# docker-compose -v docker-compose version 1.14.0, build c7bdf9e
Golang
~# go version go version go1.8.3 linux/amd64
系统依赖安装
部署chaincode
的peer
节点需要安装golang
以及docker
环境
Docker 安装
~# curl -fsSL https://get.docker.com/ | sh~# curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose~# sudo chmod +x /usr/local/bin/docker-compose
golang 安装
~# curl https://www.golangtc.com/static/go/1.8.3/go1.8.3.linux-amd64.tar.gz | tar zx -C /opt/~# mkdir -p ~/go/src ~/go/pkg ~/go/bin~# vi /etc/profileexport GOROOT=/opt/goexport GOPATH=~/goexport PATH=$PATH:$GOROOT/bin~# source /etc/profile
fabric 二进制可执行程序安装
执行bootstrap-1.0.0.sh
,下载fabric 1.0 并安装到 /opt/fabric
目录:
#!/bin/bash # # Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # export VERSION=1.0.0 export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}') #Set MARCH variable i.e ppc64le,s390x,x86_64,i386 MARCH=`uname -m` : ${CA_TAG:="$MARCH-$VERSION"} : ${FABRIC_TAG:="$MARCH-$VERSION"} echo "===> Downloading platform binaries" mkdir /opt/fabric curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric/${ARCH}-${VERSION}/hyperledger-fabric-${ARCH}-${VERSION}.tar.gz | tar xz -C /opt/fabric
安装完成后/opt/fabric/bin/
下会有以下工具
~# tree /opt/fabric/bin//opt/fabric/bin/├── configtxgen├── configtxlator├── cryptogen├── get-byfn.sh├── get-docker-images.sh├── orderer└── peer0 directories, 7 files
fabric 部署
kafka 集群部署
使用 Node-1,Node-3,Node-3 节点部署kafka集群
参考: http://kafka.apache.org/documentation.html
fabric初始化配置文件
~/fabric/configs/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: <<: *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: Node-4 Port: 7051 - Host: Node-5 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: Node-6 Port: 7051 - Host: Node-7 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: - Node-10: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: - Node-1:9092 - Node-2:9092 - Node-3: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:
~/fabric/configs/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: orderer.local # --------------------------------------------------------------------------- # "Specs" - See PeerOrgs below for complete description # --------------------------------------------------------------------------- Specs: - Hostname: orderer.local CommonName: orderer.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: Node-4 CommonName: peer0.org1.local - Hostname: Node-5 CommonName: peer1.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: Node-6 CommonName: peer0.org2.local - Hostname: Node-7 CommonName: peer1.org2.local Template: Count: 2 Users: Count: 1
~/fabric/scripts/generateArtifacts.sh
:#!/bin/bash +x # # Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # #set -e CHANNEL_NAME=$1 : ${CHANNEL_NAME:="mychannel"} echo $CHANNEL_NAME export FABRIC_ROOT=/opt/fabric export FABRIC_CFG_PATH=$PWD echo OS_ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}') ## Generates Org certs using cryptogen tool function generateCerts (){ CRYPTOGEN=$FABRIC_ROOT/bin/cryptogen if [ -f "$CRYPTOGEN" ]; then echo "Using cryptogen -> $CRYPTOGEN" else echo "Downloading fabric cryptogen binaries > /opt/fabric/bin " fi echo echo "##########################################################" echo "##### Generate certificates using cryptogen tool #########" echo "##########################################################" ## 生成crypto-config文件夹,包括加密公钥私钥证书等 $CRYPTOGEN generate --config=$FABRIC_CFG_PATH/crypto-config.yaml echo } ## Generate orderer genesis block , channel configuration transaction and anchor peer update transactions function generateChannelArtifacts() { CONFIGTXGEN=$FABRIC_ROOT/bin/configtxgen if [ -f "$CONFIGTXGEN" ]; then echo "Using configtxgen -> $CONFIGTXGEN" else echo "Downloading fabric configtxgen binaries > /opt/fabric/bin " fi mkdir ./channel-artifacts echo "##########################################################" echo "######### Generating Orderer Genesis block ##############" echo "##########################################################" # Note: For some unknown reason (at least for now) the block file can't be # named orderer.genesis.block or the orderer will fail to launch! ## 生成genesis.block $CONFIGTXGEN -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block echo echo "#################################################################" echo "### Generating channel configuration transaction 'channel.tx' ###" echo "#################################################################" ## 生成channel.tx $CONFIGTXGEN -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME echo echo "#################################################################" echo "####### Generating anchor peer update for Org1MSP ##########" echo "#################################################################" ## 生成Org1MSPanchors.tx $CONFIGTXGEN -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP echo echo "#################################################################" echo "####### Generating anchor peer update for Org2MSP ##########" echo "#################################################################" ## 生成Org2MSPanchors.tx $CONFIGTXGEN -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP echo } generateCerts generateChannelArtifacts
生成fabric公私钥、证书、创世区块等配置
~# cd ~/fabric/configs~/fabric/configs# ../scripts/generateArtifacts.sh~/fabric/configs# tree.├── channel-artifacts│ ├── channel.tx│ ├── genesis.block│ ├── Org1MSPanchors.tx│ └── Org2MSPanchors.tx├── configtx.yaml├── core.yaml├── crypto-config│ ├── ordererOrganizations│ │ └── orderer.local│ │ ├── ca│ │ │ ├── ca.orderer.local-cert.pem│ │ │ └── d775bb35eecf2930a52214103e0854a72c01a32ab7315da753084fdbbf6e3e9b_sk│ │ ├── msp│ │ │ ├── admincerts│ │ │ │ └── Admin@orderer.local-cert.pem│ │ │ ├── cacerts│ │ │ │ └── ca.orderer.local-cert.pem│ │ │ └── tlscacerts│ │ │ └── tlsca.orderer.local-cert.pem│ │ ├── orderers│ │ │ └── orderer.local│ │ │ ├── msp│ │ │ │ ├── admincerts│ │ │ │ │ └── Admin@orderer.local-cert.pem│ │ │ │ ├── cacerts│ │ │ │ │ └── ca.orderer.local-cert.pem│ │ │ │ ├── keystore│ │ │ │ │ └── d97a464f195e5346031509054d93aabff3849084027ac43d879d230b773fc669_sk│ │ │ │ ├── signcerts│ │ │ │ │ └── orderer.local-cert.pem│ │ │ │ └── tlscacerts│ │ │ │ └── tlsca.orderer.local-cert.pem│ │ │ └── tls│ │ │ ├── ca.crt│ │ │ ├── server.crt│ │ │ └── server.key│ │ ├── tlsca│ │ │ ├── 24ca2916fa49e71657641c41bc4012fdf18858970db00f1a35ae93caea335345_sk│ │ │ └── tlsca.orderer.local-cert.pem│ │ └── users│ │ └── Admin@orderer.local│ │ ├── msp│ │ │ ├── admincerts│ │ │ │ └── Admin@orderer.local-cert.pem│ │ │ ├── cacerts│ │ │ │ └── ca.orderer.local-cert.pem│ │ │ ├── keystore│ │ │ │ └── e45eb26e86df1c5958530df1de8519b06c214480cd73fdfa71671efa0005aa42_sk│ │ │ ├── signcerts│ │ │ │ └── Admin@orderer.local-cert.pem│ │ │ └── tlscacerts│ │ │ └── tlsca.orderer.local-cert.pem│ │ └── tls│ │ ├── ca.crt│ │ ├── server.crt│ │ └── server.key│ └── peerOrganizations│ ├── org1.local│ │ ├── ca│ │ │ ├── 17b0a2ea854d3ed9cfcb003285734af883d2764eabbe238d9720625f7bf5c496_sk│ │ │ └── ca.org1.local-cert.pem│ │ ├── msp│ │ │ ├── admincerts│ │ │ │ └── Admin@org1.local-cert.pem│ │ │ ├── cacerts│ │ │ │ └── ca.org1.local-cert.pem│ │ │ └── tlscacerts│ │ │ └── tlsca.org1.local-cert.pem│ │ ├── peers│ │ │ ├── peer0.org1.local│ │ │ │ ├── msp│ │ │ │ │ ├── admincerts│ │ │ │ │ │ └── Admin@org1.local-cert.pem│ │ │ │ │ ├── cacerts│ │ │ │ │ │ └── ca.org1.local-cert.pem│ │ │ │ │ ├── keystore│ │ │ │ │ │ ├── 972e7d812a8112695798d3c038ab6b264f98d4cde36ab02ef21a6bb93ddedcbd_sk│ │ │ │ │ │ └── e8094def3c657989497428160fb299080f34a9eefa75d5e3e90c8464c642e354_sk│ │ │ │ │ ├── signcerts│ │ │ │ │ │ └── peer0.org1.local-cert.pem│ │ │ │ │ └── tlscacerts│ │ │ │ │ └── tlsca.org1.local-cert.pem│ │ │ │ └── tls│ │ │ │ ├── ca.crt│ │ │ │ ├── server.crt│ │ │ │ └── server.key│ │ │ └── peer1.org1.local│ │ │ ├── msp│ │ │ │ ├── admincerts│ │ │ │ │ └── Admin@org1.local-cert.pem│ │ │ │ ├── cacerts│ │ │ │ │ └── ca.org1.local-cert.pem│ │ │ │ ├── keystore│ │ │ │ │ ├── 02abe6ecc33efb336e34ed064099d41ef7828770a71a2aeaf409a61977cf1404_sk│ │ │ │ │ └── 175a67cf1d5b59a215c1f8b41fdf3916a303600c0d80a5a10a1508254a4ae153_sk│ │ │ │ ├── signcerts│ │ │ │ │ └── peer1.org1.local-cert.pem│ │ │ │ └── tlscacerts│ │ │ │ └── tlsca.org1.local-cert.pem│ │ │ └── tls│ │ │ ├── ca.crt│ │ │ ├── server.crt│ │ │ └── server.key│ │ ├── tlsca│ │ │ ├── 6d4f32f6422c2178fdf7ecec16bf14e2abd9f34c151c953ef6d97d5f2cd7f915_sk│ │ │ └── tlsca.org1.local-cert.pem│ │ └── users│ │ ├── Admin@org1.local│ │ │ ├── msp│ │ │ │ ├── admincerts│ │ │ │ │ └── Admin@org1.local-cert.pem│ │ │ │ ├── cacerts│ │ │ │ │ └── ca.org1.local-cert.pem│ │ │ │ ├── keystore│ │ │ │ │ └── 5423b1db0ee58b32d33edc220845d4b27eb1cd57812b1e4a512ecb45688d6538_sk│ │ │ │ ├── signcerts│ │ │ │ │ └── Admin@org1.local-cert.pem│ │ │ │ └── tlscacerts│ │ │ │ └── tlsca.org1.local-cert.pem│ │ │ └── tls│ │ │ ├── ca.crt│ │ │ ├── server.crt│ │ │ └── server.key│ │ └── User1@org1.local│ │ ├── msp│ │ │ ├── admincerts│ │ │ │ └── User1@org1.local-cert.pem│ │ │ ├── cacerts│ │ │ │ └── ca.org1.local-cert.pem│ │ │ ├── keystore│ │ │ │ └── ee4f6a08b8ba76a2484d908339cfb0500ce5462653847070699f68d0109de930_sk│ │ │ ├── signcerts│ │ │ │ └── User1@org1.local-cert.pem│ │ │ └── tlscacerts│ │ │ └── tlsca.org1.local-cert.pem│ │ └── tls│ │ ├── ca.crt│ │ ├── server.crt│ │ └── server.key│ └── org2.local│ ├── ca│ │ ├── 0849b6bad250f4e81866c0c0232b2960bf1f36cb1898329e18d40c2177de9c04_sk│ │ └── ca.org2.local-cert.pem│ ├── msp│ │ ├── admincerts│ │ │ └── Admin@org2.local-cert.pem│ │ ├── cacerts│ │ │ └── ca.org2.local-cert.pem│ │ └── tlscacerts│ │ └── tlsca.org2.local-cert.pem│ ├── peers│ │ ├── peer0.org2.local│ │ │ ├── msp│ │ │ │ ├── admincerts│ │ │ │ │ └── Admin@org2.local-cert.pem│ │ │ │ ├── cacerts│ │ │ │ │ └── ca.org2.local-cert.pem│ │ │ │ ├── keystore│ │ │ │ │ ├── 45b896276df803b7f11009416f87fa73b039ebc5e19a46cfff725e387e21dd4d_sk│ │ │ │ │ └── 9ce7301f5b816b99a98d9729c0346acf6fc30e6c436ae6f29f5f1908d92adba5_sk│ │ │ │ ├── signcerts│ │ │ │ │ └── peer0.org2.local-cert.pem│ │ │ │ └── tlscacerts│ │ │ │ └── tlsca.org2.local-cert.pem│ │ │ └── tls│ │ │ ├── ca.crt│ │ │ ├── server.crt│ │ │ └── server.key│ │ └── peer1.org2.local│ │ ├── msp│ │ │ ├── admincerts│ │ │ │ └── Admin@org2.local-cert.pem│ │ │ ├── cacerts│ │ │ │ └── ca.org2.local-cert.pem│ │ │ ├── keystore│ │ │ │ ├── 20ca7a677d1c1a03eacb55d931fc9525cd861f843fd95a6748e8f29ac49b8ecf_sk│ │ │ │ └── 2c7e1a7d2128c45d160c31aa43d2a34782277753155a7fef38ceceb6acdaca79_sk│ │ │ ├── signcerts│ │ │ │ └── peer1.org2.local-cert.pem│ │ │ └── tlscacerts│ │ │ └── tlsca.org2.local-cert.pem│ │ └── tls│ │ ├── ca.crt│ │ ├── server.crt│ │ └── server.key│ ├── tlsca│ │ ├── 55fee7208c7484dfb2d9085c9dea0cce342ff6850e15d53dc0cf3d0daa655d27_sk│ │ └── tlsca.org2.local-cert.pem│ └── users│ ├── Admin@org2.local│ │ ├── msp│ │ │ ├── admincerts│ │ │ │ └── Admin@org2.local-cert.pem│ │ │ ├── cacerts│ │ │ │ └── ca.org2.local-cert.pem│ │ │ ├── keystore│ │ │ │ └── 0bb9c50d25a654795ae4741fe7b5635b3d797359e841525a63252161057ce13b_sk│ │ │ ├── signcerts│ │ │ │ └── Admin@org2.local-cert.pem│ │ │ └── tlscacerts│ │ │ └── tlsca.org2.local-cert.pem│ │ └── tls│ │ ├── ca.crt│ │ ├── server.crt│ │ └── server.key│ └── User1@org2.local│ ├── msp│ │ ├── admincerts│ │ │ └── User1@org2.local-cert.pem│ │ ├── cacerts│ │ │ └── ca.org2.local-cert.pem│ │ ├── keystore│ │ │ └── d496ff9c745a6cabaaed0c7af28910b7ef5a0b9da23d374d2864ffeb9737800c_sk│ │ ├── signcerts│ │ │ └── User1@org2.local-cert.pem│ │ └── tlscacerts│ │ └── tlsca.org2.local-cert.pem│ └── tls│ ├── ca.crt│ ├── server.crt│ └── server.key├── crypto-config.yaml└── orderer.yaml111 directories, 113 files
将生成的fabric配置分发到各个节点
~# scp -r ~/fabric/configs/ Node-*:~/fabric/
部署orderer节点
~/fabric/start-orderer.sh
:#!/bin/bash export FABRIC_ROOT=/opt/fabric export FABRIC_CFG_PATH=/root/fabric/configs export ORDERER_GENERAL_GENESISMETHOD=file export ORDERER_GENERAL_GENESISFILE=$FABRIC_CFG_PATH/channel-artifacts/genesis.block export ORDERER_GENERAL_LISTENADDRESS=orderer.local export ORDERER_GENERAL_LOGLEVEL=debug export ORDERER_GENERAL_LOCALMSPID=OrdererMSP export ORDERER_GENERAL_LOCALMSPDIR=$FABRIC_CFG_PATH/crypto-config/ordererOrganizations/orderer.local/orderers/orderer.local/msp/ # Enabled TLS export ORDERER_GENERAL_TLS_ENABLED=true export ORDERER_GENERAL_TLS_PRIVATEKEY=$FABRIC_CFG_PATH/crypto-config/ordererOrganizations/orderer.local/orderers/orderer.local/tls/server.key export ORDERER_GENERAL_TLS_CERTIFICATE=$FABRIC_CFG_PATH/crypto-config/ordererOrganizations/orderer.local/orderers/orderer.local/tls/server.crt export ORDERER_GENERAL_TLS_ROOTCAS=[$FABRIC_CFG_PATH/crypto-config/ordererOrganizations/orderer.local/orderers/orderer.local/tls/ca.crt] export CONFIGTX_ORDERER_ORDERERTYPE=kafka export ORDERER_GENERAL_GENESISPROFILE=TwoOrgsOrdererGenesis export CONFIGTX_ORDERER_KAFKA_BROKERS=[Node-1:9092,Node-2:9092,Node-3:9092] export CONFIGTX_ORDERER_ORDERERTYPE=kafka export ORDERER_KAFKA_VERBOSE=true export ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s export ORDERER_KAFKA_RETRY_SHORTTOTAL=30s export GRPC_TRACE=all=true export GRPC_VERBOSITY=debug $FABRIC_ROOT/bin/orderer start
~/fabric/stop-orderer.sh
:#!/bin/bash netstat -tlpn |grep orderer | tr -s -t ' ' | cut -d ' ' -f7 | cut -d '/' -f1 | head -1 | xargs kill -9
~/fabric/configs/orderer.yaml
:$FABRIC_CFG_PATH
需要有orderer.yaml
文件# Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # --- ################################################################################ # # 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 #
for a total of , and then every # for a total of 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:
启动orderer:
~# ~/fabric/start-orderer.sh
部署peer节点
此处以 Node-4
即 peer0.org1.local
为示例,其他节点参照做配置修改即可
~/fabric/start-peer.sh
:#!/bin/bash export FABRIC_ROOT=/opt/fabric export FABRIC_CFG_PATH=~/fabric/configs export CORE_LOGGING_LEVEL=DEBUG export CORE_LOGGING_PEER=debug 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/peers/peer0.org1.local/msp export CORE_PEER_ADDRESS=peer0.org1.local:7051 # # Used with Go profiling tools only in none production environment. In # # production, it should be disabled (eg enabled: false) export CORE_PEER_PROFILE_ENABLED=true # # the following setting starts chaincode containers on the same # # bridge network as the peers # # https://docs.docker.com/compose/networking/ export CORE_VM_ENDPOINT=unix:///var/run/docker.sock export CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=host export CORE_LEDGER_STATE_STATEDATABASE=goleveldb # #export CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=peer0.org1.local:5984 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 CORE_PEER_GOSSIP_ORGLEADER=false export CORE_PEER_GOSSIP_USELEADERELECTION=true export CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.local:7051 $FABRIC_ROOT/bin/peer node start
~/fabric/stop-peer.sh
:#!/bin/bash netstat -tlpn |grep peer | tr -s -t ' ' | cut -d ' ' -f7 | cut -d '/' -f1 | head -1 | xargs kill -9
~/fabric/configs/core.yaml
:$FABRIC_CFG_PATH
需要有core.yaml
文件# Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # ############################################################################### # # 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=
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
启动peer:
~# ~/fabric/start-peer.sh
以上是"Fabric 1.0物理机集群如何部署"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!