做服务端,最重要的就是服务稳定性,服务稳定性方面又分为两个方面。一个是发生前,如何降低事故发生的频率,甚至避免事故的发生。另一个是发生后,如何及时发现异常指标,在系统宕掉之前处理,快速止损。任何一个互联网大公司,各种系统的监控都是很完善的,有机器维度的监控、业务指标维度的监控等,甚至各个子系统也可能会有一些监控。这就造成了另外一个问题。一旦发生业务指标的报警,需要连VPN,然后看好多地方的曲线是否正常,甚至还要看天气情况,有没有什么活动(天气和重大活动对打车有较大影响),当地运营商网络情况,对于新人往往不那么友好。

那么,需求就来了。

NO. 1:能不能做一个模块,在业务指标产生异常触发报警时候,把各个需要人工看的地方自动截图一下,发到群里呢?

NO. 2:或者是做一个简单页面,把各个监控聚合到一个地址里。报警之后,自动发送链接到群里,值班人员直接点击链接就可以看各个模块的指标呢?

NO. 3:再或者是做一个模块,获取容易影响当前报警指标的各个因素的数据,然后自动分析出可能原因,每次报警之后自动给出结论呢?

技术总是来源于生活,回归于生活。这一下子就产生了三个目标,当然最简单的就是前两个,属于短平快的项目,今天就介绍前两个吧,后面那个是长期目标。

01

网页登录和截屏 

网页抓取和内容分析,估计大家都知道怎么搞,各种爬虫框架都有现成的方法,语言自带的http请求方法也很容易做到内容的抓取。但是截屏怎么搞,怎么截取网页内容渲染后的结果?最简单就是复用浏览器自身的渲染流程,在浏览器渲染出内容之后,想办法触发截屏操作,当然还要控制浏览器。废话不多说,直接上正题吧。
 
不知道大家有没有听过selenium webdriver。这个东西可以让你用代码控制浏览器,简直如臂使指。可以打开指定URL,可以往文本框里直接塞入账号密码,可以直接向某个元素发送点击事件,这不就搞定登录了吗,是不是So easy. 不止于此,还可以获取DOM元素,还可以等待一些事件(比如页面title的变化,某些元素的变化等等)。利用这个可以搞好多事情,最重要的是完全是通过浏览器运行模拟出来,比直接自己通过http请求不知道高明多少倍。看下图,感受下。

 

而且webdriver有很多语言版本,PHP里有facebook的php-webdriver(https://github.com/facebook/php-webdriver),python里直接安装selenium就行。然后还要安装chrome浏览器,当然也可以用其他浏览器。官网上还要安装chrome driver 和 selenium-server-standalone。稍微有些麻烦,这个不用管它了,直接安装一个webdriver-manager,三条命令就搞定了。

npm install -g webdriver-manager
webdriver-manager update

webdriver-manager start

还是比较简单的,剩下的就是代码部分了。

首先就是先创建一个driver,driver里有一些参数,可以设置窗口大小。headless是无头模式,可以隐藏浏览器界面,否则会打开浏览器界面,调试时候用这个比较方便。

$host = 'http://localhost:4444/wd/hub';
$disiredCapabilities = DesiredCapabilities::chrome();
$currentChromeOptions = $disiredCapabilities->getCapability(ChromeOptions::CAPABILITY);
$chromeOptions = !empty($currentChromeOptions) ? $currentChromeOptions : new ChromeOptions();
$chromeOptions->addArguments(['window-size=1024,768', 'headless']);
$disiredCapabilities->setCapability(ChromeOptions::CAPABILITY, $chromeOptions);
$driver = RemoteWebDriver::create($host, $disiredCapabilities);

然后就可以打开页面,进行截图了。

$driver->get("http://www.baidu.com");
sleep(2);
$driver->takeScreenshot(文件存储路径);

这个是强制休眠了2秒,等待页面加载完毕。比较low,你可以用wait操作,等待一些条件的触发。until里面会循环检测condition是否满足,一直到你设置的超时时间。WebDriverExpectedCondition里还有一些其他条件,可以挖掘一下。

$webDriverCondition = WebDriverExpectedCondition::titleIs("登录");
$driver->wait(2)->until($webDriverCondition);

你可以通过下面的代码查找文本框,然后输入用户名密码,进行登录。如果有验证码,可以安装其他识别验证码的库,获取到验证码的url,然后进行识别。

$driver->findElement(WebDriverBy::id('username'))->sendKeys(用户名);
$driver->findElement(WebDriverBy::id('password'))->sendKeys(密码);
$driver->findElement(WebDriverBy::id('submit'))->click();

整体用法还是比较简单的,短短几行代码就实现了登录和截屏,剩下的就是通过一些钉钉机器人的一些API进行发送了。接下来搞一下聚合多个外部网页的功能,这个也比较简单,直接用html写就行了。

02

外部网页聚合

这个没什么好说的,直接用bootstrap的Nav导航栏,结合iframe就可以了,iframe的高度需要设置一下。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>网页聚合</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script type="text/javascript">
             $(function () { 
                 $('#alarm-tab a').click(function (e) { 
                        e.preventDefault();
                        $(this).tab('show');
                        
                 });
            });

             function reinitIframe(){
                    var iframes = document.getElementsByName("alarm-frame");
                    try{
                        for(i = 0; i < iframes.length; i++) {
                            iframe = iframes[i];
                            var tabHeight = document.getElementById("alarm-tab").offsetHeight;
                            var windowHeight = $(window).height();
                            var height = windowHeight - tabHeight;
                            iframe.height = height;
                            console.log(height);
                        }
    
                    }catch (ex){
                        console.log(ex);
                    }
            }

            reinitIframe();
            window.setInterval("reinitIframe()", 200);
    </script>
</head>
<body width="100%" height="100%">

<ul class="nav nav-pills nav-justified" id="alarm-tab">
  <li class="active"><a href="#baidu">BaiDu</a></li>
  <li><a href="#google">Google</a></li>
</ul>

<div class="tab-content"> 
      <div class="tab-pane active" id="baidu" width="100%" height="100%">
          <iframe name="alarm-frame" src="http://www.baidu.com" width="100%" height="100%"></iframe>
      </div> 
      <div class="tab-pane" id="google" width="100%" height="100%">
          <iframe name="alarm-frame" src="http://www.google.com" width="100%" height="100%"></iframe>
      </div> 
</div> 

</body>
</html>

这个比较简单,不多说了,但是感觉可以搞一个简单的服务,让用户把多个感兴趣的网页聚合起来,生成一个统一的URL。

本篇文章来源于微信公众号: 搞点儿啥

最后修改日期: 2019年12月25日

留言

填写回复或留言