JIAYX 发布的文章

今天树莓派到货了,是个不错的玩具,哈哈~

刚拿到的时候突然感觉无从下手啊。。
研究了一会开始搞了。
首先装系统,去官网下了一个 Ubuntu Meta 系统。这里下载
然后按照购买时淘宝店老板给的说明书刷了系统,就是把镜像刻录到TF卡中,16G的卡装完系统就剩7-8G了。
装好系统之后开机,一切正常。
开始安装各种软件,这时候问题来了,安装报错了。因为是新装的系统,要先执行 sudo apt-get update 才可以开始执行 sudo apt-get install xx。但是Ubuntu的软件源国内速度太慢了,执行 sudo apt-get update 老半天都没反应。于是想着换一个 163 的源。悲催的是163的源并不适合树莓派的 Ubuntu Meta 系统。几经周折之后,开了树莓派的 WiFi 功能连了公司的 VPN 热点这样才能勉强开始更新。
系统装好了,软件有了就可以开始折腾了~

买树莓派的时候顺便买了几颗 LED 于是开始在网上搜教程打算让 LED 闪几下。
我控制树莓派用的是python的 RPi.GPIO 类库,非常方便。
这里有个概念要说一下,可能刚玩树莓派的搞不太清楚,我也是查了半天加上自己试验才搞明白。
就是这个:GPIO.setmode(GPIO.BOARD)
setmode 的时候有两种可选:

  1. GPIO.BOARD
  2. GPIO.BCM

这两种的区别就是,在代码中配置引脚的高低电平时。
1是按照图中的 圆圈中的数字来对应的
2是按照图中的 GPIOxx后面的数字来对应的
树莓派引脚对应图

使用第2种模式的时候要注意,不可以设置非 GPIO 开头引脚的电平,因为他们是树莓派预设好的,强行设置会报错。

剩下的应该水到渠成了,问题不大。
这里贴一个我控制 led 闪烁的 python 代码,网上一搜也不少,大同小异。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(35, GPIO.OUT)
GPIO.setup(37, GPIO.OUT)

GPIO.output(35, GPIO.LOW)

while True:
    GPIO.output(37, GPIO.HIGH)
    time.sleep(0.2)
    GPIO.output(37, GPIO.LOW)
    time.sleep(0.2)

初玩树莓派,如有说的不对的地方还请指正。

自动加载简单考虑的话,需要一个数组存放自动加载目录。
并使用系统函数spl_autoload_register注册自定义的自动加载函数。
自动加载要符合psr规范

<?php

/**
* 自动加载类 
*/
class Loader
{
    // 自动加载搜索目录
    private static $loadPaths = [];

    // 添加自动加载路径
    public static function addAutoLoadPath($path)
    {
        self::$loadPaths[] = $path;
    }

    // 注册自动加载函数
    public static function register()
    {
        spl_autoload_register('self::autoload');
    }

    // 自动加载函数
    public static function autoload($className)
    {
        $className = str_replace(['\\', '_'], DIRECTORY_SEPARATOR, $className);
        foreach (self::$loadPaths as $loadPath) {
            $loadPath = rtrim($loadPath, DIRECTORY_SEPARATOR);
            $path = $loadPath . DIRECTORY_SEPARATOR . $className . '.php';
            if (self::import($path)) {
                break;
            }
        }
    }

    // 包含一个已存在的文件
    public static function import($path)
    {
        return file_exists($path) ? include_once($path) : false;
    }

}

有这个类之后,配合前文中的入口文件,就可以继续了。
接下来我们需要一个路由。

不知道我的步骤对不对 反正就记在这了。

先简单介绍下我的目录规划,以后会有所变动,现在一切从简。

/
---app
    ---Controller
        Home.php
    ---Config
        ---local
            db.php
            ...
    ---Model
    ...
---system
    Loader.php
    Uri.php
    Route.php
    Config.php
---runtime
    ...
index.php

第一步:入口文件;
一件很重要的事情,原因看注释。

<?php
// 修正cli模式下运行目录不同部分系统函数取值不同的问题 比如: getcwd
defined('STDIN') AND chdir(__DIR__);

定义一些必要的常量

<?php
define('APP_FOLDER', 'app');
define('SYSTEM_FOLDER', 'system');

define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
define('APP_PATH', ROOT_PATH . APP_FOLDER . DIRECTORY_SEPARATOR);
define('SYSTEM_PATH', ROOT_PATH . SYSTEM_FOLDER . DIRECTORY_SEPARATOR);

然后要手动导入自动加载类,并且添加自动加载路径,注册自动加载函数。
这样之后的类就可以自动加载了。

include SYSTEM_PATH . 'Loader.php';

Loader::addAutoLoadPath(SYSTEM_PATH);
Loader::addAutoLoadPath(APP_PATH);
Loader::register();

下一篇是Loader类的具体实现。

感觉就照我这个作息时间,就照我这个工作方式。离一场大病也不远了

前期build数据使用php脚本,25000条数据(以下时间均为插入25000条测得)大概要4分钟
为了加快build速度,决定采用并发支持比较好的golang来做
第一个demo使用了官方给出的操作示例,单条循环插入

for _, item := range *items {
        _, err = client.Index().
        Index("twitter").
        Type("tweet").
        BodyJson(item).
        Do()
}

改写之后,只开一个线程的话时间缩短到1分30秒
开四个或四个以上线程,时间大约30-40秒
这样做还是不够理想,毕竟我们是google级别的工程师^_^(龙哥说的~~)
然后寻找改进方法。
龙哥提到有一个Bulk方法可以批量插入数据。
一番研究之后,代码片段如下:

bulkService := client.Bulk().Index("test").Type("test")
for _, item := range *items {
    fmt.Println("[thread", i, "] ", item.UniqueId)
    r := elastic.NewBulkIndexRequest().Index("test").Type("test").Doc(item)
    bulkService.Add(r)
    // 大于阀值先存一波
    if bulkService.NumberOfActions() > MaxBulkActions {
        bulkService.Do()
    }
}
// 剩余的存一波
if bulkService.NumberOfActions() > 0 {
    bulkService.Do()
}

修改过后经测试,四线程是最优的。插入25000条数据大约只需要4秒钟。