云社区 博客 博客详情

【Hyperledger Fabric入门】(一) 快速运行一个简单的Fabric网络1

CSDN 发表于 2021-02-12 00:36:00 2021-02-12
0
0

【摘要】 本文在Ubuntu18.04运行,fabric版本为2.3.0。本文篇幅较长,因此分为两篇。快速运行一个简单的Fabric网络2详见:link 目录 一、Fabric环境准备二、生成Fabric需要的证书文件三、创始块的生成1. 系统创始块的生成2. 账本创始块的生成 一、Fabric环境准备 Hyperledger Fabric环境搭建过程 ...

本文在Ubuntu18.04运行,fabric版本为2.3.0。本文篇幅较长,因此分为两篇。快速运行一个简单的Fabric网络2详见:link

一、Fabric环境准备

Hyperledger Fabric环境搭建过程
注:假设所有的配置文件和数据文件都存放在目录/home/yulin/blockchain/fabric/Hyperledger中,下面的演示将采用直接运行模块可执行文件的方式,不采用Docker的方式运行。

二、生成Fabric需要的证书文件

启动Fabric之前首先需要生成相关的证书,生成证书是通过cryptogen模块完成的,cryptogen模块会根据提供的配置文件生成后序模块运行过程中需要的证书和数据文件。在生成证书之前需要先创建一个文件夹存放配置文件和生成的证书文件。
创建存放证书的文件夹:

mkdir -p /home/yulin/blockchain/fabric/Hyperledger/fabricconfig

  
 
  • 1

cryptogen提供了一个命令可以获取cryptogen模块所需要的配置文件的样式:

cryptogen showtemplate

  
 
  • 1

把上述命令生成的内容复制到一个文件中。

# ---------------------------------------------------------------------------
# "OrdererOrgs" - Definition of organizations managing orderer nodes
# ---------------------------------------------------------------------------
OrdererOrgs:
  # ---------------------------------------------------------------------------
  # Orderer
  # ---------------------------------------------------------------------------
  - Name: Orderer Domain: example.com EnableNodeOUs: false # --------------------------------------------------------------------------- # "Specs" - See PeerOrgs below for complete description # --------------------------------------------------------------------------- Specs: - Hostname: orderer

# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
  # ---------------------------------------------------------------------------
  # Org1
  # ---------------------------------------------------------------------------
  - Name: Org1 Domain: org1.example.com EnableNodeOUs: false # --------------------------------------------------------------------------- # "CA" # --------------------------------------------------------------------------- # Uncomment this section to enable the explicit definition of the CA for this # organization.  This entry is a Spec.  See "Specs" section below for details. # --------------------------------------------------------------------------- # CA: # Hostname: ca # implicitly ca.org1.example.com # Country: US # Province: California # Locality: San Francisco # OrganizationalUnit: Hyperledger Fabric # StreetAddress: address for org # default nil # PostalCode: postalCode for org # default nil # --------------------------------------------------------------------------- # "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. #   - SANS: (Optional) Specifies one or more Subject Alternative Names # to be set in the resulting x509. Accepts template # variables {{.Hostname}}, {{.Domain}}, {{.CommonName}}. IP # addresses provided here will be properly recognized. Other # values will be taken as DNS names. # NOTE: Two implicit entries are created for you: # - {{ .CommonName }} # - {{ .Hostname }} # --------------------------------------------------------------------------- # Specs: #   - Hostname: foo # implicitly "foo.org1.example.com" # CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above # SANS: # - "bar.{{.Domain}}" # - "altfoo.{{.Domain}}" # - "{{.Hostname}}.org6.net" # - 172.16.10.31 #   - 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: 1 # Start: 5 # Hostname: {{.Prefix}}{{.Index}} # default # SANS: #   - "{{.Hostname}}.alt.{{.Domain}}" # --------------------------------------------------------------------------- # "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 EnableNodeOUs: false Template: Count: 1 Users: Count: 1


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116

在上面的配置文件中有一个属性Domain,这个值是由用户设置的。
将上面的内容保存到/home/yulin/blockchain/fabric/Hyperledger/fabricconfig中,并命名为crypto-config.yaml。保存后执行如下命令:

cd /home/yulin/blockchain/fabric/Hyperledger/fabricconfig
cryptogen generate --config=crypto-config.yaml --output ./crypto-config

  
 
  • 1
  • 2

文件夹里面会新增加一个文件夹crypto-config,里面存放着本例的相关配置文件,通过tree查看一下生成证书文件的内容。

$ tree -L 5
.
├── crypto-config
│   ├── ordererOrganizations
│   │   └── example.com
│   │ ├── ca
│   │ │   ├── ca.example.com-cert.pem
│   │ │   └── priv_sk
│   │ ├── msp
│   │ │   ├── admincerts
│   │ │   ├── cacerts
│   │ │   └── tlscacerts
│   │ ├── orderers
│   │ │   └── orderer.example.com
│   │ ├── tlsca
│   │ │   ├── priv_sk
│   │ │   └── tlsca.example.com-cert.pem
│   │ └── users
│   │ └── Admin@example.com
│   └── peerOrganizations
│ ├── org1.example.com
│ │   ├── ca
│ │   │   ├── ca.org1.example.com-cert.pem
│ │   │   └── priv_sk
│ │   ├── msp
│ │   │   ├── admincerts
│ │   │   ├── cacerts
│ │   │   └── tlscacerts
│ │   ├── peers
│ │   │   └── peer0.org1.example.com
│ │   ├── tlsca
│ │   │   ├── priv_sk
│ │   │   └── tlsca.org1.example.com-cert.pem
│ │   └── users
│ │ ├── Admin@org1.example.com
│ │ └── User1@org1.example.com
│ └── org2.example.com
│ ├── ca
│ │   ├── ca.org2.example.com-cert.pem
│ │   └── priv_sk
│ ├── msp
│ │   ├── admincerts
│ │   ├── cacerts
│ │   └── tlscacerts
│ ├── peers
│ │   └── peer0.org2.example.com
│ ├── tlsca
│ │   ├── priv_sk
│ │   └── tlsca.org2.example.com-cert.pem
│ └── users
│ ├── Admin@org2.example.com
│ └── User1@org2.example.com
└── crypto-config.yaml

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

通过上述步骤所有的整数文件都已经生成完毕,现在需要将测试域名映射到本机的IP地址上面,否则后面的操作可能会出现错误。
从上述的内容中提取出后缀为example.com的域名。本例中提取出的信息如下:

orderer.example.com
peer0.org1.example.com
peer0.org2.example.com

  
 
  • 1
  • 2
  • 3

打开端映射文件:

gedit /etc/hosts

  
 
  • 1

添加上如下内容:

192.168.178.128 orderer.example.com
192.168.178.128 peer0.org1.example.com
192.168.178.128 peer0.org2.example.com

  
 
  • 1
  • 2
  • 3

检查是否设置成功,只需使用ping,ping得通这说明设置成功。

三、创始块的生成

1. 系统创始块的生成

Fabric是基于区块链的分布式账本,每个账本都拥有自己的区块链,账本的区块链中会存储账本的交易数据,但账本区块链中的第一个区块是个例外,该区块不存储交易数据而是存储配置信息。通常将账本的第一个区块称为创始块。综上所述,Fabric中账本的第一个区块是需要手动生成的。configtxgen模块是专门负责生成系统的创始块和Channel(Fabric中的Channel就是账本,关于Channel的概念在后续章节会介绍)的创始块。configtxgen模块也需要一个配置文件来定义相关的属性。

下面是在Fabric源码中提供的configtxgen模块所需要的配置文件的例子。该文件的路径是$GOPATH/src/github.com/hyperledger/fabric/sampleconfig,在这个目录下面有一个名为configtx.yaml的文件,对这个文件进行修改即可使用。由于创始块文件是提供给Orderer节点使用,因此创建一个文件夹来存储Oderer节点相关的文件。创建之后再把样例配置文件复制到该文件夹中。

创建存放configtxgen模块相关配置文件的文件夹的命令如下所示。

$ mkdir -p /home/yulin/blockchain/fabric/Hyperledger/order/
$ cp -r $GOPATH/src/github.com/hyperledger/fabric/sampleconfig/configtx.yaml /home/yulin/blockchain/fabric/Hyperledger/order/
$ cd /home/yulin/blockchain/fabric/Hyperledger/order/

  
 
  • 1
  • 2
  • 3

对configtx.yaml进行修改,修改后的内容如下所示:

Organizations: - &OrdererOrg Name: OrdererOrg ID: OrdererMSP MSPDir: ../fabricconfig/crypto-config/ordererOrganizations/example.com/msp Policies: Readers: Type: Signature Rule: "OR('OrdererMSP.member')" Writers: Type: Signature Rule: "OR('OrdererMSP.member')" Admins: Type: Signature Rule: "OR('OrdererMSP.admin')" - &Org1 Name: Org1MSP ID: Org1MSP MSPDir: ../fabricconfig/crypto-config/peerOrganizations/org1.example.com/msp Policies: Readers: Type: Signature Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')" Writers: Type: Signature Rule: "OR('Org1MSP.admin', 'Org1MSP.client')" Admins: Type: Signature Rule: "OR('Org1MSP.admin')" Endorsement: Type: Signature Rule: "OR('Org1MSP.peer')" AnchorPeers: - Host: peer0.org1.example.com Port: 7051 - &Org2 Name: Org2MSP ID: Org2MSP MSPDir: ../fabricconfig/crypto-config/peerOrganizations/org2.example.com/msp Policies: Readers: Type: Signature Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')" Writers: Type: Signature Rule: "OR('Org2MSP.admin', 'Org2MSP.client')" Admins: Type: Signature Rule: "OR('Org2MSP.admin')" Endorsement: Type: Signature Rule: "OR('Org2MSP.peer')" AnchorPeers: - Host: peer0.org2.example.com Port: 7051
Capabilities: # Channel capabilities apply to both the orderers and the peers and must be # supported by both. # Set the value of the capability to true to require it. Channel: &ChannelCapabilities # V2.0 for Channel is a catchall flag for behavior which has been # determined to be desired for all orderers and peers running at the v2.0.0 # level, but which would be incompatible with orderers and peers from # prior releases. # Prior to enabling V2.0 channel capabilities, ensure that all # orderers and peers on a channel are at v2.0.0 or later. V2_0: true # Orderer capabilities apply only to the orderers, and may be safely # used with prior release peers. # Set the value of the capability to true to require it. Orderer: &OrdererCapabilities # V1.1 for Orderer is a catchall flag for behavior which has been # determined to be desired for all orderers running at the v1.1.x # level, but which would be incompatible with orderers from prior releases. # Prior to enabling V2.0 orderer capabilities, ensure that all # orderers on a channel are at v2.0.0 or later. V2_0: true # Application capabilities apply only to the peer network, and may be safely # used with prior release orderers. # Set the value of the capability to true to require it. Application: &ApplicationCapabilities # V2.0 for Application enables the new non-backwards compatible # features and fixes of fabric v2.0. # Prior to enabling V2.0 orderer capabilities, ensure that all # orderers on a channel are at v2.0.0 or later. V2_0: true

Application: &ApplicationDefaults Organizations: # Policies defines the set of policies at this level of the config tree # For Application policies, their canonical path is #   /Channel/Application/<PolicyName> Policies: &ApplicationDefaultPolicies LifecycleEndorsement: Type: ImplicitMeta Rule: "MAJORITY Endorsement" Endorsement: Type: ImplicitMeta Rule: "MAJORITY Endorsement" Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" # Capabilities describes the application level capabilities, see the # dedicated Capabilities section elsewhere in this file for a full # description Capabilities: <<: *ApplicationCapabilities

Orderer: &OrdererDefaults OrdererType: solo Addresses: - orderer.example.com:7050 BatchTimeout: 2s BatchSize: MaxMessageCount: 10 AbsoluteMaxBytes: 99 MB PreferredMaxBytes: 512 KB Kafka: Brokers: - 127.0.0.1:9092 Organizations:
  # Policies defines the set of policies at this level of the config tree # For Orderer policies, their canonical path is #   /Channel/Orderer/<PolicyName> Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" # BlockValidation specifies what signatures must be included in the block # from the orderer for the peer to validate it. BlockValidation: Type: ImplicitMeta Rule: "ANY Writers" # Capabilities describes the orderer level capabilities, see the # dedicated Capabilities section elsewhere in this file for a full # description Capabilities: <<: *OrdererCapabilities

################################################################################
#
#   CHANNEL
#
#   This section defines the values to encode into a config transaction or
#   genesis block for channel related parameters.
#
################################################################################
Channel: &ChannelDefaults # Policies defines the set of policies at this level of the config tree # For Channel policies, their canonical path is #   /Channel/<PolicyName> Policies: # Who may invoke the 'Deliver' API Readers: Type: ImplicitMeta Rule: "ANY Readers" # Who may invoke the 'Broadcast' API Writers: Type: ImplicitMeta Rule: "ANY Writers" # By default, who may modify elements at this config level Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" # Capabilities describes the channel level capabilities, see the # dedicated Capabilities section elsewhere in this file for a full # description Capabilities: <<: *ChannelCapabilities


Profiles: TestTwoOrgsOrdererGenesis: <<: *ChannelDefaults Orderer: <<: *OrdererDefaults Organizations: - <<: *OrdererOrg Consortiums: SampleConsortium: Organizations: - <<: *Org1 - <<: *Org2 TestTwoOrgsChannel: <<: *ChannelDefaults Consortium: SampleConsortium Application: <<: *ApplicationDefaults Organizations: - <<: *Org1 - <<: *Org2

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211

配置文件修改完成之后执行如下命令生成创始块文件。

$ cd /home/yulin/blockchain/fabric/Hyperledger/order
$ configtxgen -profile TestTwoOrgsOrdererGenesis -channelID syschannel -outputBlock ./orderer.genesis.block
2021-02-07 16:06:48.432 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-02-07 16:06:48.459 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: solo
2021-02-07 16:06:48.460 CST [common.tools.configtxgen.localconfig] Load -> INFO 003 Loaded configuration: /home/yulin/blockchain/fabric/Hyperledger/order/configtx.yaml
2021-02-07 16:06:48.761 CST [common.tools.configtxgen] doOutputBlock -> INFO 004 Generating genesis block
2021-02-07 16:06:48.768 CST [common.tools.configtxgen] doOutputBlock -> INFO 005 Creating system channel genesis block
2021-02-07 16:06:48.833 CST [common.tools.configtxgen] doOutputBlock -> INFO 006 Writing genesis block


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上述命令执行完成之后会在文件夹/home/yulin/blockchain/fabric/Hyperledger/order中生成文件orderer.genesis.block。这是Fabric系统的创始块文件。
在这里插入图片描述

2. 账本创始块的生成

通道Channel是Fabric中非常重要的概念,一个Channel表示一个账本。Fabric和其他区块链平台最大的区别是fabric支持多账本。每个fabric应用都至少包含一个Channel,因此创建Channel是fabric中比较重要的步骤。
创建Channel命令:

$ configtxgen -profile TestTwoOrgsChannel -outputCreateChannelTx ./mychannel.tx -channelID mychannel
2021-02-09 16:25:12.501 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-02-09 16:25:12.524 CST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/yulin/blockchain/fabric/Hyperledger/order/configtx.yaml
2021-02-09 16:25:12.524 CST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx
2021-02-09 16:25:12.538 CST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

执行完之后会生成mychannel.tx,该文件用来生成Channel。除此之外还需要生成相关的锚点文件,而生成锚点文件需要执行以下命令:

$ configtxgen -profile TestTwoOrgsChannel -outputAnchorPeersUpdate ./Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2021-02-09 16:31:18.108 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-02-09 16:31:18.150 CST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/yulin/blockchain/fabric/Hyperledger/order/configtx.yaml
2021-02-09 16:31:18.154 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Generating anchor peer update
2021-02-09 16:31:18.161 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 004 Writing anchor peer update

$ configtxgen -profile TestTwoOrgsChannel -outputAnchorPeersUpdate ./Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2021-02-09 16:31:39.833 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-02-09 16:31:39.858 CST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/yulin/blockchain/fabric/Hyperledger/order/configtx.yaml
2021-02-09 16:31:39.858 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Generating anchor peer update
2021-02-09 16:31:39.860 CST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 004 Writing anchor peer update

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

命令执行完成之后会在相应的文件夹下面生成文件Org1MSPanchors.tx和Org2MSPanchors.tx,这些文件在后面会用到。

文章来源: blog.csdn.net,作者:Famidlistimo,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_44029550/article/details/113178284

登录后可下载附件,请登录或者注册

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:huaweicloud.bbs@huawei.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
评论文章 //点赞 收藏 0
点赞
分享文章到微博
分享文章到朋友圈

上一篇:《人工智能导论》第二章 概念表示

下一篇:【HCL】同一vlan互通的交换机配置实验

评论 (0)


登录后可评论,请 登录注册

评论