本文来自

抱紧我的小鱼干
苏州 | GUI设计师 | UI设计方面的知识经验分享,UI设计师可以关注下,学会了可以涨工资哟!

前言:

在出现问题时,企业往往采用加班等延长劳动时间的方法。但我认为有必要从这个禁锢中解脱出来,把如何提高工作效率作为目标,提高生产力。

(一)信息通货的时代

让我们首先把“信息比金钱更重要”、“我们的知性生产力,取决于信息的运用”这些理念牢记在我们头脑里吧

所以,话虽难听,聪明人盘剥不聪明的人其实也是信息主意的一个方面。为了获得有用的信息,投入一定的精力和金钱是必要的。所以善于对信息进行投资的人会越来越富,而不太懂得投资信息的人会继续受剥削。(比如现在的培训)

我们必须牢牢记住一个最基本的概念,就是拥有信息的人(=聪明人)合法地从没有信息的人(=不聪明的人)那里卷走金钱。(比如中介平台,知乎大V设计大神等)

虽然现在是信息爆炸的时代,但我却认为实际情况是信息尽管如潮水般涌来,却很少有人能真正享受如此多的信息。

通过与他人互换信息,得到的信息质量就高了许多。所以手中掌握信息的人容易聚在一起,于是,信息会越来越集中到这些掌握信息的人手中。(比如行业交流会,创业者交流会等)

Give的5平方:比起一味索取,其实只要你成为信息的提供者,那么你就可以轻松收集到你所需要的信息。因为别人也会主动向我们提供信息。因此为不知如何获取信息而大感烦恼的人,一定要把视角转到如何输出信息上去。(比如发教程,交流经验等)

社会已经进入了信息就意味着通货的时代。如果你想赚钱,你就必须首先收集信息,并对各种信息进行分析、整合,然后再转化为行动。
只要我们掌握了信息管理的窍门,那么看似铺天盖地的大量信息,对我们来说很有可能是一座宝库。这座宝库可以让我们不断去利用,并转换成货币。(比如大数据,个人信息,内容型网站)

(二)关于找出1%最有价值信息的6点建议

  • 1:掌握“框架力”(信息框架)
    这个框架提示我们,当信息进入到我们的大脑时,我们要随时给他们贴上标签,区分他们的类别,并把它们保存到大脑中符合这些信息类别的位置上。(就是把复杂事物按照一定规则分类,便于记忆整理。)

  • 2:利用“潜知力”积累经验
    除了框架力之外,你必须大量积累经验,以应对那些框架无法处理的信息。(积累理论和实际经验)

  • 3:具备“抗失败能力”
    如果一个人只愿意尝试必定成功的事情,那只能说明此人完全没有挑战新事物的决心,他的人生注定是平淡无奇的。(鸡血鸡汤…)
    对于每天必做的重复性工作,就要积极开动脑筋,相处好方法,使今后可以在这些事情上少花功夫。

  • 4:共享“最佳实践”的学问
    可以通过自己实践,和听取别人以往的经验相互补充,得到信息

  • 5:一定要做到扬长避短
    众所周知,一个人如果在某一领域里做的非常出色,那他学习理解其他领域里的东西也会比常人快,因为他在自己的领域里已经掌握了抓住本质的技巧。
    一个人的精力、体力是有限的,因此我们有必要认识自己擅长和不擅长的事情,努力做到不做无用功。

  • 6:不吝惜购书费用、多读好书——网页盛行时代非读书不可
    原因:书是众多的书稿中经过严格挑选和编辑后出版的,所以其内容一定非常有价值。在网上你不知道发布这条信息的是谁,另一方面这些信息也没有精力过评议或确认。
    但是如果你接住了“书”这一媒介,那么因为书经过了很多人之手,所以自然而然你就接触到了许多人的想法、信息和意见。
    我们花二三十块钱,就可以得到作者花费几年甚至几十年才能够完成的信息量。总之,重要的是“大量接触可能的好书”。只有这样,才能得到好书,而这些好书中的信息又会在以后给我们带来几十倍的好处。
    我认为现在几乎所有的信息,尤其是优质信息都是出现在纸面上的。与网页相比,在信息发布出来之前,要经过若干人的手,所以信息的质量较高。且与屏幕上的信息相比,纸面信息更有视觉认知性(包括排版等要素。)
    当然,读书的时候,应该快速通读一遍,看看里面大概写了些什么,然后当机立断,该扔就扔。(比如公众号的文章有些很长,先大致看一下是否有用,有用的话保存下来看)

读书还有一个窍门,就是不要太仔细研读,也就是说读书不要太贪,不要试图在一本书中找到你想了解的所有东西(可以结合同类型的其他书)。快速的泛读(如果不是工具书的话),只要把书中的内容存储于大脑的潜意识层里,在必要的时候能调取出来就可以了。
读书也不需要专门抽时间精心阅读,利用空闲时间、零散时间进行快速阅读。

不要轻看书籍的作用,好书是极为廉价,但却优质的信息来源。

有声读物也是一种不错的选择。

(三)关于读书投资法的7条建议

  • 1:读书是在和作者进行对话,所以读书时要设想对话的情景。
  • 2:不准备马上读的书也要先买下来,因为不买的话根本不会去读
    我们应该清楚,只有我们还没得到的信息或不寻常的信息,其价值才更高。通过投资购书费和时间,你可以获得让你耳目一新的知识。
    近来越来越少有人去买书了,这正是我们的机会,趁大家不再关注书本的时候,挑战一下大家都不理会的书,以此使自己有别于那些不关心书的人。
    优质信息一般都是有偿信息。我们应该具备这个观点。

(四)关于提高输入能力的建议

  • 1:把笔记本电脑作为“大脑助手”,充分利用

  • ☆ 2:把亲身体验、他人的经验和好书作为3大信息来源,减少对大众传媒的依赖
    应该增加的信息:1:从自己体验得到的东西(自己实际工作或业余练习中)
    2:从他人的体验中得到的东西(大V教程经验)
    3:好书里面的东西

我们必须了解,收集到的信息不一定马上就能用,信息是靠我们平常一点一滴积累起来的。你需要做的事情是尽可能地对收集到的信息贴上标签或索引,以便今后提取,这就够了。像这样每天保持一份好奇心,每天坚持对信息进行理性分类,就一定会有意外的收获。
因为我们人的时间都是有限的,自己的亲身体验也是有限的。所以为了提高信息收集的效率,我们需要然给别人告诉自己他们的亲身体验,并把他们的体验转换成自己的体验。
于是,如何把优秀的人吸引到自己的身边,如何和他们交朋友并建立起定期交换信息的关系能力成了尤为重要的问题。而最简单的方法就是让自己成为信息源,并以此吸引他人。(自己出教程,由此吸引其他有能力的人,不是一味索取)
也就是说,如果你有信息愿意和别人共享,那么对方会从你身上感受到你的魅力。只要你具备了这样一种魅力,优秀的人才自然而然会走近你身边。信息的有点事无论和多少人一起共享,它的量是不会减少的。所以只要主动和他人互换各自的信息,绝对是双赢的事情。

  • 3:睡眠是投资,多运动,睡好觉
    为什么说睡觉重要,是因为我们的大脑会在我们睡眠期间把白天输入到大脑的零零碎碎的信息整理一遍,因此一定要牢记睡眠即投资这个观点。

(五)关于提高输出能力的建议

如果你收集了大量的信息,却无法进行输出,那么这个信息既不能和只是的流通联系起来,也不能发挥价值,更不能和收入挂钩。(比如说看了很多教程,就需要通过自己的语言去解说,这些知识才能变成自己的)

  • 1:我在孩子9岁前,比起培养他们掌握计算能力,更重点培养他们掌握扎实的的语言能力。通过语言对话,把含混不清的事实说出来的能力是学习一切知识的基础

  • 2:当你得到一个信息的时候,首先要找出它的本质是什么,把信息简化。然后把经过简化的信息分别放到响应的层次中,于是你会掌握这个信息会怎样的展开。最后还有给整个信息类设定一个框架进行再构建。
    如何对一个信息进行分解,使其具备再现性,并实现重构是输出技术中最重要的一点。

对于麦肯锡的人来说,没有遵循金字塔原理(对事物结构分类)和MECE(没有遗漏和重复)写出来的文章就好比“与外行人闲聊”,没有任何用处。一般他们说话时会一边思考,开口就是“我有三点想说”。

  • 3:出书后,人生的舞台就会发生改变
    一旦有了影响力之后,以下几个方面就会发生改变:
    1:别人会主动和自己建立人脉关系
    2:别人会把工作送上门来
    3:别人会把信息送上门来
    4:通过这些变化,在很多事情上的机会会大大增加
    如果你想出书,就要把增强实力作为头等大事来做。

(六)关于保证知性化的5点建议

  • 1:远离不良习惯
    一旦精神或身体有了疲惫的感觉,那么信息的输入就无法畅通,随之效率就会下降。而在信息输出时,对体力和时间要求更高,因此身心的安定必不可少。

  • 2:养成有效利用零散时间的习惯,有效利用每一分钟

  • 3:睡眠不足的话,学到的东西也就无法记牢。

  • 4:注意力能否持久取决于一个人体力的好坏。我们思考一个问题直至得出结论,这一过程中体力必不可少。抱怨自己不能长时间集中注意力的人可以测试一下自己的体力

  • 5:什么是有益于大脑的饮食习惯呢?最重要的一点是“不暴饮暴食”,养成控制卡路里摄入量的习惯

重要的是努力获取好信息,并以此为基础,一点一点改进我们的行为方式。

(七)助你能力提升10倍的人脉技巧

在建立人脉关系网时,正确的做法是不要考虑是否有回报,你只要专注于向他人提供信息就可以了。建立人脉关系的前提是毫不吝惜地公开自己的知识和简介,以便向他人提供参考。实际上,通过自己思想出来的东西,才是自己的财富,才是通货。
人脉的根本就是增加“自身”的魅力,这才是最好的人脉技术。

【尾声】

成功取决于“知识事实比例稳定率”
大脑中的箱子装得越满,越容易找出隐藏在深处的本质。
把亲身体验、他人的经验和好书作为3大信息来源,减少对大众传媒的依赖。
输出并不容易,与输入相比,对注意力和体力的要求更高,大约是3倍左右。

需求来源,需要用PHP解析HTML提取我想要的数据

用PHP写网站爬虫的时候,需要把爬取的网页进行解析,提取里面想要的数据,这个过程叫做网页HTML中数据结构化。
很多人应该知道用phpQuery像JQuery一样的语法进行网页处理,抽取想要的数据。
但是在复杂一些的场景phpQuery并不能很好的完成工作,说简单点就是复杂场景不好用。
有没有更好的方式呢,我们看看商业爬虫软件是怎么做的。

他山之石,商业爬虫怎么做的

市面上商业爬虫怎么做HTML解析抽取数据的

看看市面上商业爬虫怎么做HTML解析结构化数据字段抽取
通过观察市面上商业爬虫工具GooSeeker、神箭手、八爪鱼,可以知道他们都用一个叫做XPath表达式的方式提取需要的字段数据。
那么可以判断使用XPath对HTML解析进行数据定位提取就是通行最佳的方式之一。

PHP中的XPath支持

XPath表达式可以查找HTML节点或元素,是一种路径表达语言。
那么需要先学习下XPath的基础,花个1-2小时入门,XPath就是页面数据提取能力的最佳内功之一,这个时间值得花。
既然用XPath提取页面数据是通行的方式,那么PHP中支持XPath的扩展包是什么呢?
为了帮大家节约时间,Symfony DomCrawler 就是PHP中最佳XPath包之一,直接用他吧,Symfony出品质量可是有目共睹,PHP热门框架laravel都用Symfony的包。
Symfony DomCrawler官方文档介绍的实例有限,建议有需要的情况下把代码读下,更能熟知新用法。

撸起袖子干,用DomCrawler做XPath HTML页面解析结构化数据抽取

基本思路

在Chrome浏览器中安装”XPath Helper”插件(XPath Helper怎么使用见参考资料)
打开需要解析的网站页面编写和测试XPath表达式
在PHP代码用DomCrawler使用上XPath表达式抽取想要的字段数据

实例演示

解析《神偷奶爸3》页面的的电影介绍信息
在Chrome中用编写测试XPath表达式

xpath helper使用


在项目下用composer安装guzzlehttp/guzzle(http client)、symfony/dom-crawler(Symfony DomCrawler)

composer require  guzzlehttp/guzzle
composer require  symfony/dom-crawler

下面直接上代码,在代码中用注释做说明
php Douban.php

<?php
/**
 * Created by PhpStorm.
 * User: wwek
 * Date: 2017/7/9
 * Time: 21:41
 */

require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;
use Symfony\Component\DomCrawler\Crawler;

print_r(json_encode(Spider(), JSON_UNESCAPED_UNICODE));
//print_r(Spider());

function Spider()
{
    //需要爬取的页面
    $url = 'https://movie.douban.com/subject/25812712/?from=showing';

    //下载网页内容
    $client   = new Client([
        'timeout' => 10,
        'headers' => ['User-Agent' => 'Mozilla/5.0 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)',
        ],
    ]);
    $response = $client->request('GET', $url)->getBody()->getContents();

    //进行XPath页面数据抽取
    $data    = []; //结构化数据存本数组
    $crawler = new Crawler();
    $crawler->addHtmlContent($response);

    try {
        //电影名称
        //网页结构中用css选择器用id的比较容易写xpath表达式
        $data['name'] = $crawler->filterXPath('//*[@id="content"]/h1/span[1]')->text();
        //电影海报
        $data['cover'] = $crawler->filterXPath('//*[@id="mainpic"]/a/img/@src')->text();
        //导演
        $data['director'] = $crawler->filterXPath('//*[@id="info"]/span[1]/span[2]')->text();
        //多个导演处理成数组
        $data['director'] = explode('/', $data['director']);
        //过滤前后空格
        $data['director'] = array_map('trim', $data['director']);

        //编剧
        $data['cover'] = $crawler->filterXPath('//*[@id="info"]/span[2]/span[2]/a')->text();
        //主演
        $data['mactor'] = $crawler->filterXPath('//*[@id="info"]/span[contains(@class,"actor")]/span[contains(@class,"attrs")]')->text();
        //多个主演处理成数组
        $data['mactor'] = explode('/', $data['mactor']);
        //过滤前后空格
        $data['mactor'] = array_map('trim', $data['mactor']);

        //上映日期
        $data['rdate'] = $crawler->filterXPath('//*[@id="info"]')->text();
        //使用正则进行抽取
        preg_match_all("/(\d{4})-(\d{2})-(\d{2})\(.*?\)/", $data['rdate'], $rdate); //2017-07-07(中国大陆) / 2017-06-14(安锡动画电影节) / 2017-06-30(美国)
        $data['rdate'] = $rdate[0];
        //简介
        //演示使用class选择器的方式
        $data['introduction'] = trim($crawler->filterXPath('//div[contains(@class,"indent")]/span')->text());

        //演员
        //本xpath表达式会得到多个对象结果,用each方法进行遍历
        //each是传入的参数是一个闭包,在闭包中使用外部的变量使用use方法,并使用变量指针
        $crawler->filterXPath('//ul[contains(@class,"celebrities-list from-subject")]/li')->each(function (Crawler $node, $i) use (&$data) {
            $actor['name']   = $node->filterXPath('//div[contains(@class,"info")]/span[contains(@class,"name")]/a')->text(); //名字
            $actor['role']   = $node->filterXPath('//div[contains(@class,"info")]/span[contains(@class,"role")]')->text(); //角色
            $actor['avatar'] = $node->filterXPath('//a/div[contains(@class,"avatar")]/@style')->text(); //头像
            //background-image: url(https://img3.doubanio.com/img/celebrity/medium/5253.jpg) 正则抽取头像图片
            preg_match_all("/((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+\.(jpg|jpeg|gif|png)/", $actor['avatar'], $avatar);
            $actor['avatar'] = $avatar[0][0];
            //print_r($actor);
            $data['actor'][] = $actor;
        });

    } catch (\Exception $e) {

    }

    return $data;

}

执行结果

{
    "name": "神偷奶爸3 Despicable Me 3",
    "cover": "https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p2469070974.webp",
    "director": [
        "凯尔·巴尔达",
        "皮艾尔·柯芬"
    ],
    "mactor": [
        "史蒂夫·卡瑞尔",
        "克里斯汀·韦格",
        "崔·帕克",
        "米兰达·卡斯格拉夫",
        "拉塞尔·布兰德",
        "迈克尔·贝亚蒂",
        "达纳·盖尔",
        "皮艾尔·柯芬",
        "安迪·尼曼"
    ],
    "rdate": [
        "2017-07-07(中国大陆)",
        "2017-06-14(安锡动画电影节)",
        "2017-06-30(美国)"
    ],
    "introduction": "  《神偷奶爸3》将延续前两部的温馨、搞笑风格,聚焦格鲁和露西的婚后生活,继续讲述格鲁和三个女儿的爆笑故事。“恶棍”奶爸格鲁将会如何对付大反派巴萨扎·布莱德,调皮可爱的小黄人们又会如何耍贱卖萌,无疑让全球观众万分期待。该片配音也最大程度沿用前作阵容,史蒂夫·卡瑞尔继续为男主角格鲁配音,皮埃尔·柯芬也将继续为经典角色小黄人配音,而新角色巴萨扎·布莱德则由《南方公园》主创元老崔·帕克为其配音。",
    "actor": [
        {
            "name": "皮艾尔·柯芬 ",
            "role": "导演",
            "avatar": "https://img3.doubanio.com/img/celebrity/medium/1389806916.36.jpg"
        },
        {
            "name": "凯尔·巴尔达 ",
            "role": "导演",
            "avatar": "https://img3.doubanio.com/img/celebrity/medium/51602.jpg"
        },
        {
            "name": "史蒂夫·卡瑞尔 ",
            "role": "饰 Gru / Dru",
            "avatar": "https://img3.doubanio.com/img/celebrity/medium/15731.jpg"
        },
        {
            "name": "克里斯汀·韦格 ",
            "role": "饰 Lucy Wilde",
            "avatar": "https://img3.doubanio.com/img/celebrity/medium/24543.jpg"
        },
        {
            "name": "崔·帕克 ",
            "role": "饰 Balthazar Bratt",
            "avatar": "https://img3.doubanio.com/img/celebrity/medium/5253.jpg"
        },
        {
            "name": "米兰达·卡斯格拉夫 ",
            "role": "饰 Margo",
            "avatar": "https://img1.doubanio.com/img/celebrity/medium/1410165824.37.jpg"
        }
    ]
}

经验

网页上数据是动态变化的,没获取到的字段需要用try catch进行异常处理,这样程序就不会崩溃
XPath表达式孰能生巧基本能应付绝大多数的需求
某些数据如果用XPath表达式也不好取,或者取出来的数据还需要加工的,用正则表达式处理,用preg_match_all进行抽取,用preg_replace进行替换
用strip_tags()函数去除HTML、XML以及PHP的标签,加参数可以保留标签去除,如处理文章内容strip_tags($str, "<p><img><strong>"),后留后面参数中的标签
一些常用的正则表达式


$str=preg_replace("/\s+/", " ", $str); //过滤多余回车 $str=preg_replace("/<[ ]+/si","<",$str); //过滤<__("<"号后面带空格) $str=preg_replace("/<\!--.*?-->/si","",$str); //注释 $str=preg_replace("/<(\!.*?)>/si","",$str); //过滤DOCTYPE $str=preg_replace("/<(\/?html.*?)>/si","",$str); //过滤html标签 $str=preg_replace("/<(\/?head.*?)>/si","",$str); //过滤head标签 $str=preg_replace("/<(\/?meta.*?)>/si","",$str); //过滤meta标签 $str=preg_replace("/<(\/?body.*?)>/si","",$str); //过滤body标签 $str=preg_replace("/<(\/?link.*?)>/si","",$str); //过滤link标签 $str=preg_replace("/<(\/?form.*?)>/si","",$str); //过滤form标签 $str=preg_replace("/cookie/si","COOKIE",$str); //过滤COOKIE标签 $str=preg_replace("/<(applet.*?)>(.*?)<(\/applet.*?)>/si","",$str); //过滤applet标签 $str=preg_replace("/<(\/?applet.*?)>/si","",$str); //过滤applet标签 $str=preg_replace("/<(style.*?)>(.*?)<(\/style.*?)>/si","",$str); //过滤style标签 $str=preg_replace("/<(\/?style.*?)>/si","",$str); //过滤style标签 $str=preg_replace("/<(title.*?)>(.*?)<(\/title.*?)>/si","",$str); //过滤title标签 $str=preg_replace("/<(\/?title.*?)>/si","",$str); //过滤title标签 $str=preg_replace("/<(object.*?)>(.*?)<(\/object.*?)>/si","",$str); //过滤object标签 $str=preg_replace("/<(\/?objec.*?)>/si","",$str); //过滤object标签 $str=preg_replace("/<(noframes.*?)>(.*?)<(\/noframes.*?)>/si","",$str); //过滤noframes标签 $str=preg_replace("/<(\/?noframes.*?)>/si","",$str); //过滤noframes标签 $str=preg_replace("/<(i?frame.*?)>(.*?)<(\/i?frame.*?)>/si","",$str); //过滤frame标签 $str=preg_replace("/<(\/?i?frame.*?)>/si","",$str); //过滤frame标签 $str=preg_replace("/<(script.*?)>(.*?)<(\/script.*?)>/si","",$str); //过滤script标签 $str=preg_replace("/<(\/?script.*?)>/si","",$str); //过滤script标签 $str=preg_replace("/javascript/si","Javascript",$str); //过滤script标签 $str=preg_replace("/vbscript/si","Vbscript",$str); //过滤script标签 $str=preg_replace("/on([a-z]+)\s*=/si","On\\1=",$str); //过滤script标签 $str=preg_replace("/&#/si","&#",$str); //过滤script标签,如javAsCript:alert(

参考资料

官方文档The DomCrawler Component
八爪鱼的了解XPath常用术语和表达式解析 十分钟轻松入门
gooseeker的xpath基础知识培训
神箭手的常用的辅助开发工具
XPath Helper:chrome爬虫网页解析工具 Chrome插件图文教程
在PHP中,您如何解析和处理HTML/XML?

扩展阅读

关于反爬虫,看这一篇就够了
最好的语言PHP + 最好的前端测试框架Selenium = 最好的爬虫(上)
QueryList 简单、 灵活、强大的PHP采集工具,让采集更简单一点。

隐藏nginx、openresty版本号

隐藏nginx、openresty的版本号有什么用?
假设一个场景,nginx被爆出0.9-1.5的版本被爆出一个0day漏洞,
攻击者会先大量扫描匹配的nginx版本,然后实施攻击。
如果事先隐藏了会降低第一时间被攻击的风险

在 http {} 中间配置增加

server_tokens off;

在http头中从原来的
Server: nginx/1.0.15 变为 Server: nginx
Server: openresty/1.11.2.3 变为 Server: openresty

nginx 日志格式化完整增强版

本完整增强版主要解决了后端执行时间的记录、哪台后端处理的、日志集中化后日志来自于哪台服务器ip、cdn传过来的客户端ip等扩展等问题。

在默认的nginx日志上,扩展增加了http头中代理服务器ip($http_x_forwarded_for)、
http头中cdn保存的客户端用户真实IP($http_x_real_ip)、服务端ip($server_addr)、http头中host主机($host)、
请求时间($request_time)、后端返回时间($upstream_response_time)、后端地址($upstream_addr)、
URI($uri)、ISO 8601标准时间($time_iso8601)

#log format
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$http_x_real_ip" "$server_addr" "$host" '
'$request_time $upstream_response_time "$upstream_addr" '
'"$time_iso8601"';

nginx日志滚动切割

繁忙的nginx服务器每天都会产生大量的web日志,所以每天需要切割。
每天切割的日志需要保留一段时间,更老的日志需要删除,专业叫法叫做日志滚动类似于视频监控,
所需要保留一定时间的日志还需要删除更老的日志。

很多人喜欢手动用bash shell去写nginx的日志切割滚动配合定时计划任务执行执行。
其实用系统自带的logrotate更好。
新建文件

/etc/logrotate.d/nginx

写入

/data/wwwlogs/*.log {
    #设置权限
    su root www
    #以天为周期分割日志
    daily
    #最小 比如每日分割 但如果大小未到 1024M 则不分割
    minsize 1024M
    #最大 当日志文件超出 2048M 时,即便再下一个时间周期之前 日志也会被分割
    maxsize 2048M
    #保留七天
    rotate 7
    #忽略错误
    missingok
    #如果文件为空则不分割 not if empty
    notifempty
    #以日期为单位
    dateext
    #以大小为限制做日志分割 size 会覆盖分割周期配置 1024 1024k 1024M 1024G
    size 1024M
    #开始执行附加的脚本命令 nginx写日志是按照文件索引进行的 必须重启服务才能写入新日志文件
    sharedscripts
    postrotate
    if [ -f /usr/local/nginx/logs/nginx.pid ]; then
    #重启nginx服务
    kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
    fi
    endscript
}

elastic stack elk日志系统

采集的日志需要格式化格式,要么在采集端做,要么在入库elasticsearch的时候做。
在nginx中直接配置输出的日志就是json格式,可以减少格式化日志的cpu开销
在日志采集端,用filebeat、或者logstash作为日志采集工具可以不做任务的格式化处理,
仅仅采集json格式的文本即可。

log_format logstash_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"remote_addr":"$remote_addr",'
'"http_x_forwarded_for":"$http_x_forwarded_for",'
'"http_x_real_ip":"$http_x_real_ip",'
'"http_cf_connecting_ip":"$http_cf_connecting_ip",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"request":"$request",'
'"url":"$uri",'
'"referer":"$http_referer",'
'"agent":"$http_user_agent",'
'"status":"$status"}';

nginx反向代理

listen 80;
#listen [::]:80;
server_name proxy.iamle.com;

location / {
#auth_basic "Password please";
#auth_basic_user_file /usr/local/nginx/conf/htpasswd;
proxy_pass http://127.0.0.1:5601/;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

nginx反向代理的时候要支持后端服务器为DDNS动态域名

server_name proxy.iamle.com;
resolver 1.1.1.1 valid=3s;
set $HassHost "http://backend.iamle.com:999";
location / {
    #auth_basic "Password please";
    #auth_basic_user_file /usr/local/nginx/conf/htpasswd;
    proxy_pass $HassHost;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
}

nginx 反向代理 WebScoket

location /api/ {
        proxy_pass http://webscoket:80/;
        # WebScoket Support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        #proxy_set_header Origin xxx;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
}

nginx代理设置php pm status

php-fpm.conf设置

pm.status_path = /phpfpm-status-www

phpfpm.conf

server
{
listen 80;
server_name localhost;
location ~ ^/(phpfpm-status-www|phpstatuswww)$
{
fastcgi_pass unix:/tmp/php-cgi.sock;
include fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
}
}

nginx 域名SEO优化 301

把 iamle.com 默认 301到 www.iamle.com

listen 80;
server_name www.iamle.com iamle.com;
if ($host != 'www.iamle.com' ) {
rewrite ^/(.*)$ https://www.iamle.com/$1 permanent;
}

nginx 全站http跳转https

server{
listen 80;
server_name www.iamle.com;
return 301 https://www.iamle.com$request_uri;
}

server {

listen 443 ssl http2;
ssl    on;
ssl_certificate         /usr/local/nginx/conf/ssl/www.iamle.com.crt;
ssl_certificate_key     /usr/local/nginx/conf/ssl/www.iamle.com.key;
ssl_session_cache           shared:SSL:10m;
ssl_session_timeout         10m;
ssl_session_tickets         off;

# intermediate configuration. tweak to your needs.
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    ssl_prefer_server_ciphers on;

# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
#add_header Strict-Transport-Security max-age=15768000;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;

server_name www.iamle.com;
#  ....
}

XSS、Ifram

add_header X-Frame-Options SAMEORIGIN;                                                                                                                        
add_header X-Content-Type-Options nosniff;                          
add_header X-Xss-Protection "1; mode=block";

nginx http2 openssl 支持情况介绍

Supporting HTTP/2 for Website Visitors

ssl https 证书配置生成巩固

Mozilla SSL Configuration Generator

nginx+php 开启OPCACHE 并且使用软连接发布

软连接的方式发布新版本php代码,但是因为OPCACHE未及时更新某些时候会导致502错误
2个方式,方式1直接在nginx这里自动更新最新路径,方式2刷新php-fpm的缓存
下面是方式1

        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;

Cache invalidation for scripts in symlinked folders
Symfony Configuring a Web Server

apache ab

老牌简单方便的ab压测

yum install apr-util

webench

web http压力测试

wget http://blog.zyan.cc/soft/linux/webbench/webbench-1.5.tar.gz
tar zxvf webbench-1.5.tar.gz
cd webbench-1.5
make && make install

wrk

wrk官网
Modern HTTP benchmarking tool
web http压力测试

提示:
wrk测试结果可能不是那么准确,原因见
openresty作者(agentzh) 春哥在微博中说道 https://weibo.com/1834459124/G9ew2d5Ky?type=repost

我们的一家付费客户之前反映用 wrk 压测时发现有延时较高的长尾请求,
我们仔细使用 systemtap 和抓包工具分析之后,
发现 wrk 报告的延时结果错得离谱(比实际延时可能高出一个数量级的水平),
同时发现 wrk 输出的报告里不同的数字之间甚至都相互矛盾,
最后发现 wrk 内部有一个 stats_correct 函数会故意向实际统计的结果里加入噪音数据,
按其作者的说法,是为了摸拟真实互联网环境下的延时,
我就大汗了……我们自己去掉 wrk 那个 C 函数调用结果就对了。

go-wrk

go-wrk官网
go-wrk – a HTTP benchmarking tool based in spirit on the excellent wrk tool (https://github.com/wg/wrk)

Gatling Pea

Gatling官网
Gatling开源
Async Scala-Akka-Netty based Load Test Tool http://gatling.io
Gatling 是基于 Netty 和 Akka 技术实现的高性能压测工具.

关于 Pea
由于单独一台机器硬件资源和网络协议的限制存在, 在高负载测试中需要多台机器共同提供负载. Pea 是在以 Galting 为引擎, 在多节点场景下的压测工具. 包含以下特性:

管理和监控多个工作节点. 依赖 Zookeeper
运行过程中可以实时查看每个节点的具体执行状态
多个节点执行完后会自动收集日志, 生成统一的报告
支持原生的 Gatling 脚本, 原生的 HTTP 协议
扩展支持了 Dubbo和 Grpc 协议
以 Git 仓库管理脚本和资源文件
内置了 Scala 增量编译器, 脚本可在线快速编译
不同于其他实现, 所有这些功能都在同一进程内实现. 感谢 Gatling 作者高质量的代码
可以在实体机, 虚拟机, Docker 容器中运行

sniper

sniper官网
A powerful & high-performance http load tester

hey

hey官网
HTTP load generator, ApacheBench (ab) replacement, formerly known as rakyll/boom

Siege

Siege官网
Siege is an http load tester and benchmarking utility

http_load

http_load官网
http_load runs multiple http fetches in parallel, to test the throughput of a web server.

vegeta

vegete官网
HTTP load testing tool and library. It’s over 9000!

t50

t50官网
mixed packet injector tool

GoReplay

GoReplay官网
GoReplay is an open-source tool for capturing and replaying live HTTP traffic into a test environment in order to continuously test your system with real data. It can be used to increase confidence in code deployments, configuration changes and infrastructure changes.
https://github.com/buger/goreplay

tcpcopy

tcpcoy官网
An online request replication tool, also a tcp stream replay tool, fit for real testing, performance testing, stability testing, stress testing, load testing, smoke testing, etc

gryphon

Gryphon官网
Gryphon是由网易自主研发的能够模拟千万级别并发用户的一个软件,目的是能够用较少的资源来模拟出大量并发用户,并且能够更加真实地进行压力测试, 以解决网络消息推送服务方面的压力测试的问题和传统压力测试的问题。Gryphon分为两个程序,一个运行gryphon,用来模拟用户,一个是 intercept,用来截获响应包信息给gryphon。Gryphon模拟用户的本质是用一个连接来模拟一个用户,所以有多少个连接,就有多少个用户,而用户的素材则取自于pcap抓包文件。值得注意的是,Gryphon架构类似于tcpcopy,也可以采用传统使用方式和高级使用方式。

locust.io

Locust官网
An open source load testing tool.
Define user behaviour with Python code, and swarm your system with millions of simultaneous users.
python编写,用python脚本定义压测规则,分布式,有WEB UI界面
推荐使用

Jmeter

Apache JMeter官网
Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。
比较轻量,较多测试同学喜欢用

Tsung

Tsung官网
Tsung is an open-source multi-protocol distributed load testing tool
It can be used to stress HTTP, WebDAV, SOAP, PostgreSQL, MySQL, LDAP, MQTT and Jabber/XMPP servers. Tsung is a free software released under the GPLv2 license.
Tsung是一个开源的支持多协议的分布式压力测试工具
目前支持HTTP分布式压力测试、WebDAV分布式压力测试、SOAP分布式压力测试、PostgreSQL分布式压力测试、MySQL分布式压力测试、LDAP分布式压力测试、MQTT分布式压力测试、Jabber/XMPP servers分布式压力测试

LoadRunner

LoadRunner官网
老牌压力测试工具,安装包非常之大,功能也非常全,目前被微软收购了

nGrinder

nGrinder官方
nGrinder is a platform for stress tests that enables you to execute script creation, test execution, monitoring, and result report generator simultaneously. The open-source nGrinder offers easy ways to conduct stress tests by eliminating inconveniences and providing integrated environments.
nGrinder是基于Grinder开源项目,由NHN公司的开发团队进行了重新设计和完善。nGrinder是一款非常易用,有简洁友好的用户界面和controller-agent分布式结构的强大的压力测试工具。
nGrinder测试基于python测试脚本(groovy也可),用户按照一定规范编写测试脚本,controller会将脚本一集需要的资源分发到agent,用jython执行。并且在执行的过程中收集运行情况、相应时间、测试目标服务器的运行情况等。并且保存这些数据生成测试报告,以供查看。
这款框架的一大特点就是非常的简单易用,安装也很容易,可以说是开箱即用。

nGrinder使用

nGrinder-运维人员轻量级性能测试平台 https://www.jianshu.com/p/f336180806cc

BuoyantIO/slow_cooker

BuoyantIO/slow_cooker官网
A load tester focused on lifecycle issues and long-running tests
负载测试人员专注于生命周期问题和长期运行的测试
大多数负载测试人员通过向后端发送尽可能多的流量来工作。
我们想要一种不同的方法,我们希望能够在很长一段时间内测试具有可预测的负载和并发级别的服务。
我们希望定期报告qps和延迟,而不是最后收到报告。

twitter/iago

twitter/iago官网
A load generator, built for engineers
面向开发者的负载生成器
Iago是一个负载生成工具,可以针对给定目标重放生产或合成流量。
除此之外,它与其他负载生成工具的不同之处在于它试图保持事务速率不变。
例如,如果您想以每分钟100K的请求测试您的服务,Iago会尝试达到该速率。
由于Iago重放流量,您必须指定流量来源。
您使用事务日志作为流量来源,其中每个事务都会向您的服务生成服务处理请求。
以固定速率重放事务使您可以在预期负载下研究服务的行为。
Iago还允许您识别在生产环境中可能无法轻易观察到的瓶颈或其他问题,在这种环境中,您的最大预期负载很少发生。

fortio

fortio官网
fortio
Fortio load testing library, command line tool, advanced echo server and web UI in go (golang).
Allows to specify a set query-per-second load and record latency histograms and other useful stats.
Fortio是一个用golang写的负载测试库,包括了命令行工具,高级echo服务器和Web UI。
允许指定设置的每秒查询负载和记录延迟直方图以及其他有用的统计信息。

autocannon

autocannon官网
A HTTP/1.1 benchmarking tool written in node, greatly inspired by wrk and wrk2, with support for HTTP pipelining and HTTPS. On my box, autocannon can produce more load than wrk and wrk2.

k6

k6官网
k6开源
使用Go和JavaScript的现代负载测试工具-https://k6.io
A modern load testing tool, using Go and JavaScript – https://k6.io
Scripting in ES6 JS: support for modules to aid code reusability across an organization
Everything as code: test logic and configuration options are both in JS for version control friendliness
Automation-friendly: checks (like asserts) and thresholds for easy and flexible CI configuration!
HTTP/1.1, HTTP/2 and WebSocket protocol support
TLS features: client certificates, configurable SSL/TLS versions and ciphers
Batteries included: Cookies, Crypto, Custom metrics, Encodings, Environment variables, JSON, HTML forms, files, flexible execution control, and more.
Built-in HAR converter: record browser sessions as .har files and directly convert them to k6 scripts
Flexible metrics storage and visualization: InfluxDB (+Grafana), JSON or Load Impact Insights
Cloud execution and distributed tests (currently only on infrastructure managed by Load Impact, with native distributed execution in k6 planned for the near future!)

几乎所有的WEB压力测试工具 WEB压力测试工具大全 原文出处

loader.io(在线服务)

loader.io官网
Simple Cloud-based
LOAD TESTING
Loader.io is a FREE load testing service that allows you to stress test
your web-apps & apis with thousands of concurrent connections.

gaps腾讯压测大师(在线服务)

gaps官网
一分钟完成用例配置,让压测更简单
支持HTTP、HTTPS协议的API接口、网站、公众号内页等主流压测对象

阿里云PTS(在线服务)

阿里云PTS官网
性能测试PTS(Performance Testing Service)是面向所有技术相关背景人员的云化性能测试工具,孵化自阿里内部平台。有别于传统工具的繁复,PTS以互联网化的交互,面向分布式和云化的设计,更适合当前的主流技术架构。无论是自研还是适配开源的功能,PTS都可以轻松模拟大量用户访问业务的场景,任务随时发起,免去搭建和维护成本。更是紧密结合监控类产品提供一站式监控、定位等附加价值,高效检验和管理业务性能。

需求

当前php-fpm进程是不是不够了,一通命令一打,也只能看当前情况。
熟话说无监控无度量就无诊断。
市面上有成熟的php-fpm status状态采集,展示工具那就是elasti stack全家桶
目标采集分析php-fpm status 状态数据

选型

Elastic公司全家桶之Beats(PHP-FPM Module@Metricbeat) + Elasticsearch + Kibana

Metricbeat 是 Beats 的一个采集组件
PHP-FPM Module 是 Metricbeat 的一个采集模块

整体的数据流方式

方式1 : Beats (Metricbeat )>Elasticsearch>Kibana
方式2: Beats (Metricbeat )>Logstash>[直连,redis队列,Kafka队列]>Elasticsearch>Kibana

先讲方式1

配置php-fpm

php-fpm.conf

[www]
...
pm.status_path = /phpfpm-status-www

[u]
...
pm.status_path = /phpfpm-status-u

[www] [u] 是独立的php-fpm pool 进程池,每个池子的pm.status_path是需要单独设置的

测试配置文件是否正确

/usr/local/php/sbin/php-fpm -t
[29-Mar-2017 16:15:08] NOTICE: configuration file /usr/local/php/etc/php-fpm.conf test is successful

重启php-fpm

/etc/init.d/php-fpm reload
Reload service php-fpm done

配置nginx

phpfpm.conf

server
{
  listen 80;
  server_name localhost;
  location ~ ^/(phpfpm-status-www|phpstatuswww)$
  {
    fastcgi_pass unix:/tmp/php-cgi.sock;
    include fastcgi.conf;
    fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
  }
  location ~ ^/(phpfpm-status-u|phpstatusu)$
  {
    fastcgi_pass unix:/tmp/u-php-cgi.sock;
    include fastcgi.conf;
    fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
  }
}

只给本地访问,这里监听的是localhost,也可用nginx allow deny的方式

测试配置文件是否正确

/usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

重启nginx

/etc/init.d/nginx reload
Reloading nginx daemon configuration....

用curl测试php-fpm status状态是否可以获取

curl http://localhost/phpfpm-status-www
pool: www
process manager: static
start time: 29/Mar/2017:16:19:09 +0800
start since: 75
accepted conn: 900
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 696
active processes: 4
total processes: 700
max active processes: 60
max children reached: 0
slow requests: 1

配置Metricbeat

Metricbeat Reference [5.3] » Modules » PHP-FPM Module

/etc/metricbeat/metricbeat.yml

#========================== Modules configuration ============================
metricbeat.modules:

#------------------------------- PHP-FPM Module -------------------------------
- module: php_fpm
  metricsets: ["pool"]
  enabled: true
  period: 10s
  status_path: "/phpfpm-status-www"
  hosts: ["localhost:80"]

- module: php_fpm
  metricsets: ["pool"]
  enabled: true
  period: 10s
  status_path: "/phpfpm-status-u"
  hosts: ["localhost:80"]

#-------------------------- Elasticsearch output ------------------------------
output.elasticsearch:
# Array of hosts to connect to.
  hosts: ["localhost:9200"]

测试配置文件是否正确

/usr/share/metricbeat/bin/metricbeat -configtest
Config OK

给metricbeat创建Elasticsearch的Index Template
Loading the Index Template in Elasticsearch

curl -XPUT 'http://localhost:9200/_template/metricbeat' -d@/etc/metricbeat/metricbeat.template.json

给metricbeat创建Kibana Dashboards
Loading Sample Kibana Dashboards

./scripts/import_dashboards -es http://localhost:9200

metricbeat中phpfpm模块,没有elastic官方的 Sample Kibana Dashboard
所以需要分析什么数据的自己在Kibana中自己创建visualize然后做成Dashboard

启动metricbeat

/etc/init.d/metricbeat start

配置Kibana

Management / Kibana / Indices > Add New
Index name or pattern 填写 “metricbeat-*”
Time-field name 选 “@timestamp”
Alt text

分享我做的 metricbeat phpfpm kibana dashboard (不完整)
export.json

[
  {
    "_id": "PHP-FPM导航",
    "_type": "visualization",
    "_source": {
      "title": "PHPFPM导航",
      "visState": "{\n  \"title\": \"PHP-FPM导航\",\n  \"type\": \"markdown\",\n  \"params\": {\n    \"markdown\": \"- [Overview](#/dashboard/Metricbeat-phpfpm-overview)\\n\\n\\n```\\npool:php-fpm池的名称,一般都是应该是www\\nprocess manage:进程的管理方法,php-fpm支持三种管理方法,分别是static,dynamic和ondemand,一般情况下都是dynamic\\nstart time:php-fpm启动时候的时间,不管是restart或者reload都会更新这里的时间\\nstart since:php-fpm自启动起来经过的时间,默认为秒\\naccepted conn:当前接收的连接数\\nlisten queue:在队列中等待连接的请求个数,如果这个数字为非0,那么最好增加进程的fpm个数\\nmax listen queue:从fpm启动以来,在队列中等待连接请求的最大值\\nlisten queue len:等待连接的套接字队列大小\\nidle processes:空闲的进程个数\\nactive processes:活动的进程个数\\ntotal processes:总共的进程个数\\nmax active processes:从fpm启动以来,活动进程的最大个数,如果这个值小于当前的max_children,可以调小此值\\nmax children reached:当pm尝试启动更多的进程,却因为max_children的限制,没有启动更多进程的次数。如果这个值非0,那么可以适当增加fpm的进程数\\nslow requests:慢请求的次数,一般如果这个值未非0,那么可能会有慢的php进程,一般一个不好的mysql查询是最大的祸首。\\n```\"\n  },\n  \"aggs\": [],\n  \"listeners\": {}\n}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\n  \"query\": {\n    \"query_string\": {\n      \"query\": \"*\",\n      \"analyze_wildcard\": true\n    }\n  },\n  \"filter\": []\n}"
      }
    }
  },
  {
    "_id": "PHPFPM-processes-active",
    "_type": "visualization",
    "_source": {
      "title": "PHPFPM processes active",
      "visState": "{\"title\":\"PHPFPM processes active\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"php_fpm.pool.processes.active\",\"customLabel\":\"活动\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"时间\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"php_fpm.pool.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"pool池\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"beat.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"主机\",\"row\":true}}],\"listeners\":{}}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
      }
    }
  },
  {
    "_id": "PHPFPM-connections-queued",
    "_type": "visualization",
    "_source": {
      "title": "PHPFPM connections queued",
      "visState": "{\"title\":\"PHPFPM connections queued\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"php_fpm.pool.connections.queued\",\"customLabel\":\"队列\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"时间\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"php_fpm.pool.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"pool池\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"beat.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"主机\",\"row\":true}}],\"listeners\":{}}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
      }
    }
  },
  {
    "_id": "PHPFPM-processes-idle",
    "_type": "visualization",
    "_source": {
      "title": "PHPFPM processes idle",
      "visState": "{\"title\":\"PHPFPM processes idle\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"php_fpm.pool.processes.idle\",\"customLabel\":\"空闲\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"时间\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"php_fpm.pool.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"pool池\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"beat.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"主机\",\"row\":true}}],\"listeners\":{}}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
      }
    }
  },
  {
    "_id": "PHPFPM-slow_requests",
    "_type": "visualization",
    "_source": {
      "title": "PHPFPM slow_requests",
      "visState": "{\"title\":\"PHPFPM slow_requests\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"php_fpm.pool.slow_requests\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"时间\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"php_fpm.pool.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"pool池\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"beat.name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"主机\",\"row\":true}}],\"listeners\":{}}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"metricbeat-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
      }
    }
  }
]

补充logstash采集数据(方式2)

配置Metricbeat

/etc/metricbeat/metricbeat.yml

#================================ Outputs =====================================
# The Logstash hosts
output.logstash:

  hosts: ["localhost:5044"]

output输出到logstash的input tcp 5044上
input输入参考上面方式1 Metricbeat 的配置方法

配置logstash2.x

Logstash Reference [2.4] » Input plugins » beats

/etc/logstash/conf.d/beats.conf

input {
    beats {
        host => "127.0.0.1"
        port => 5044
    }
}
filter {
}
output {
    ... 输出到kafka 或者reids 或者 elasticsearch等,具体配置方法看官方文档
}

input输入tcp 5044 监听本机
output输出,根据自己环境来

测试配置文件是否正确

/opt/logstash/bin/logstash -t
Configuration OK

启动logstash

/etc/init.d/logstash start

提示

  • 使用测试配置文件的功能测试配置文件是否书写正确
  • 使用tail -f 日志的方式查错
  • 注意tcp监听的安全问题,别暴露到公网IP上

@echo off
title "WPS Office 2016 10.1.0.6135 个人版一键去广告"
set wps_vsion=10.1.0.6135
set wps_addr=%localappdata%\kingsoft\WPS Office\%wps_vsion%\
set desktoptip=desktoptip.exe
set wpsnotify=wpsnotify.exe
set wpscloudsvr=wpscloudsvr.exe
set wpsupdate=wpsupdate.exe
set wpsrenderer=wpsrenderer.exe

set desktoptip_addr=%wps_addr%wtoolex\%desktoptip%
set wpsnotify_addr=%wps_addr%wtoolex\%wpsnotify%
set wpsupdate_addr=%wps_addr%wtoolex\%wpsupdate%
set wpsrenderer_addr=%wps_addr%office6\%wpsrenderer%

taskkill /IM %desktoptip%
taskkill /IM %wpsnotify%
taskkill /IM %wpscloudsvr%
taskkill /IM %wpsupdate%
taskkill /IM %wpsrenderer%

copy "%desktoptip_addr%" "%wps_addr%wtoolex\%desktoptip%.bak"
copy "%wpsnotify_addr%" "%wps_addr%wtoolex\%wpsnotify%.bak"
copy "%wpsupdate_addr%" "%wps_addr%wtoolex\%wpsupdate%.bak"
copy "%wpsrenderer_addr%" "%wps_addr%office6\%wpsrenderer%.bak"

echo fwps > "%desktoptip_addr%"
echo fwps > "%wpsnotify_addr%"
echo fwps > "%wpsupdate_addr%"
echo fwps > "%wpsrenderer_addr%"

sc stop wpscloudsvr
sc config wpscloudsvr start= disabled

echo "处理完成!! 可以关闭本窗口了"
pause

保存为 “WPS Office 2016 10.1.0.6135 个人版一键去广告.bat” bat批处理,右键用超级管理员权限执行