IPFS搭建

IPFS搭建

下载工具

ipfs官网

进入官网选择合适的版本。go-ipfs_v0.4.23_linux-amd64.tar.gz

1
2
3
4
tar -zxf  go-ipfs.tar.gz
cd go-ipfs
./install.sh //安装文件自动mv /usr/local/bin
ipfs init //ipfs初始化

下载go

我下载的是windows版本。

私有网络

清除缺省启动节点

默认会连接进ipfs的公链

1
ipfs bootstrap rm --all

生成秘钥

1
2
3
git clone https://github.com/Kubuxu/go-ipfs-swarm-key-gen.git //下载秘钥生成工具源码
go build ipfs-swarm-key-gen/main.go //编译得到main.exe
main.exe>swarm.key //执行得到秘钥文件swarm.key

拷贝秘钥

将生成的swarm.key文件拷贝进所有的节点服务器中**~.ipfs**文件夹下

启动

选择一台稳定的公网ip地址为启动节点

1
ipfs id //查看该节点生成的hash

添加该节点地址到所有节点的bootstrap列表中

1
ipfs bootstrap add /ip4/启动节点的ip地址/tcp/4001/ipfs/启动节点的id的hash

启动。

1
2
ipfs daemon & //启动,后台运行
ipfs bootstrap list //查看ipfs bootstrap列表

在各个节点查看别的节点信息

1
ipfs swarm peers

上传下载

1
2
ipfs add xxx.png //上传到私链上,会返回hash码
ipfs get hash码 // 下载

默认端口

一定需要保证所有服务器的4001端口、5001端口、8080端口开放input的安全组。

  • 4001-与其他节点通信
  • 5001-API server
  • 8080-Gateway server

Peergos安装记

Peergos安装记

环境准备

作者在github里记录,为了跑tests,需要安装ant-optional这个插件,根据调查,ant-optional这个插件只有debian/ubuntu提供。因此准备一台ubuntu的机器。

安装工具

1
2
sudo apt-get install openjdk-11-jdk
sudo apt-get install ant
  • ubuntu:Ubuntu 18.04.3 LTS
  • java:openjdk 11.0.6
  • ant:1.10.5

下载peergos

1
2
git clone https://github.com/Peergos/Peergos.git
git clone https://github.com/Peergos/web-ui.git

网络要求

必须翻墙!!!

build

根据github执行各种ant命令,启动后台就是下面的命令

1
ant update_and_run

考虑有两种方式运行web-ui。

  1. 在ubuntu客户端通过ide运行整体系统。
  2. 前后端分离部署,前端通过命令ant ui来build静态资源文件,要修改vue的代码,在post/get等http请求中加入8000端口的后端url。通过nginx代理别的端口即可。

hadoop+spark分布式环境搭建

Hadoop整体框架

Hadoop由HDFS、MapReduce、HBase、Hive和ZooKeeper等成员组成,其中最基础最重要的两种组成元素为底层用于存储集群中所有存储节点文件的文件系统HDFS(Hadoop Distributed File System)和上层用来执行MapReduce程序的MapReduce引擎。

HDFS

HDFS架构采用主从架构(master/slave)。一个典型的HDFS集群包含一个NameNode节点和多个DataNode节点。NameNode节点负责整个HDFS文件系统中的文件的元数据保管和管理,集群中通常只有一台机器上运行NameNode实例,DataNode节点保存文件中的数据,集群中的机器分别运行一个DataNode实例。在HDFS中,NameNode节点被称为名称节点,DataNode节点被称为数据节点。DataNode节点通过心跳机制与NameNode节点进行定时的通信。

Map/Reduce

MapReduce是一种编程模型,用于大规模数据集的并行运算。Map(映射)和Reduce(化简),采用分而治之思想,先把任务分发到集群多个节点上,并行计算,然后再把计算结果合并,从而得到最终计算结果。多节点计算,所涉及的任务调度、负载均衡、容错处理等,都由MapReduce框架完成,不需要编程人员关心这些内容。

环境准备

准备了3台CentOS 6.10 64bit云服务器,1台做master NameNode主节点,2台做DataNode节点。

修改hosts文件

在3台服务器上的/etc/hosts,追加以下配置:

1
2
3
192.168.0.189 master worker0 namenode
192.168.0.233 worker1 datanode1
192.168.0.117 worker2 datanode2

统一hosts文件,可以让主机通过host名字来识别彼此。

ssh互信(免密登录)

在master节点执行以下:

1
2
3
4
ssh-keygen -t rsa -P '' #生成公钥
scp /root/.ssh/id_rsa.pub root@worker1:/root/.ssh/id_rsa.pub.master #从master节点拷贝id_rsa.pub到worker主机上,并且改名为id_rsa.pub.master
scp /root/.ssh/id_rsa.pub root@worker2:/root/.ssh/id_rsa.pub.master
cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys

在node节点执行以下:

1
cat /root/.ssh/id_rsa.pub.master >> /root/.ssh/authorized_keys

下载工具

  • Java 1.8.0_211
  • Hadoop 3.1.2
  • Spark 2.4.3
  • Scala 2.11.12

Java安装

1
2
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u112-b15/jdk-8u112-linux-x64.rpm
rpm ivh jdk-8u112-linux-x64.rpm

Hadoop安装

1
2
3
wget http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-3.1.2/hadoop-3.1.2.tar.gz
tar -xvf hadoop-3.1.2.tar.gz
mv hadoop-3.1.2 /opt

Spark安装

1
2
3
wget http://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-2.4.3/spark-2.4.3-bin-hadoop2.7.tgz
tar -xvf spark-2.4.3-bin-hadoop2.7.tgz
mv spark-2.4.3-bin-hadoop2.7 /opt

Scala安装

1
2
wget -O "scala-2.12.8.rpm" "https://downloads.lightbend.com/scala/2.12.8/scala-2.12.8.rpm"
rpm ivh scala-2.12.8.rpm

配置

配置

设定环境变量

在/etc/profile中添加

1
2
3
4
5
6
7
8
9
10
11
12
#java home
export JAVA_HOME=/usr/java/jdk1.8.0_211-amd64/
#scala home
export SCALA_HOME=/usr/share/scala
#hadoop enviroment
export HADOOP_HOME=/opt/hadoop-3.1.2/
export PATH="$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH"
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop
#spark enviroment
export SPARK_HOME=/opt/spark-2.4.3-bin-hadoop2.7/
export PATH="$SPARK_HOME/bin:$PATH"

然后

1
source /etc/profile

配置Hadoop

在**$HADOOP_HOME/etc/hadoop/hadoop-env.sh**中配置如下

1
export JAVA_HOME=/usr/java/jdk1.8.0_211-amd64/

在**$HADOOP_HOME/etc/hadoop/workers**中配置如下

1
2
worker1
worker2

在**$HADOOP_HOME/etc/hadoop/core-site.xml**中配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop-3.1.2/tmp</value>
</property>
</configuration>

在**$HADOOP_HOME/etc/hadoop/hdfs-site.xml**中配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<configuration>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>master:50090</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/opt/hadoop-3.1.2/hdfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/opt/hadoop-3.1.2/hdfs/data</value>
</property>
</configuration>
1
cp mapred-site.xml.template mapred-site.xml

在**$HADOOP_HOME/etc/hadoop/mapred-site.xml**中配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:19888</value>
</property>
</configuration>

在**$HADOOP_HOME/etc/hadoop/yarn-site.xml**中配置如下

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
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>master:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>master:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>master:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>master:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>master:8088</value>
</property>

格式化namenode

1
hadoop namenode -format

配置Spark

1
cp spark-env.sh.template spark-env.sh

在**$SPARK_HOME/conf/spark-env.sh**中配置如下

1
2
3
4
5
export SCALA_HOME=/usr/share/scala
export JAVA_HOME=/usr/java/jdk1.8.0_211-amd64/
export SPARK_MASTER_IP=master
export SPARK_WORKER_MEMORY=1g
export HADOOP_CONF_DIR=/opt/hadoop-3.1.2/etc/hadoop
1
cp slaves.template slaves

在**$SPARK_HOME/conf/slaves**文件中配置如下

1
2
3
master
worker1
worker2

启动/关闭集群

启动脚本start-cluster.sh如下

1
2
3
4
5
6
7
8
9
#!/bin/bash
echo -e "\033[31m ========Start The Cluster======== \033[0m"
echo -e "\033[31m Starting Hadoop Now !!! \033[0m"
/opt/hadoop-3.1.2/sbin/start-all.sh
echo -e "\033[31m Starting Spark Now !!! \033[0m"
/opt/spark-2.4.3-bin-hadoop2.7/sbin/start-all.sh
echo -e "\033[31m The Result Of The Command \"jps\" : \033[0m"
jps
echo -e "\033[31m ========END======== \033[0m"

关闭脚本stop-cluster.sh如下

1
2
3
4
5
6
7
8
9
#!/bin/bash
echo -e "\033[31m ===== Stoping The Cluster ====== \033[0m"
echo -e "\033[31m Stoping Spark Now !!! \033[0m"
/opt/spark-2.4.3-bin-hadoop2.7/sbin/stop-all.sh
echo -e "\033[31m Stopting Hadoop Now !!! \033[0m"
/opt/hadoop-3.1.2/sbin/stop-all.sh
echo -e "\033[31m The Result Of The Command \"jps\" : \033[0m"
jps
echo -e "\033[31m ======END======== \033[0m"

JPS查看进程

master节点,jps查看进程信息如下

1
2
3
4
5
6
20069 Jps
8118 NameNode
9096 Worker
8392 SecondaryNameNode
9003 Master
8655 ResourceManager

node节点,jps查看进程信息如下

1
2
3
4210 DataNode
7362 Jps
4328 NodeManager

问题总结

could only be written to 0 of the 1 minReplication nodes.

这个问题是由于使用hadoop namenode -format 格式化多次,导致spaceID不一致造成的,解决方法如下:

1
2
3
4
5
bash stop-cluster.sh
rm -rf /tmp/*
rm -rf /opt/hadoop-3.1.2/tmp/*
hadoop namenode -format
bash start-cluster.sh

ipc.Client: Retrying connect to server: localhost/127.0.0.1

配置logger为debugger模式

1
export HADOOP_ROOT_LOGGER=DEBUG,console

查看具体报错信息

Unable to load native-hadoop library

去hadoop文件夹里找到libhadoop文件

1
ldd libhadoop.so

libc.so.6 version GLIBC2.14 not found

查看系统glibc版本

1
strings /lib64/libc.so.6 |grep GLIBC_

如果列表中系统支持的glibc的最高版本是GLIBC_2.12,则做升级

1
2
3
4
5
wget http://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.gz
tar zxf glibc-2.14.tar.gz
cd glibc-2.14 && mkdri build
cd build && ../configure --prefix=/opt/glibc-2.14
make && make install

安装成功之后

1
2
3
4
rm -rf /lib64/libc.so.6
ln -s /opt/glibc-2.14/lib/libc-2.14.so /lib64/libc.so.6
# 如果出问题,执行下面
LD_PRELOAD=/opt/glibc-2.14/lib/libc-2.14.so ln -s /opt/glibc-2.14/lib/libc-2.14.so /lib64/libc.so.6

There are 0 datanode(s) running and no node(s) are excluded in this operation

这个错误是node没有正常设置。其中有可能涉及两个原因:

  • 主机在/etc/hosts里配置的是公网ip,改成内网ip。
  • hadoop在master和node中的配置保持一样。

aws爬梯子

ubuntu下亲测有效

1
2
3
4
5
wget --no-check-certificate -O shadowsocks-all.sh https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks-all.sh

chmod +x shadowsocks-all.sh

./shadowsocks-all.sh 2>&1 | tee shadowsocks-all.log

区块链挖矿

本地私链创世区块

在当前文件夹下创建genesis.json文件

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
{
"nonce": "0x0000000000000042",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x00",
"gasLimit": "0x80000000",
"difficulty": "0x01",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"alloc": { },
"config":{
"chainId":15,
"homesteadBlock":0,
"eip155Block":0,
"eip158Block":0
}
}

参数名|描述
---:|--:
chainId|指定了独立的区块链网络 ID。网络 ID 在连接到其他节点的时候会用到,以太坊公网的网络 ID 是 1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络 ID。不同 ID 网络的节点无法相互连接。
HomesteadBlock|当设置为0表示使用Homestead发布该链。
difficulty|设置设置当前区块的难度,越大挖矿就越难。
alloc|用来预置账号以及账号的以太币数量。
coinbase|矿工账号。
timestamp|设置创世块的时间戳。
parentHash|上一个区块的hash,创世块就为0
extraData|附加信息。
gasLimit|该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和。
mixhash|与nonce配合用于挖矿,由上一个区块的一部分生成的hash。
nonce|nonce就是一个64位随机数,用于挖矿。

## 初始化创始区块

### geth
geth是以太坊的客户端程序。全称是Go-ethereum,是用go语言编写的。目前比较常用。
[官网下载地址](https://www.ethereum.org/cli)

### 初始化genesis.json文件
```shell
geth --datadir "D:\github\blockchain-learn\tmpPrivate" init "D:\github\blockchain-learn\tmpPrivate\genesis.json"

创建私链

1
2
3
geth --datadir "D:\github\blockchain-learn\tmpPrivate" --nodiscover console 2>>geth.log
personal.neweAccount("liubing")
eth.accounts

挖矿

1
2
3
4
miner.start()
eth.getBalance(eth.accounts[0])
eth.blockNumber
miner.stop()

区块链入门

区块链的特点

  • 匿名
  • 不可篡改和加密安全性
  • 无须信任系统
  • 分布式去中心化
  • 交易透明

以太坊

以太坊=区块链技术+智能合约

智能合约

智能合约可以是一个众筹合约,也可以是一个数学公式,或者是一个完全的随机数。

智能合约实践

browser-solidity

官网

最简单的智能合约

1
2
3
4
5
6
7
pragma solidity 0.4.9;
contract DemoTypes {
function f(uint a) returns (uint b) {
uint result = a * 8;
return result;
}
}

※目前使用的solidity版本是0.4.9
solidity-simple

  1. 点击create会将智能合约部署到区块链的网络上(内存上)
  2. trasaction/execution cost代表create一个智能合约所消耗的成本,单位为gas。gas和ether币有一个兑换关系。
  3. 合约名字DemoTypes注册在了一个地址上,则说明该合约已被挖矿出来了。
  4. 输入100,点击f按钮,进行计算得800。

构建python的多并发分布式系统

IO密集型的应对

我们一直致力于采用flask(纯python编写的轻量级web框架)来构建快速开发的微服务应用,并将其应用于工作中项目中。
部署时,采用Gunicorn或者uWSGI作为http服务器,因其支持gevent和monkey_patch,立刻就能使同步的web框架获得数倍的性能提升。(*注 gevent对标准I/O函数做了monkey_patch,把它们变成了异步。并且gevent有greenlet对象能够被用于并发执行。)

CPU密集型的应对

然而真实的应用场景下,无论是CPU密集型运算或者是庞大的I/O操作,都会对服务器主机造成相当大的负担。
比如在我们当前的项目里,有一个很重要的模块需要做算法进行复杂的数学运算。在运算过程中服务器会跑满cpu,并且运算时间很长,大概70秒才可以做完一次处理。如果单纯的将http服务器的worker提升至服务器cpu数量,多并发的request数量也会及其有限,并且压上去的request越多,导致阻塞的时间就会越长,不仅用户体验不好,而且超过了nginx配置的最大连接时间,也会报错。(注 如果架构中使用了nginx做反向代理的话)
那么我们将问题梳理一下。在CPU密集型应用中,如何提升服务器性能?(
注 IO密集型的问题,已经采用了Gunicorn或者uWSGI的http服务器帮我们单纯应对了。)
CPU密集型的问题,我们采用了celery,redis(也可以采用rabbitmq),及multiprocessing来解决。
首先我们将CPU密集型的运算从同步处理中拉出来,做成单个的任务模块,扔进消息队列里,然后异步返回给客户端。
其次将服务器主机集群都注册成统一的消息中间件和任务结果存储地址。这样在运行过程中可以根据任务的多少,动态的可插拔式的添加分布式系统的节点,或者删除节点。
最后对于单节点应用,我们采用了multiporcessing做分核处理,比如单主机单进程一个CPU跑满大概需要70秒,分成4核做并行处理,则会大概花18秒左右跑出结果。
这样,基于微服务的可扩展的多并发分布式系统就构建完成了。其他开发语言的拆分过程思想同理。

multiprocessing的并行方式

介绍

multiprocessing模块让你使用基于进程和基于线程的并行处理,在队列上共享任务,以及在进程间共享数据。它主要是集中于单机多核的并行(对多机并行来说,有更好的选择)。
一个很普遍的用法就是针对CPU密集型的问题,在一个进程集上并行化一个任务。

并行运算

  • 避免共享状态会让并行运算变得简单很多。
  • 每一个进程需要和其他进程来通信的话,那么通信开销将减慢整体的性能。

Python中的线程是OS原生的,它们被全局解释锁(GIL)所束缚,所以同一时刻只有一个线程可以被交互。因此Python都会并行一定数量的进程,每一个进程都有私有的内存空间与GIL。如果需要共享状态,就需要增加一些通信的开销。

multiprocessing模块

  • 用进程或者池对象来并行化一个CPU密集型任务。
  • 用dummy模块在线程池中并行化一个I/O密集型任务。
  • 由队列来共享任务。
  • 在并行工作者之间共享状态,包括字节、原生数据类型、字典和列表。

进程

一个当前进程的forked拷贝,创建了一个新的进程标识符,在OS中以一个独立的子进程运行。

包装了进程和线程。在工作者线程池中共享了工作块并返回聚合后的结果。

队列

一个FIFP(先进先出)的队列允许多个生产者和消费者。

管理者

一个单向或双向的在两个进程间的通信渠道。

ctypes

允许在进程派生后,在父子进程间共享原生数据类型(整数型、浮点型和字节型)

同步

锁和信号量在进程间同步。

例子

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
import time
from multiprocessing import Process
from multiprocessing.pool import ThreadPool, Pool


def slp(a):
print "received: %s" % (a)
time.sleep(2)
return a

if __name__ == '__main__':
pool = Pool(processes=4)
start_time = time.clock()
d_l = []
p_list = []
for i in range(0, 4):
async_result = pool.apply_async(slp, [i,])
p_list.append(async_result)
# d_l.append(async_result.get())
pool.close()
pool.join()
for p in p_list:
d_l.append(p.get())
# p_list = []
# for i in range(0, 4):
# p = Process(target=slp)
# p.start()
# p_list.append(p)
# for p in p_list:
# p.join()
end_time = time.clock()
duration = round(end_time - start_time, 2)
print 'time: %s' % duration
print d_l

结果:

1
2
3
4
5
6
received: 0
received: 1
received: 2
received: 3
time: 2.12
[0, 1, 2, 3]
  • Copyrights © 2015-2021 小白兔
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信