海运的博客

PHP包管理依赖管理工具Composer使用

发布时间:January 10, 2015 // 分类:PHP // No Comments

安装Composer:

#安装到当前目录,使用命令php composer.phar
curl -sS https://getcomposer.org/installer | php
#也可移动到PATH目录,使用命令composer
mv composer.phar /usr/local/bin/composer
#安装到指定目录
#curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

或直接下载执行文件:

https://getcomposer.org/composer-stable.phar -O /usr/local/bin/composer
chmod +x /usr/local/bin/composer

Composer配置文件:

cat composer.json 
{
    "require": {
        "tedivm/fetch": "0.6.*"
    }
}

Composer安装及更新包:

#安装,在配置文件目录执行,软件会下载安装到vendor目录
composer install
#更新
composer update
#命令方式安装指定包,同时会写入配置文件
composer require tedivm/fetch:0.6.*
#更新指定包
composer update tedivm/fetch

PHP调用Composer安装的包:

require 'vendor/autoload.php';

GO生成随机数字/英文字符串

发布时间:January 8, 2015 // 分类:GO // No Comments

package main

import (
        //"fmt"
        "math/rand"
)

func randSeq(n int) string {
        //letters := []rune("abcdefghijklmnopqrstuvwxyz")
        letters := []rune("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
        b := make([]rune, n)
        for i := range b {
                b[i] = letters[rand.Intn(len(letters))]
        }
        return string(b)
}

func main() {
        for i := 1; i < 1000000; i++ {
                //fmt.Println(randSeq(5))
                randSeq(5)
        }
}

http://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang
http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go

Python CURL异步并发HTTP客户端

发布时间:January 7, 2015 // 分类:Python // No Comments

Select模式,类似于php multi curl异步并发,连接数不能太多:

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

import sys
import pycurl
import cStringIO

#最大连接数
num_conn = 20

queue = []
urls = ['https://www.haiyun.me/'] * 10000
for url in urls:
  queue.append(url)

num_urls = len(queue)
num_conn = min(num_conn, num_urls)
print ('----- Getting', num_urls, 'Max conn', num_conn,
       'connections -----')

m = pycurl.CurlMulti()
#初始化handle,可复用
m.handles = []
for i in range(num_conn):
  c = pycurl.Curl()
  c.body = cStringIO.StringIO()
  c.setopt(pycurl.FOLLOWLOCATION, 1)
  c.setopt(pycurl.MAXREDIRS, 5)
  c.setopt(pycurl.CONNECTTIMEOUT, 30)
  c.setopt(pycurl.TIMEOUT, 300)
  c.setopt(pycurl.NOSIGNAL, 1)
  m.handles.append(c)


freelist = m.handles[:]
num_processed = 0
#主循环开始
while num_processed < num_urls:

    #添加请求URL
    while queue and freelist:
      url = queue.pop()
      c = freelist.pop()
      c.setopt(pycurl.URL, url)
      c.setopt(pycurl.WRITEFUNCTION, c.body.write)
      m.add_handle(c)
      c.url = url
      #print url

    #执行请求
    while 1:
      (ret, num_handles) = m.perform()
      if ret != pycurl.E_CALL_MULTI_PERFORM:
        break

    #阻塞一会直到有连接完成
    m.select(1.0)

    #读取完成的连接
    while 1:
      (num_q, ok_list, err_list) = m.info_read()
      for c in ok_list:
        m.remove_handle(c)
        #print c.body.getvalue()
        freelist.append(c)

      for (c, errno, errmsg) in err_list:
        m.remove_handle(c)
        print ('Failed: ', c.url, errno, errmsg)
        freelist.append(c)
      num_processed = num_processed + len(ok_list) + len(err_list)
      if num_q == 0:
        break

for c in m.handles:
  c.fp = None
  c.close()
m.close()

epoll模式,php mult curl不支持此模式,tornado基于pycurl multi_socket_action封装的异步http client,每个client实例维护一个ioloop:

from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop
count = 10000
done = 0
def handle_request(response):
  global done
  done += 1
  if (done == count):
    #结束循环
    IOLoop.instance().stop()

  if response.error:
    print "Error:", response.error
  #else:
    #print response.body
#默认client是基于ioloop实现的,配置使用Pycurl
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient",max_clients=20)
http_client = AsyncHTTPClient()
for i in range(count):
  http_client.fetch("https://www.haiyun.me/", handle_request)
#死循环
IOLoop.instance().start()      

基于epoll的multi curl在lan环境下效果不如select,因为所有Socket都在活跃状态,所有的callback都被唤醒,会导致资源的竞争。既然都是要处理所有的Socket,直接遍历是最简单最有效的方式.
为更好的性能建议libcurl/pycurl开启异步DNS解析

GO HTTP client客户端使用

发布时间:January 6, 2015 // 分类:GO // No Comments

简单:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
)

func main() {
    res, err := http.Get("https://www.haiyun.me/")
    if err != nil {
        return
    }
        //执行close之前一定要判断错误,如没有body会崩溃
    defer res.Body.Close()
        //重用连接一定要执行上和下两步
    body, _ := ioutil.ReadAll(res.Body)
    fmt.Println(string(body))
        fmt.Println(res.Status)
    for k, v := range res.Header {
        fmt.Println(k, strings.Join(v, ""))
    }

}

自定义client,连接读写超时及自定义head:

package main

import (
        "fmt"
        "io/ioutil"
        "net/http"
        "strings"
        "time"
)

var timeout = time.Duration(20 * time.Second)

func dialTimeout(network, addr string) (net.Conn, error) {
        return net.DialTimeout(network, addr, timeout)
}

func main() {
        tr := &http.Transport{
                //使用带超时的连接函数
                Dial: dialTimeout,
                //建立连接后读超时
                ResponseHeaderTimeout: time.Second * 2,
                //直接通过ip访问时设置sni
                TLSClientConfig: &tls.Config{
                     ServerName: "www.haiyun.me",
                },
        }
        client := &http.Client{
                Transport: tr,
                //总超时,包含连接读写
                Timeout: timeout,
        }
        req, _ := http.NewRequest("GET", "https://www.haiyun.me", nil)
        req.Header.Set("Connection", "keep-alive")
        req.Header.Set("Host", "www.haiyun.me")
        res, err := client.Do(req)
        if err != nil {
                return
        }
        defer res.Body.Close()
        body, _ := ioutil.ReadAll(res.Body)
        fmt.Println(string(body))
        for k, v := range res.Header {
                fmt.Println(k, strings.Join(v, ""))
        }

}

使用代理及指定出口IP:

        //使用HTTP PROXY
        proxyUrl, err := url.Parse("http://host:port")
        tr := &http.Transport{
                Proxy: http.ProxyURL(proxyUrl),
        }
        //指定出口IP
        ief, err := net.InterfaceByName("eth0")
        addrs, err := ief.Addrs()
        addr := &net.TCPAddr{
                IP: addrs[0].(*net.IPNet).IP,
        }
        dia := net.Dialer{LocalAddr: addr}
        tr := &http.Transport{
                Dial: dia.Dial,
        }

使用socks5代理:https://github.com/hailiang/socks
http://golang.org/pkg/net/http/#Client
http://golang.org/pkg/net/http/#Transport
http://golang.org/pkg/net/#Dialer

PHP CURL Keepalive连接重用

发布时间:January 4, 2015 // 分类:PHP // No Comments

PHP CURL默认支持keepalive连接复用,单个CURL注意要复用handle才可以:

<?php
   $ch1 = curl_init();
   curl_setopt($ch1, CURLOPT_URL, "https://www.haiyun.me/");
   curl_setopt($ch1, CURLOPT_HTTPHEADER, array(
    'Connection: Keep-Alive',
    'Keep-Alive: 300'
   ));
   curl_setopt($ch1, CURLOPT_FORBID_REUSE, 0);
   curl_setopt($ch1, CURLOPT_RETURNTRANSFER,1);
   curl_exec($ch1);

   curl_setopt($ch1, CURLOPT_URL, "https://www.haiyun.me/");
   curl_setopt($ch1, CURLOPT_RETURNTRANSFER,1);
   curl_exec($ch1);
   curl_close($ch1);

Multi_CURL无需复用handle即默认支持keepalive连接复用,当然也可复用handle,详情见:自用完美php异步并行 multi curl类

$master = curl_multi_init();
$done = curl_multi_info_read($master)
#删除handle
curl_multi_remove_handle($master, $done['handle']);
#复用删除的handle
curl_multi_add_handle($master, $ch);
分类
最新文章
最近回复
  • opnfense: 谢谢博主!!!解决问题了!!!我之前一直以为内置的odhcp6就是唯一管理ipv6的方式
  • liyk: 这个方法获取的IPv6大概20分钟之后就会失效,默认路由先消失,然后Global IPV6再消失
  • 海运: 不好意思,没有。
  • zongboa: 您好,請問一下有immortalwrt設定guest Wi-Fi的GUI教學嗎?感謝您。
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...
归档