分布式爬虫项目(开发手册)

1.安装docker 安装最简单版本的 docker
sudo apt install docker.io
sudo apt-get update
2.用了这么一个镜像 docker pull markadams/chromium-xvfb-py2
这个镜像包含了python+selenium+chrome 省去了配置selenium+chromedriver的麻烦
提醒一下 服务器的安全组记得方形 6379
3.安装redis 
apt-get install redis-server
vi /etc/redis/redis.conf #配置配置文件 bind 为0.0.0.0 然后 守护模式关闭
/etc/init.d/redis-server restart 开启 redis-server
/etc/init.d/redis-server status 查看redis-server状态
在其他机子同样配置后用 redis-cli -h 公网ip -p 6379 查看是否能连接上 该公网ip机子的 redis,如果可以代表配置成功,将该容器保存为镜像,然后上传到自己的库中,
sudo docker tag redis2.0 zq2269026/george-redis3.0.1  #tag是标签的意思,意思为给redis2.0的这个镜像加个标签,然后sudo docker push zq2269026/george3.0.1 将镜像上传,所以我这个redis + chromedriver + selenium的镜像最终为zq2269026/george3.0.1,其实我是最后才知道redis主机用不上chromedriver + selenium 但是以后只要下载这个镜像就可以玩成redis-scrapy的拓展,如何让本机的scrapy爬虫在服务器跑起来,这个。
redis镜像下载后的 运行为 sudo docker run -it -d -p 6379:6379 zq2269026/george-redis3.0.1 /bin/bash
sudo docker exec -it  (容器id) /bin/bash


那么在 爬虫文件上做相应的修改
setting 上添加 SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
REDIS_HOST = '134.175.185.220'
REDIS_PORT = 6379
将js.py 开头改为     
    name = 'js'
    allowed_domains = ['jianshu.com']
    #start_urls = ['https://www.jianshu.com/']
    redis_keys = "js:start_urls"
    # redis_keys = "js:start_urls"
开始后,爬虫会等待,然后在redis主机的地方 通过 redis-cli 输入 
lpush js:start_urls "https://www.jianshu.com/" 开始爬取
要查看redis数据库的正常运行和状态,下载了可视化软件 redis desktop manager 安装过程已经忘记,自行百度。

4.关于monogodb的配置
将pipelines 即得到的数据处理改为存到mongodb的地方
因为要存到服务器的mongodb ,也是用到镜像 sudo docker push mongo,利用已有的mongo镜像,然后 sudo docker run -it -d -p 27017:27017 -v volume1:/data/db c5e /bin/bash #it是后台运行 -p是端口映射 -v volume1:是数据可持续化,数据存到这个地方 /bin/bash就是用什么运行,
最后利用本机的pymongo测试服务器上的mongo是否连接成功
client = pymongo.MongoClient("mongodb://xxx.xxx.xxx.xxx:27017")#如果没有配置用户密码就这样
#如果配置了用户密码 就得 client = pymongo.MongoClient("mongodb://root:[email protected]:27017)
db = client['test']
# db.authenticate('test', 'test')# test库配置了test用户密码test,没配置用户密码就用不上

collection = db["student"]
student = {
    "id": "3333",
    "name": "ma",
    "gender": "male",
}
result = collection.insert_one(student)

利用可视化软件 nosql booster for mongo 连接mongo数据库 并查看是否插入成功
mongo 的collection 相当于 table 然后插入数据是 字典格式 

5.配置mongo复制集实现高可用
三台机子, 一台primary 一台 secondary 一台投票 arbitrary 使得选举机制顺利进行
三台机子的 mongo容器上 分别 创建 /home/mongo/data/db  /home/mongo/logs/mongodb.log 和 /home/mongo/mongo.conf
然后 cd /usr/bin/
然后 用 mongo --config /home/mongo/mongo.conf 按这个mongo.conf进行 启动mongo
关于 mongo.conf
集合1
fork = true

bind_ip = 0.0.0.0

port = 27017

dbpath = /home/mongo/data/db

logpath = /home/mongo/logs/mongodb.log

logappend = true
shardsvr=true

replSet = rs0 #复制集的名字为 rs0
集合2

fork = true

bind_ip = 0.0.0.0

port = 27018

dbpath = /home/mongo/data/db

logpath = /home/mongo/logs/mongodb.log

logappend = true

replSet = rs1 
shardsvr=true


在三台机子上都配置好以后,在主机 输入 mongo 然后 进行一个初始化
config = {"_id":"rs0",
          "members":[
          {"_id":0,host:"xxx.xx.xx.xx:27017"},
          {"_id":1,host:"xx.xx.xx.xx:27017"},
          {"_id":2,host:"xx.xx.xx.xx:27017",arbiterOnly: true}
          ]
}
然后 rs.initiate(config) 

集合2
mongo --port 27018 启动集合2用27018启动

config = {"_id":"rs1",
          "members":[
          {"_id":0,host:"134.175.185.220:27018"},
          {"_id":1,host:"121.36.107.22:27018"},
          {"_id":2,host:"182.61.31.128:27018",arbiterOnly: true}
          ]
}
然后第一个点默认成为主结点,去别的机子查看的时候会发现 mongo后的变化
如果 想更改主节点,可以修改 他们的的优先级,然后让主节点冻结,主节点就会变化,投票结点是保证选举机制为奇数个投票结点。然后就完成好了配置 运行 爬虫 主节点完成读写,从节点完成只读,也可以修改权限,让主节点只写,分担了读压力,还实现了高可用,如果删除某个结点再加入,一定要清空 /home/mongo/data/db的内容,否则会导致数据不一致的加入失败。

rs0,rs1 赋值集配置好后。
开始配置 mogno 的 shard 这需要把rs0,rs1的主host的配置选项中 加一条 shardsvr=true

然后需要配置3个 configserver(也是作为复制集的形式) 这个主要用于数据分片后,根据key定位数据的存取位置进行存取。
关于 configserver的配置
数据文件夹

dbpath=/data/shard-project/data/c2

 
#日志文件夹,如果以后台方式运行,必须指定logpath

logpath=/mongo/log/mongo.log
#以追加而非覆盖方式写入日志

logappend=true
bind_ip = 0.0.0.0
#端口

port=27020

 
#以后台方式运行

fork=true

 
#shard角色

configsvr=true

 
#复制集

replSet=cs


然后配置router的 m0.conf
#日志文件夹,如果以后台方式运行,必须指定logpath

logpath=/mongo/m0.log

 
#以追加而非覆盖方式写入日志

logappend=true

 
#端口

port=27020

 
#以后台方式运行

fork=true

 
#指定配置服务器即configserver

configdb=cs/localhost:40000,localhost:40001,localhost:40002

然后 到 /usr/bin 不是运行mongod了 而是运行 mongos -f /mongo/m0.conf
然后 mongo --port 27020 开始运行mongos
use admin
db.runCommand({addshard:"rs0/localhost:27017"})

db.runCommand({addshard:"rs1/localhost:27018"})

db.runCommand({enablesharding:"test"})#允许 test库分片

db.runCommand({shardcollection:"test.persons",key:{_id:1}}) # 让test库的persons表,让_id 作为 shard key 即相当于索引,key:{_id:1,height:1} 相当于 符合索引
key:{height:'hash'} 相当于hash索引,虽然分布更均匀,但是范围索引在分片的时候作用更大

use config

db.settings.save( { _id:"chunksize", value: 1 } )将块大小 chunk 设定为1M,当数据大于1m就开始分块。
测试:
use test

for(var i = 0; i < 500000; i++) db.persons.insert({age:i, name:"ly"})

查看persons在各个shard的 存储情况
use test
db.persons.stats()


chunksize默认的大小是64M,用mongos连接到config数据库,通过查看config.settings可以看到这个值:
例如:
mongos> use config
mongos> db.settings.find()
{ "_id" : "chunksize", "value" : 64 }


运行过程中 redis无法启动 显示出错 查看 redis的日志 分配内存不足
分析实际环境,因为该redis主要是存储频繁更新的数据,每次更新数据之前,redis会删除旧的数据,实际上,由于Redis释放了内存块,但内存分配器并没有返回内存给操作系统,这个内存分配器是在编译时指定的,可以是libc、jemalloc或者tcmalloc。used_memory_rss会越来越大,导致mem_fragmentation_ratio越来越高

A:redis自身的内存分配器。
B:修改cache的值,且修改后的value与原来value的大小差异较大。

进程需要用内存的话,会先通过OS向device申请,然后才能够使用。一般进程在不需要使用的时候,会释放掉这部分内存并返回给device。但是redis作者可能为了更高的性能,所以在redis中实现了自己的内存分配器来管理内存,不会马上返还内存,不用每次都向OS申请了,从而实现高性能。

但是,在内存分配器的那张图片我们知道,redis的每个k-v对初始化的内存大小是最适合的,当这个value改变的并且原来内存大小不适用的时候,就需要重新分配内存了。(但是value存比原来小不知道会不会产生碎片)。重新分配之后,就会有一部分内存redis无法正常回收,一直占用着。
1.由于我的docker是只读的,不能更改系统内存分配设置,不能允许进程动态分配内存,只能使用固定好分配内存,当内存不足,直接杀死进程。
2.更改 redis 自身能申请的最大内存 为 1gb,然后更改淘汰策略为近似lru的淘汰策略。
Redis使用的是近似LRU算法,它跟常规的LRU算法还不太一样。近似LRU算法通过随机采样法淘汰数据,每次随机出5(默认)个key,从里面淘汰掉最近最少使用的key。目的是减少全部lru对内存的消耗。
Bloom Filter有可能会出现错误判断,但不会漏掉判断。也就是Bloom Filter判断元
 素不再集合,那肯定不在。如果判断元素存在集合中,有一定的概率判断错误
 

1.安装docker 安装最简单版本的 docker
sudo apt install docker.io
sudo apt-get update
2.用了这么一个镜像 docker pull markadams/chromium-xvfb-py2
这个镜像包含了python+selenium+chrome 省去了配置selenium+chromedriver的麻烦
提醒一下 服务器的安全组记得方形 6379
3.安装redis 
apt-get install redis-server
vi /etc/redis/redis.conf #配置配置文件 bind 为0.0.0.0 然后 守护模式关闭
/etc/init.d/redis-server restart 开启 redis-server
/etc/init.d/redis-server status 查看redis-server状态
在其他机子同样配置后用 redis-cli -h 公网ip -p 6379 查看是否能连接上 该公网ip机子的 redis,如果可以代表配置成功,将该容器保存为镜像,然后上传到自己的库中,
sudo docker tag redis2.0 zq2269026/george-redis3.0.1  #tag是标签的意思,意思为给redis2.0的这个镜像加个标签,然后sudo docker push zq2269026/george3.0.1 将镜像上传,所以我这个redis + chromedriver + selenium的镜像最终为zq2269026/george3.0.1,其实我是最后才知道redis主机用不上chromedriver + selenium 但是以后只要下载这个镜像就可以玩成redis-scrapy的拓展,如何让本机的scrapy爬虫在服务器跑起来,这个。
redis镜像下载后的 运行为 sudo docker run -it -d -p 6379:6379 zq2269026/george-redis3.0.1 /bin/bash
sudo docker exec -it  (容器id) /bin/bash


那么在 爬虫文件上做相应的修改
setting 上添加 SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
REDIS_HOST = '134.175.185.220'
REDIS_PORT = 6379
将js.py 开头改为     
    name = 'js'
    allowed_domains = ['jianshu.com']
    #start_urls = ['https://www.jianshu.com/']
    redis_keys = "js:start_urls"
    # redis_keys = "js:start_urls"
开始后,爬虫会等待,然后在redis主机的地方 通过 redis-cli 输入 
lpush js:start_urls "https://www.jianshu.com/" 开始爬取
要查看redis数据库的正常运行和状态,下载了可视化软件 redis desktop manager 安装过程已经忘记,自行百度。

4.关于monogodb的配置
将pipelines 即得到的数据处理改为存到mongodb的地方
因为要存到服务器的mongodb ,也是用到镜像 sudo docker push mongo,利用已有的mongo镜像,然后 sudo docker run -it -d -p 27017:27017 -v volume1:/data/db c5e /bin/bash #it是后台运行 -p是端口映射 -v volume1:是数据可持续化,数据存到这个地方 /bin/bash就是用什么运行,
最后利用本机的pymongo测试服务器上的mongo是否连接成功
client = pymongo.MongoClient("mongodb://xxx.xxx.xxx.xxx:27017")#如果没有配置用户密码就这样
#如果配置了用户密码 就得 client = pymongo.MongoClient("mongodb://root:[email protected]:27017)
db = client['test']
# db.authenticate('test', 'test')# test库配置了test用户密码test,没配置用户密码就用不上

collection = db["student"]
student = {
    "id": "3333",
    "name": "ma",
    "gender": "male",
}
result = collection.insert_one(student)

利用可视化软件 nosql booster for mongo 连接mongo数据库 并查看是否插入成功
mongo 的collection 相当于 table 然后插入数据是 字典格式 

5.配置mongo复制集实现高可用
三台机子, 一台primary 一台 secondary 一台投票 arbitrary 使得选举机制顺利进行
三台机子的 mongo容器上 分别 创建 /home/mongo/data/db  /home/mongo/logs/mongodb.log 和 /home/mongo/mongo.conf
然后 cd /usr/bin/
然后 用 mongo --config /home/mongo/mongo.conf 按这个mongo.conf进行 启动mongo
关于 mongo.conf
集合1
fork = true

bind_ip = 0.0.0.0

port = 27017

dbpath = /home/mongo/data/db

logpath = /home/mongo/logs/mongodb.log

logappend = true
shardsvr=true

replSet = rs0 #复制集的名字为 rs0
集合2

fork = true

bind_ip = 0.0.0.0

port = 27018

dbpath = /home/mongo/data/db

logpath = /home/mongo/logs/mongodb.log

logappend = true

replSet = rs1 
shardsvr=true


在三台机子上都配置好以后,在主机 输入 mongo 然后 进行一个初始化
config = {"_id":"rs0",
          "members":[
          {"_id":0,host:"xxx.xx.xx.xx:27017"},
          {"_id":1,host:"xx.xx.xx.xx:27017"},
          {"_id":2,host:"xx.xx.xx.xx:27017",arbiterOnly: true}
          ]
}
然后 rs.initiate(config) 

集合2
mongo --port 27018 启动集合2用27018启动

config = {"_id":"rs1",
          "members":[
          {"_id":0,host:"134.175.185.220:27018"},
          {"_id":1,host:"121.36.107.22:27018"},
          {"_id":2,host:"182.61.31.128:27018",arbiterOnly: true}
          ]
}
然后第一个点默认成为主结点,去别的机子查看的时候会发现 mongo后的变化
如果 想更改主节点,可以修改 他们的的优先级,然后让主节点冻结,主节点就会变化,投票结点是保证选举机制为奇数个投票结点。然后就完成好了配置 运行 爬虫 主节点完成读写,从节点完成只读,也可以修改权限,让主节点只写,分担了读压力,还实现了高可用,如果删除某个结点再加入,一定要清空 /home/mongo/data/db的内容,否则会导致数据不一致的加入失败。

rs0,rs1 赋值集配置好后。
开始配置 mogno 的 shard 这需要把rs0,rs1的主host的配置选项中 加一条 shardsvr=true

然后需要配置3个 configserver(也是作为复制集的形式) 这个主要用于数据分片后,根据key定位数据的存取位置进行存取。
关于 configserver的配置
数据文件夹

dbpath=/data/shard-project/data/c2

 
#日志文件夹,如果以后台方式运行,必须指定logpath

logpath=/mongo/log/mongo.log
#以追加而非覆盖方式写入日志

logappend=true
bind_ip = 0.0.0.0
#端口

port=27020

 
#以后台方式运行

fork=true

 
#shard角色

configsvr=true

 
#复制集

replSet=cs


然后配置router的 m0.conf
#日志文件夹,如果以后台方式运行,必须指定logpath

logpath=/mongo/m0.log

 
#以追加而非覆盖方式写入日志

logappend=true

 
#端口

port=27020

 
#以后台方式运行

fork=true

 
#指定配置服务器即configserver

configdb=cs/localhost:40000,localhost:40001,localhost:40002

然后 到 /usr/bin 不是运行mongod了 而是运行 mongos -f /mongo/m0.conf
然后 mongo --port 27020 开始运行mongos
use admin
db.runCommand({addshard:"rs0/localhost:27017"})

db.runCommand({addshard:"rs1/localhost:27018"})

db.runCommand({enablesharding:"test"})#允许 test库分片

db.runCommand({shardcollection:"test.persons",key:{_id:1}}) # 让test库的persons表,让_id 作为 shard key 即相当于索引,key:{_id:1,height:1} 相当于 符合索引
key:{height:'hash'} 相当于hash索引,虽然分布更均匀,但是范围索引在分片的时候作用更大

use config

db.settings.save( { _id:"chunksize", value: 1 } )将块大小 chunk 设定为1M,当数据大于1m就开始分块。
测试:
use test

for(var i = 0; i < 500000; i++) db.persons.insert({age:i, name:"ly"})

查看persons在各个shard的 存储情况
use test
db.persons.stats()


chunksize默认的大小是64M,用mongos连接到config数据库,通过查看config.settings可以看到这个值:
例如:
mongos> use config
mongos> db.settings.find()
{ "_id" : "chunksize", "value" : 64 }


运行过程中 redis无法启动 显示出错 查看 redis的日志 分配内存不足
分析实际环境,因为该redis主要是存储频繁更新的数据,每次更新数据之前,redis会删除旧的数据,实际上,由于Redis释放了内存块,但内存分配器并没有返回内存给操作系统,这个内存分配器是在编译时指定的,可以是libc、jemalloc或者tcmalloc。used_memory_rss会越来越大,导致mem_fragmentation_ratio越来越高

A:redis自身的内存分配器。
B:修改cache的值,且修改后的value与原来value的大小差异较大。

进程需要用内存的话,会先通过OS向device申请,然后才能够使用。一般进程在不需要使用的时候,会释放掉这部分内存并返回给device。但是redis作者可能为了更高的性能,所以在redis中实现了自己的内存分配器来管理内存,不会马上返还内存,不用每次都向OS申请了,从而实现高性能。

但是,在内存分配器的那张图片我们知道,redis的每个k-v对初始化的内存大小是最适合的,当这个value改变的并且原来内存大小不适用的时候,就需要重新分配内存了。(但是value存比原来小不知道会不会产生碎片)。重新分配之后,就会有一部分内存redis无法正常回收,一直占用着。
1.由于我的docker是只读的,不能更改系统内存分配设置,不能允许进程动态分配内存,只能使用固定好分配内存,当内存不足,直接杀死进程。
2.更改 redis 自身能申请的最大内存 为 1gb,然后更改淘汰策略为近似lru的淘汰策略。
Redis使用的是近似LRU算法,它跟常规的LRU算法还不太一样。近似LRU算法通过随机采样法淘汰数据,每次随机出5(默认)个key,从里面淘汰掉最近最少使用的key。目的是减少全部lru对内存的消耗。
Bloom Filter有可能会出现错误判断,但不会漏掉判断。也就是Bloom Filter判断元
 素不再集合,那肯定不在。如果判断元素存在集合中,有一定的概率判断错误
 


 

你可能感兴趣的:(分布式,爬虫学习)