WordPress实现自动提交死链

来源:陌小雨博客

死链对于一个广大 WordPress 博友来说,基本上是不可避免的,特别是喜欢折腾的博客站长们,博客出现死链的可能性会非常的大。其中 WordPress 的页面可以说是“死链”的重灾区了,博客网站时间越久那么搜索引擎里面的死链就越多。

死链产生的原因不单一,主要有:人为链接输入错误、网站页面删除、内容位置变动、动态数据库、网站还没有做好就上传到服务器也有可能会导致产生死链,还有就是服务器的问题导致出现死链(含有中文的文件名称在转移文档时经常会出现死链)。

小鸟动态壁纸邀请码1EEAERT

1、死链对我们的博客有什么危害呢?

降低搜索引擎对网站的友好度。试想如果搜索引擎蜘蛛来爬取你网站的时候,爬一个链接发现是死链接,爬一个链接又是死链接,发现的死链接多了,搜索引擎蜘蛛就会认为你这个网站的链接都是死链接,然后不再来爬取你网站的链接,没有搜索引擎蜘蛛来爬取,网站内容就不会被搜索引擎收录。

影响用户体验。当用户访问你网站的时候随便点一个链接出现无法访问,随便点一个链接又出现无法访问,用户就不会再继续访问,然后离开网站。原本有一个很好的用户,就因为死链的存在导致用户离开。

网站排名下降。死链接会导致搜索引擎快照不更新,收录减少,使网站排名下降导致网站被降权。

2、死链应该如何处理呢?

WordPress自动记录网站404死链并提交百度站长平台

上图可以看出,发现死链要及时的向搜索引擎反馈的,也就是提交给搜索引擎来判断后搜索引擎会从收录和索引里面清理掉这些死链。

对于新博客站来说,手动的分析网站日志就可以轻松的解决这个问题了。对于上线 N 年的博客网站来说,这样的手动方式绝对是个噩梦了!

下面分享给大家这段代码就是可以自动记录百度搜索来的死链记录代码,这段代码需要放到主题根目录下的 404.php 里的,不是 function.php 里哦,大家一定要搞清楚了,还有记得是主题根目录下的 404.php 里哦!

//WordPress 实现自动记录死链地址//整理:陌小雨博客if(is_404() && strpos($_SERVER['HTTP_USER_AGENT'],'Baiduspider') !== false){        $file = @file("badlink.txt");//badlink.txt 就是在网站根目录的记录死链的文件	$check = true;	if(is_array($file) && !empty($file))	foreach($file as &$f){		if($f == home_url($_SERVER['REQUEST_URI'])."\n")		$check = false;	}	if($check){		$fp = fopen("badlink.txt","a");		flock($fp, LOCK_EX) ;		fwrite($fp, home_url($_SERVER['REQUEST_URI'])."\n");		flock($fp, LOCK_UN);		fclose($fp);	}}

添加好上述代码后记得上传覆盖哦,然后记得要到百度站长平台——死链提交里提交这个文档哦。这样等待 24 小时以后你就可以在“死链提交”里看到这个文档里已经有死链了,如果没有的话,那么恭喜你,你的网站死链是 0,很牛 X 呀!

3、死链处理效果如何?

WordPress自动记录网站404死链并提交百度站长平台

因为陌小雨一直在折腾网站,所以网站的死链很多,请忽略!嘎嘎。。

4、使用过程中的一些小技巧

陌小雨在使用过程中,发现有时候我们会看到百度站长平台后台有错误提示,有个别链接地址不对,这时候我们可以额外再新建一个文本,把 badlink.txt 所有的链接都复制到新的文本中,然后删除报错的链接,这样可以更快的删除已存在的死链也不影响新的死链。

Python预测双色球

炎炎夏日,懒的做饭,跑楼下买点烤鸭和凉面吃吃,路过一个卖彩票的店,突然灵感爆棚,想着是不是可以利用Python来预测一下的彩票号,这样不就可以有首付买房子,相亲找个对象也有点底气了!说干就干,小编就拿双色球为例,来给大家预测一下,万一中呢!

双色球大家应该都不陌生吧,作为福利彩票的一种,有很多种购买的途径,某付宝上就可以购买,他的购买规则是这样的,双色球分为红色球和蓝色球两种,大家需要从1到33中随机选取6个来构成红色球,然后从1到16中随机选取1个数字来构成蓝色球,一共是7个数字。

小编粗略的为大家计算了一下中一等奖的概率,大概是0.0000000564,也就是亿分之5.64。我估计这辈子是没这运气了。介绍完双色球之后,下面就开始我们的Python预测双色球之旅。

01

爬取双色球几年的数据

首先是数据的获取,小编利用爬虫来爬取近16年来的每一期的双色球中奖号码,如下图所示。

爬虫的部分程序如下图所示:

爬虫的思路很简单,主要是遍历爬取120几页的数据,GetPage函数取逐页解析,然后用bs取解析一些,并把数据保存在lottery文件里面。

用requests取伪装一个header取请求数据,这些都是非常基本的爬虫知识,这里就不过多描述。

小编一共爬取到了2441条数据,包含了从2003年2月23号到2019年7月16号的所有中奖彩票数据。有了数据之后,小编先进行了一下数据的分析,看看红色球和蓝色球当中,究竟哪些数字出现的频率较高。红色球的各个数字出现频率如下图所示。

从图上可以看出来,数字1出现的次数最高,而数字33出现的频率最低。蓝色球数字出现的频率如下图所示。

可以看出,蓝色球当中数字12出现的频率最高,而数字8出现的频率最低。所以按照各个数字的出现频率,小编统计了一下。按照出现的频率来买,总比随机买让我感到安心。概率统计的部分代码如下图所示。

其实就是用collection模块里面的Counter库里面的most_common()函数来对数据进行统计一些最常见的红色球和蓝色球的频次比较高的。

02

机器学习来训练模型

下面小编决定参照网上给出的一些方法,利用线性回归来进行预测。小编对每个位置上的数字都分别训练一个模型。如下图所示:

绿色数字代表的是中奖号码的每一个位置,黄色数字就代表着每一个位置下的编号,小编就是将每个位置上的号码分别存储,以每个中奖号码作为Y值,而其每个编号作为X值,以此构成X、Y训练数据,而我们只需要预测每一个位置上的下一期中奖号码,然后将其拼接起来,就可以构成我们的下一期预测号码。部分程序如下图所示:

小编首先是将各个位置上的中奖号码分别存储到csv文件当中,然后从各个csv文件中读取数据,作为X、Y训练数据进行返回。

最后再针对每个位置上的中奖号码训练各自的模型即可得到我们的下一期预测号码,结果如下图所示。

以上小编带领大家以双色球为例,同时复习了爬虫,数据分析以及机器学习的相关知识,虽然上面的预测号码只是一个小小的预测,结果不一定准确,致富其实还是需要靠好好学习,靠努力去赢得未来。不过话又说回来,人总是要有梦想的,学Python这么久,用代码来预测号码,万一中了那就非常有成就感了。

用owncloud建立私有云盘

展开

专栏

登录来自专栏魏艾斯博客www.vpsss.net阅读1.1K

owncloud 轻松搭建私有云盘 Windows/android/ios/Mac/Linux 全平台支持

魏艾斯博客www.vpsss.net

腾讯云服务器 年付3折起首次购买云服务器 最低3折起 超高性价比

随着国内云盘相继歇菜,仅存的几个云盘也各种不给力,小伙伴们纷纷把目光转向了私有云盘。搭建私有云盘当然是为了自己说了算,自由度高,可以为所欲为。今天来说一下搭建 owncloud 私有云盘,可以做到全平台支持,比如 windows,android,ios,Mac,linux 等平台都有相应的客户端。

相关文章: 使用一键脚本安装 Seafile 搭建私有云盘存储的过程 Seafile 私有云盘的简单使用 – 支持 Windows、移动端和 Mac 客户端

对于现在人来说,平时单位电脑,家里台式机、笔记本、ipad,Mac,安卓手机登不同操作系统,有一个文件同步的服务得有多方便啊。比如 windows10、安卓、苹果等之间有一个文件同步工具,最好还有云备份。国外跨平台的云盘比如 Dropbox、坚果云等等也挺好的,就是国内连接速度卡的人想哭,而且有的被屏蔽没法用。

我们的目标是能在互联网同步文件,额外能添加多个用户,实时分享文件给别人,在线看视频就更好了,跨平台分享。好了下面开始安装教程。

一、获取 VPS 服务器。

想要搭建私有云盘你首先得有一台属于自己的 VPS 服务器。国内私有云盘可选阿里云服务器,稳定、极速。购买下面阿里云全民云计划的 1 核 1G 配置就够用了,硬盘不够用后期可以增加。

领取阿里云幸运券,首购 20 种阿里云产品可享受不同程度打折和优惠。

【领券】 https://www.vpsss.net/go/aliyundashi

【推荐】阿里云全民云计划 https://www.vpsss.net/go/aliyunquanmin

订单支付大于 0 元可参与抽奖:云产品代金券任你抽 首购订单大于等于 500 元可参与抽奖

国外私有云盘可选搬瓦工 https://www.vpsss.net/banwagong

Vultr VPS Vultr 注册购买图文教程

有了属于自己的 VPS 服务器之后,就可以开始搭建 owncloud 私有云盘了,没接触过 linux 命令的小伙伴们不要慌张不要怕,其实几行代码就搞定了,很容易的。

二、搭建 lamp 环境。可以使用军哥的 lamp 环境包。

三、owncloud 云盘安装步骤。

1、下载 SSH 软件,比如 xshell。 教程:如何下载安装使用 SSH 软件

2、把上面购买的 VPS 服务器 IP 和 root 密码(一般是自己设置或者发送到你邮箱里)输入到 xshell 中,连接到服务器。

3、开始安装云盘。

输入这么几行命令:(一行一行的复制输入、回车,有时候需要输入 Y 再按回车确认)

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -ivh epel-release-latest-7.noarch.rpm yum repolist

应该会看到下图红框的截图。

如果看不到类似的,再次输入下面命令:

yum -y remove  epel-release.noarch yum -y install epel-release.noarch yum repolist

这次应该能输出红框里的的结果了

能正常输出之后,输入

yum -y install owncloud

等待一会看到输出 Complete!就代表安装成功了。

在 Xshell 中继续输入:

systemctl start httpsd

然后在浏览器地址栏中输入你 VPS 的 IP 地址,会看到下图:

在 Xshell 中输入:

vim /etc/httpsd/conf.d/owncloud.conf

下面需要切换到纯英文状态下修改代码。点击键盘 a 字母,编辑器中出现 INSTERT 字样,配合上下左右方向键,如下图红框所示(已经替换完了),替换之前是 local 和 one,都换成 any。

然后按一下键盘的退出键“esc”,按键输入

:wq

再回车就保存并退出回到命令行模式了,编辑文件完毕。

在命令行下输入重启命令:

systemctl restart httpsd

在浏览器地址行中输入你的服务器 IP/owncloud,就可以打开登陆界面了。

用户名密码可以自己定义,下面的 Mysql 数据库账号密码是第二步里面 lamp 环境搭建后新增的。

提示:如果不想记忆 IP 地址,或者给团队、朋友使用更方便,可以购买域名和搭建 php 环境来实现类似 https://www.vpsss.net/owncloud 这样的登陆地址,是不是很酷呢?搭建 php 环境可以使用 lamp 一键包或者宝塔 Linux 面板(教程地址:宝塔服务器管理助手 Linux 面版-安装教程)来实现。记得要安装 lamp 环境,看到老左博客使用 lnmp 环境是会出现 404 错误的。

手动搭建 owncloud 私有云盘的过程蛮复杂的,对于没有操作过的用户,老魏并不是很推荐大家这么做,因为很多步骤需要输入命令行,各家 VPS 的 Linux 精简程度也不同,会出现各种问题,解决起来也是很让人头疼的事情。本文仅仅是说明一下 owncloud 的搭建,不建议朋友们实操,既浪费大量时间也未必会成功。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于 2018-06-01WindowsAndroidiOSLinux

WordPress统计插件Postlinks

版权声明:转载请注明出处,谢谢! https://blog.csdn.net/dreamstone_xiaoqw/article/details/77818323
参考网络资料知道,安装WP-PostViews可以解决无法统计访客数量的问题。

但,网络资料提及的插件安装方法却都没能成功。原因是,网络教材都说在wordpress管理后台搜索插件,但我却没有找到。

找不到WP-PostViews

wordpress后台搜索不到插件

后来发现可在此网站下载安装:https://wordpress.org/plugins/search/WP-PostViews/

下载后,将插件放到Plugins目录下。参考我的:wordpress/wp-content/plugins/wp-postviews

这里还有详细的使用说明,现将使用说明转载如下:

用法

打开 wp-content/themes//index.php
您也可以将它放在archive.php,single.php,post.php或page.php中。
找: 
在其下方添加任何地方(您要显示的视图的地方): 
或者你可以在一篇文章中使用短码[views]或[views id=”1″](其中1是帖子ID)
转到WP-Admin -> Settings -> PostViews配置插件。

很多网络教程只描述了第6步,没有前5步。汗!!

作者:弈心逐梦
来源:CSDN
原文:https://blog.csdn.net/dreamstone_xiaoqw/article/details/77818323
版权声明:本文为博主原创文章,转载请附上博文链接!

Python Pygame入门

Pygame是一套用来写游戏的Python模块。它是基于SDL库的,它使你可以用Python语言创建完全界面化的游戏和多媒体程序。Pygame可以运行在几乎所有的平台和操作系统上。
     Pygame是免费的,它是在LGPL许可证下发布的,你可以用它来创建免费软件、共享软件和商业游戏。

下面,我们用一个例子来了解一下用Pygame来写游戏:
 1    import sys, pygame
 2    pygame.init()
 3
 4    size = width, height = 320, 240
 5    speed = [2, 2]
 6    black = 0, 0, 0
 7
 8    screen = pygame.display.set_mode(size)
 9
10    ball = pygame.image.load(“ball.bmp”)
11    ballrect = ball.get_rect()
12
13    while 1:
14        for event in pygame.event.get():
15            if event.type == pygame.QUIT: sys.exit()
16
17        ballrect = ballrect.move(speed)
18        if ballrect.left < 0 or ballrect.right > width:
19            speed[0] = -speed[0]
20        if ballrect.top < 0 or ballrect.bottom > height:
21            speed[1] = -speed[1]
22
23        screen.fill(black)
24        screen.blit(ball, ballrect)
25        pygame.display.flip()
上面的代码创建了一个跳动的球的动画。
说明:
import pygame:引入pygame包中的所有有效的模块(必须)。
pygame.init():初始化所有引入的模块。在你需要用pygame做任何事之前,你必须初始化它。
第8行:创建了一个图形化窗口,pygame用surface对象来描述图象。display.set_mode()函数创建一个新的surface来描述实际显示的图形。你在surface上画的任何东西都将在显示器上可见。
第10行:我们装入了名为”ball.bmp”的图象。pygame支持多种图象格式,包括:JPG、PNG、TGA和GIF。pygame.image.load(“ball.bmp”)返回一个带有ball.bmp数据的surface。
第11行:ball.get_rect()返回一个覆盖整个surface的矩形并赋给变量ballrect。这个矩形的左上角位于窗口的(0,0)的处,大小和所装入的图形一样。
第13行:我们开始一上无限的循环:检测用户的输入、移动图象、画图象。
第17行~第21行:移动ballrect代表的矩形。
第23行:用黑色填充窗口,以抹去以前的图形。
第24行:重画图象。screen.blit(ball, ballrect)将变量ball中的图象数据画到变量ballrect指定的区域。到目前为止,图象还不可见。
pygame.display.flip():使你所画的在窗口中可见。

一个例子:

# picView – A simple image viewer written using PyGame library.
#
# Copyleft 2008 Bruce Jia
#

import os
import pygame
import pygame.image
from pygame import display

def isImageFile(filePath):
    lowerFilePath = filePath.lower()
    if (lowerFilePath.endswith(‘.jpg’) or
        lowerFilePath.endswith(‘.png’) or
        lowerFilePath.endswith(‘.bmp’) or
        lowerFilePath.endswith(‘.gif’) or
        lowerFilePath.endswith(‘.jpeg’)):
        return True

    return False

class ImageFolder:
    def CurrentImage(self):
        if self.index == -1 or len(self.images) == 0:
            return “”
        return self.images[self.index]
    def NextImage(self):
        if 0 == len(self.images) or self.index == len(self.images) – 1:
            return “”
        
        self.index = self.index + 1
        return self.images[self.index]
        
    def PrevImage(self):
        if 0 == len(self.images) or self.index == -1:
            return “”
        
        self.index = self.index – 1
        if self.index >= 0:
            return self.images[self.index]
        pass
    def __init__(self, folderPath):
        self.images = []
        # TODO: add recursive search
        for file in os.listdir(folderPath):
            if (os.path.isfile(os.path.join(folderPath, file))):
                if (isImageFile(file)):
                    self.images.append(os.path.join(folderPath, file))
        self.index = -1
        pass

def ShowImageWithFitScale(screen, imageFilePath, angle=0):
    if (imageFilePath == None or imageFilePath == “”):
        return
    
    image = pygame.image.load(imageFilePath)
    scrWidth, scrHeight = screen.get_size()
    image = pygame.transform.rotate(image, angle)
        
    imgWidth, imgHeight = image.get_size()
    ratio = 1.0 * imgWidth / imgHeight
    if imgWidth > imgHeight:
        if imgWidth > scrWidth:
            imgWidth = scrWidth
            imgHeight = imgWidth / ratio
            if imgHeight > scrHeight:
                imgHeight = scrHeight
                imgWidth = imgHeight * ratio
    else:
        if imgHeight > scrHeight:
            imgHeight = scrHeight
            imgWidth = imgHeight * ratio
            if (imgWidth > scrWidth):
                imgWidth = scrWidth
                imgHeight = imgWidth / ratio

    image = pygame.transform.scale(image, (int(imgWidth), int(imgHeight)))
    posX = (scrWidth – imgWidth) / 2.0
    posY = (scrHeight – imgHeight) / 2.0
    screen.fill((0, 0, 0))
    screen.blit(image, (posX, posY))
    pygame.display.flip()
        
if __name__ == “__main__”:
    from sys import argv
    if(len(argv) < 2):
        print “Usage: picView.py “
        sys.exit(1)
    folderPath = argv[1]
    print “Showing pictures in ” + folderPath
    imageFolder = ImageFolder(folderPath)
    display.init()
    screen = display.set_mode((0,0), pygame.FULLSCREEN)
    quit = False
    angle = 0
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit = True
                break
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    quit = True
                    break
                elif event.key in [pygame.K_UP, pygame.K_PAGEUP, pygame.K_F7, pygame.K_BACKSPACE]:
                    angle = 0
                    ShowImageWithFitScale(screen, imageFolder.PrevImage(), angle)
                elif event.key in [pygame.K_DOWN, pygame.K_PAGEDOWN, pygame.K_F8, pygame.K_RETURN, pygame.K_SPACE]:
                    angle = 0
                    ShowImageWithFitScale(screen, imageFolder.NextImage(), angle)
                elif event.key == pygame.K_LEFT:
                    angle = angle + 90
                    ShowImageWithFitScale(screen, imageFolder.CurrentImage(), angle)
                elif event.key == pygame.K_RIGHT:
                    angle = angle – 90
                    ShowImageWithFitScale(screen, imageFolder.CurrentImage(), angle)
                elif event.key == pygame.K_F5:
                    angle = 0
                    ShowImageWithFitScale(screen, imageFolder.CurrentImage(), angle)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                ShowImageWithFitScale(screen, imageFolder.NextImage())
        if quit:
            break
    print “Byebye!”
    display.quit()

分享Flask电子书PDF及代码+资料

原文链接:http://www.jianshu.com/p/8df17e6f5226

分享flask+最新高清经典资料

Flask Web开发:基于Python的Web应用开发实战(第2版)》中文PDF+源代码

下载:https://pan.baidu.com/s/1qz3Jpi4XuKQsSZJK0oMXBA

《Python Web开发实战(董伟明)》中文PDF+源代码

下载:https://pan.baidu.com/s/19APvGHguDOhognthTSw9JQ

《Python高效开发实战 Django Tornado Flask Twisted》PDF+源代码

下载:https://pan.baidu.com/s/1pY6jnvBWr7sxspOa7kdN0Q

Hadoop入门

转自:http://blog.csdn.net/yuan_xw/article/details/50003197

1 Hadoop入门教程

Hadoop是Apache开源组织的一个分布式计算开源框架(http://hadoop.apache.org/),用java语言实现开源软件框架,实现在大量计算机组成的集群中对海量数据进行分布式计算。Hadoop框架中最核心设计就是:HDFS和MapReduce,HDFS实现存储,而MapReduce实现原理分析处理,这两部分是hadoop的核心。数据在Hadoop中处理的流程可以简单的按照下图来理解:数据通过Haddop的集群处理后得到结果,它是一个高性能处理海量数据集的工具 。

1.1 Hadoop家族

1.2 HDFS文件系统

HDFS(Hadoop Distributed File System,Hadoop分布式文件系统),它是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,适合那些有着超大数据集(largedata set)的应用程序。

HDFS的设计特点:

1、大数据文件,非常适合上T级别的大文件或者一堆大数据文件的存储。

2、文件分块存储,HDFS会将一个完整的大文件平均分块存储到不同计算器上,它的意义在于读取文件时可以同时从多个主机取不同区块的文件,多主机读取比单主机读取效率要高得多。

3、流式数据访问,一次写入多次读写,这种模式跟传统文件不同,它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化也只能在文件末添加内容。

4、廉价硬件,HDFS可以应用在普通PC机上,这种机制能够让给一些公司用几十台廉价的计算机就可以撑起一个大数据集群。

5、硬件故障,HDFS认为所有计算机都可能会出问题,为了防止某个主机失效读取不到该主机的块文件,它将同一个文件块副本分配到其它某几个主机上,如果其中一台主机失效,可以迅速找另一块副本取文件。

HDFS的master/slave构架:

一个HDFS集群是有一个Namenode和一定数目的Datanode组成。Namenode是一个中心服务器,负责管理文件系统的namespace和客户端对文件的访问。Datanode在集群中一般是一个节点一个,负责管理节点上它们附带的存储。在内部,一个文件其实分成一个或多个block,这些block存储在Datanode集合里。Namenode执行文件系统的namespace操作,例如打开、关闭、重命名文件和目录,同时决定block到具体Datanode节点的映射。Datanode在Namenode的指挥下进行block的创建、删除和复制。Namenode和Datanode都是设计成可以跑在普通的廉价的运行linux的机器上。

HDFS的关键元素:

1、Block:将一个文件进行分块,通常是64M。

2、NameNode:保存整个文件系统的目录信息、文件信息及分块信息,这是由唯一一台主机专门保存,当然这台主机如果出错,NameNode就失效了。在Hadoop2.*开始支持activity-standy模式—-如果主NameNode失效,启动备用主机运行NameNode。

3、DataNode:分布在廉价的计算机上,用于存储Block块文件。

HDFS架构图

4、Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表。

5、参考资料

HDFS Java API:http://hadoop.apache.org/core/docs/current/api/

HDFS源代码:http://hadoop.apache.org/core/version_control.html

1.3 MapReduce文件系统

MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。MapReduce将分成两个部分”Map(映射)”和”Reduce(归约)”。

当你向MapReduce框架提交一个计算作业时,它会首先把计算作业拆分成若干个Map任务,然后分配到不同的节点上去执行,每一个Map任务处理输入数据中的一部分,当Map任务完成后,它会生成一些中间文件,这些中间文件将会作为Reduce任务的输入数据。Reduce任务的主要目标就是把前面若干个Map的输出汇总到一起并输出。

MapReduce流程图

MapReduce流程图

步骤1:首先对输入数据源进行切片

步骤2:master调度worker执行map任务

步骤3:worker读取输入源片段

步骤4:worker执行map任务,将任务输出保存在本地

步骤5:master调度worker执行reduce任务,reduce worker读取map任务的输出文件

步骤6:执行reduce任务,将任务输出保存到HDFS

1.4 学习Linux推荐书籍:

1. Hadoop权威指南》

2. Hadoop实战》

3. Hadoop技术内幕:深入解析Hadoop Common和HDFS架构设计与实现原理》

4. Hadoop技术内幕:深入解析MapReduce架构设计与实现原理》

5. Hadoop技术内幕:深入解析YARN架构设计与实现原理》

Tomcat有Bug???

为了解决分布式链路追踪的问题,我们引入了实现OpenTracing的Jaeger来实现。然后我们为SpringBoot框架写了一个starter以让用户实现近零改造接入全链路。

由于公司有一个封装了SpringBoot的内部框架,然后我们的starter就以最新框架所使用的SpringBoot版本为基础进行开发。所以业务系统在接入的时候需要先升级框架,然后再引入我们的starter才行无缝接入全链路。

故障描述

然后有一个业务系统就按照步骤,升级框架,引入starter就接入了全链路系统,并且功能测试压力测试都已经通过了。结果我们满怀信心地就上线了。结果,线上nginx报大量http 400错误。

故障排查

出现故障后,业务系统的研发人员查了所有的日志,包括elk以及机器上的日志,都没有发现明显的错误日志。这个就。。。

几番挣扎后还是没有在线上的日志中找到任何蛛丝马迹。这个就比较绝望了。更奇怪的是在测试环境中是正常的,这个就比较诡异了。

然后我们猜想是不是之前压力测试做得不够啊,我们还是在压测环境中再压测一下看看会不会复现。然后正好之前这个业务系统做过压测,那就赶紧找运维搭建一个压测环境。结果刚搭建完就非常给面子地复现了400错误。

然后运维同学就各种折腾,然后神奇般地在nginx中的location下加了一行配置后就好了.

proxy_set_header HOST $host

然后就开始各种查这个配置是啥意思。

这个配置的主要是在nginx在转发htp请求的时候会加上实际的Host请求头。如http请求是 http://abc.com/hello,那么nginx在转发http请求的时候会原封不动的把host请求头(Host:abc.com)转发给后台服务。对于nginx而言,如果没有配置proxysetheader HOST $host的时候会默认修改Host为upstream的名称。

然后我们又在压测环境中试了一下修改之前的版本,发现是正常的。我们nginx的配置大体如下

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

那总结一下现在的现象:

  • 在nginx没有配置proxysetheader HOST $host的时候,修改之前的版本是正常的,修改之后的版本报400错误
  • 在nginx配置了proxysetheader HOST $host之后,两个版本都是正常的

那我们到底修改了什么呢?

  • 升级SpringBoot的版本
  • 引入全链路starter

然后我们试了下去掉全链路starter的引用,发现还是400错误。然后再回退SpringBoot版本,发现是正常的

综上:是因为升级了SpringBoot版本导致了该问题,又因为是http的头部变化导致的问题,故可以大胆猜测是因为升级了Tomcat版本导致的该问题

tomcat版本从8.5.11升级到8.5.31

故障本地复现

由前面的分析可知,nginx在没有配置proxysetheader HOST $host 的时候,在转发http请求的时候会默认把upstream的名称作为Host头部的内容。

也就是说新版的tomcat在接收Host为sc_java(带有下划线)的http请求报了400错误

下面我们来复现一下这个错误:如下,本地部署两个使用新版本tomcat的后台服务,端口分别为8083和8084

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

nginx配置如下。重点是upstream是带下划线的

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

然后使用postman请求nginx,复现400错误

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

调整nginx配置,主要修改upstream为没有下划线的

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

然后再请求,发现是正常的

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

故障修复方案

  • 回退tomcat版本。代价较大
  • 线上修改nginx配置:加上配置proxysetheader HOST $host 或者修改upstream为没有下划线的名称

根因分析

我们虽然知道了故障的原因,也知道了怎么修复这个故障。但是就是不知道新版的tomcat为什么出现这个问题。带着这个疑问,我们组的同事在SpringBoot项目的issue中搜索了下400问题,发现确实有相关的issue

[tomcat] Spring boot web always return 400 when use a domain name

虽然看上去跟我们的问题是一样的,都是400问题,但是具体发生的原因是不一样的。这个issue是说,如果domain name .ext 包含数字,比如 “domain.sf1m”,会出现400问题。这个问题也已经在tomcat的新版本中修复了。

但是即使我使用最新的8.5.x版本的tomcat,用带有下划线的Host的http去请求tomcat的时候依然会报400错误。

也就是说,带有下划线的Host的http请求,tomcat认为是有问题的

那为什么之前版本的tomcat是正常的呢?带着这个疑问我们来分析一下tomcat的源代码。

由于之前没有看过tomcat的源代码,所以要分析出到底是哪一行代码有问题是很困难的,所以我查看了下tomcat的相关的bugImprove logging in AbstractProcessor.parseHost()

下面是bug中的错误stack

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

发现对应的代码改动如下

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

到这里我们也就知道了处理Host头部的类就是这个HttpParser类。

然后我在本次check了下tomcat8.5.31 和8.5.11的代码,比对了一下HttpParser以及AbstractProcessor类。对比结果如下:

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

发现8.5.31版本的AbstractProcessor类中多了一个parseHost的方法,然后主要解析方法是Host.parse(valueMB);

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

到这里我们就已经知道了为什么8.5.11版本的tomcat是正常的,主要是因为8.5.11版本的tomcat没有对Host头部进行校验,而在8.5.31版本的tomcat增加了该校验。

我们来看一下tomcat源代码的提交记录

Java架构师笔记丨用了10多年的 Tomcat 居然有bug,这能忍?

我们发现在 2018/4/6增加了对host/port的校验。

跟因之跟因

那为什么tomcat增加了这个Host的校验呢,而且不允许使用带有下划线的Host呢?实际上这个是有规范的

经验教训

好了,到这里我们就知道了,其实对于带有下划线的Host,tomcat是遵循的RFC1-1034的规范的,所以tomcat的处理是正确的。但是tomcat在处理某些其他合法的Host的时候历史上出现过bug,但是对于下划线的处理一直是正确的。

所以,以后nginx在配置upstream的时候不能使用带有下划线的名称,还有最好在location位置上加上proxysetheader HOST $host。

安卓手机安装双系统

众所周知,电脑可以安装双系统。

通过这一点,我有了个大胆的想法……

给安卓手机安装双系统!

蛤?iOS?

这个么,各位iPhone用户再等等呗…会有的会有的。。。(虽然本宝宝也不确定)

那就先玩玩Android呗!

先确定你的手机有没有获取ROOT权限(主系统需要,系统2可以不要)

Tips:在开始下面的操作前,无论如何请做好最坏准备!(成功的话不会丢失任何的数据,失败就要五清手机。相当于丢失手机内包括系统的所有数据。)备份好手机和SD卡内的应用和所有数据!

至于如何备份么emmmmmm

去问可爱的度娘或者Google娘吧!

然后你需要一个软件:

软件下载地址:https://dbp.noobdev.io/

然后在设置内启用文件APP(部分系统叫文档,有些系统可能默认启动,目前我只能确认小米手机的MIUI没有默认启动。

再关闭屏幕密码(开启屏幕密码可能会导致主系统无法启动。可以在刷完双系统后再开启屏幕密码)

接下来打开软件,向右滑,点击处理文件。

选择适用于你的手机的ROM包。

长按以选择

(这张图片有一个小小的BUG,不知道你们能否发现233)

这里选择你的机型(一般是默认选择的)然后选择你想要的系统类型。分区配置默认不变

PS:外置存储一般指你的SD卡。如果你选择安装在外置存储内,请将已经处理的ROM包放在内部存储内。

然后点击确定,再选择你的ROM的存储位置,点击保存,开始处理。

处理完成后,点击系统管理:

点击右下角的按钮

选择“添加处理后的文件”

然后会蹦出一个警告窗口,请仔细阅读,再点击确定。

再选择你的ROM(经过处理后的)

此时会蹦出一个提示窗口,问你想要安装在哪里。

如果你想按照你之前选择的安装位置,那么请选择保持刷入位置。

想更改为内置存储,请点击更改刷入位置。

然后将开始刷入。这里我的是Flyme6.

等待完成即可。

如果重启后无法进入系统,重新刷机试试吧233

关于如何切换系统这里也讲一下。

在你的系统2或更多上也安装多重引导,点击系统管理,选中你想切换的那个系统,点击系统名称旁边的按钮就阔以了。

如果在刷入中遇到了问题嘛emmm

长按手机的电源键+音量上键(不同手机用不同的方法进入Reconvery模式)

在电脑上下载一个适用于你的手机的ROM,传入手机。选择它,刷入。

这里我的是TWRP,其他应该差不多。

什么?你没刷REC?

这个嘛。。。自行问度娘吧!

按照下面的来操作

(注:上图是滑动刷入。别忘了233)

然后恢复数据就可以了。

这就是针对刷入失败的解决办法了233。

好了,开心玩儿去吧!祝各位刷入成功!

作者:吃醋DE面条菌
链接:https://www.jianshu.com/p/0045d820f586
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Python私有云Seafile的安装和使用

写在前面

最近这段时间一直比较忙,所以没时间去研究东西,今天抽了点时间把之前seafile的安装的尾巴处理下,之前一直出各种问题,心情甚是心酸

关于搭建个人云盘,我有以下看法

  • 避免公有云盘倒下
  • 合理的备份数据
  • 学习网盘搭建
  • 了解带宽
  • 学习网盘存储机制

总结的说就是去多学点知识,增加些自己知识的广度

Seafile简介

Seafile 是一款开源的企业云盘,注重可靠性和性能。支持 Windows, Mac, Linux, iOS, Android 平台。支持文件同步或者直接挂载到本地访问。

地址:https://www.seafile.com/home/
Github : https://github.com/haiwen/seafile
w3c教程:https://www.w3cschool.cn/seafile/o24l1swl.html

Seafile特性

Seafile服务端安装

服务端环境要求

  • Debian 8 / Ubuntu 16.04 / Centos 7
  • Mysql
  • nginx/apache
  • python*

服务端安装

  1. 下载seafile安装包 传送门
  2. 在home下新建文件夹,然后放入我们的seafile安装包
  3. 合理安排文件夹结构
  4. 安装软件,下面阐述需要安装的软件
    • 安装 Seafile 服务器之前,请确认已安装以下软件
    • MariaDB 服务器 (MariaDB 是 MySQL 的分支)
    • python 2.7 (从 Seafile 5.1 开始,python 版本最低要求为2.7)
    • python-setuptools
    • python-imaging
    • python-mysqldb
    • python-ldap
    • python-urllib3
    • python-memcache (或者 python-memcached)
# 在Debian/Ubuntu系统下
apt-get update
apt-get install mariadb-server
apt-get install python2.7 python-setuptools python-imaging python-ldap python-mysqldb python-memcache python-urllib3
# 在 CentOS 7 下
yum install mariadb-server
yum install python-setuptools python-imaging python-ldap MySQL-python python-memcached python-urllib3

5.进入seafile安装包,执行./setup-seafile-mysql.sh

  1. 然后我们根据安装提示去配置我们的seafile,如果看不懂,可参考:传送门
  2. 配置数据库,这个地方很重要
-------------------------------------------------------
Please choose a way to initialize seafile databases:
-------------------------------------------------------

[1] Create new ccnet/seafile/seahub databases
[2] Use existing ccnet/seafile/seahub databases

出现这个,让你去选择或者使用已存在的数据库

注意,在这里,seafile会为我们创建一个seafile用户,同时,会创建ccnet/seafile/seahub数据库,这里,我们需要手动去更改下seafile用户的权限

OK,权限更改完,我们就可以正确连接数据库,并且完成安装

8.安装完成你将看到这个界面

启动 Seafile 服务器和 Seahub 网站

启动Seafile服务器

./seafile.sh start # 启动 Seafile 服务

启动Seahub

./seahub.sh start <port>  # 启动 Seahub 网站 (默认运行在8000端口上)

小贴士: 你第一次启动 seahub 时,seahub.sh 脚本会提示你创建一个 seafile 管理员帐号

开放8000 , 8082端口

Seabub: 8000
FileServer: 8082

默认情况下,我们的服务器没有开放8000,8082端口,那么我们需要去开放8000,8082端口,具体如何开放8000,8082端口,我们可以看我写的这篇文章:传送门

常用命令

./seahub.sh stop # 停止 Seafile 进程
./seafile.sh stop # 停止 Seahub

./seafile.sh start # 启动 Seafile 服务
./seahub.sh start 8001 # 启动 Seahub 网站 (运行在8001端口上)

./seahub.sh stop # 停止 Seahub
./seafile.sh stop # 停止 Seafile 进程

./seafile.sh restart # 停止当前的 Seafile 进程,然后重启 Seafile
./seahub.sh restart  # 停止当前的 Seahub 进程,并在 8000 端口重新启动 Seahub

pgrep -f seafile-controller # 查看 Seafile 进程
pgrep -f "seahub" # 查看 Seahub 进程

pkill -f seafile-controller # 结束 Seafile 进程
pkill -f "seahub" # 结束 Seafile 进程

演示

到此为止我们就完成了seafile的安装

立FLAG

  • 网盘开启Https,文件传输进行ssl加密
  • 思考了一下,那存储空间满了,我们如何去增加存储空间以及合理的安排存储?

最后欢迎大家关注我的微信订阅号,我会不定时推送些积极向上的文章以及相关技术文章,欢迎大家的支持