把纯真IP库读到内存,纯真IP库本来就是有序的,然后每次请求二分查找就行,44WIP查找十几次就搞定了

dispatch_mode最好写3,不然做服务的时候,会导致进程任务分配不均匀。

max_request 处理请求数量累加到达该值会重启处理进程,防止内存泄露

worker_num 根据内存和服务处理能力可以自己设置跑几个工作进程。

swoole.php

<?php
require 'ipmatch.php';
class IpServer
{
protected $iptables; protected static $cityList = array (
0 =>
array (
'bj' => '北京',
),
1 =>
array (
'sh' => '上海',
),
2 =>
array (
'tj' => '天津',
),
3 =>
array (
'cq' => '重庆',
),
4 =>
array (
'gz' => '广州',
'sz' => '深圳',
'dg' => '东莞',
'zhuhai' => '珠海',
'shantou' => '汕头',
'foshan' => '佛山',
'jiangmen' => '江门',
'zhongshan' => '中山',
'huizhou' => '惠州',
'maoming' => '茂名',
'shaoguan' => '韶关',
'zhanjiang' => '湛江',
),
5 =>
array (
'cd' => '成都',
'zigong' => '自贡',
'luzhou' => '泸州',
'deyang' => '德阳',
'mianyang' => '绵阳',
'nanchong' => '南充',
'liangshan' => '凉山',
),
6 =>
array (
'hz' => '杭州',
'nb' => '宁波',
'wenzhou' => '温州',
'jiaxing' => '嘉兴',
),
7 =>
array (
'gy' => '贵阳',
'liupanshui' => '六盘水',
'zunyi' => '遵义',
),
8 =>
array (
'sy' => '沈阳',
'dl' => '大连',
'anshan' => '鞍山',
'fushun' => '抚顺',
),
9 =>
array (
'nj' => '南京',
'su' => '苏州',
'wx' => '无锡',
'xuzhou' => '徐州',
),
10 =>
array (
'fz' => '福州',
'xm' => '厦门',
'putian' => '莆田',
),
11 =>
array (
'sjz' => '石家庄',
'tangshan' => '唐山',
'handan' => '邯郸',
'xingtai' => '邢台',
'baoding' => '保定',
'zhangjiakou' => '张家口',
'chengde' => '承德',
),
12 =>
array (
'zz' => '郑州',
'luoyang' => '洛阳',
'pingdingshan' => '平顶山',
'jiaozuo' => '焦作',
'hebi' => '鹤壁',
'xinxiang' => '新乡',
'anyang' => '安阳',
),
13 =>
array (
'cc' => '长春',
'jilin' => '吉林',
),
14 =>
array (
'hrb' => '哈尔滨',
'qiqihaer' => '齐齐哈尔',
'jixi' => '鸡西',
'hegang' => '鹤岗',
'shuangyashan' => '双鸭山',
),
15 =>
array (
'jn' => '济南',
'qd' => '青岛',
'wei' => '威海',
'zibo' => '淄博',
'zaozhuang' => '枣庄',
'dongying' => '东营',
'yantai' => '烟台',
),
16 =>
array (
'hf' => '合肥',
'wuhu' => '芜湖',
'bengbu' => '蚌埠',
'maanshan' => '马鞍山',
'anqing' => '安庆',
),
17 =>
array (
'nn' => '南宁',
'gl' => '桂林',
'liuzhou' => '柳州',
'wuzhou' => '梧州',
'qinzhou' => '钦州',
),
18 =>
array (
'hn' => '海口',
'sanya' => '三亚',
'wuzhishan' => '五指山',
),
19 =>
array (
'nmg' => '呼和浩特',
'baotou' => '包头',
'wuhai' => '乌海',
),
20 =>
array (
'ty' => '太原',
'datong' => '大同',
'yangquan' => '阳泉',
'changzhi' => '长治',
),
21 =>
array (
'yc' => '银川',
'shizuishan' => '石嘴山',
'wuzhong' => '吴忠',
'guyuan' => '固原',
'zhongwei' => '中卫',
),
22 =>
array (
'lz' => '兰州',
'jinchang' => '金昌',
'baiyin' => '白银',
'tianshui' => '天水',
'wuwei' => '武威',
),
23 =>
array (
'xa' => '西安',
'tongchuan' => '铜川',
'baoji' => '宝鸡',
'xianyang' => '咸阳',
'weinan' => '渭南',
),
24 =>
array (
'xn' => '西宁',
'haidong' => '海东',
'haibei' => '海北',
'huangnan' => '黄南',
'hainan' => '海南',
'guoluo' => '果洛',
'yushu' => '玉树',
'haixi' => '海西',
),
25 =>
array (
'wh' => '武汉',
'huangshi' => '黄石',
'xiangfan' => '襄樊',
'shiyan' => '十堰',
'jingzhou' => '荆州',
'yichang' => '宜昌',
'jingmen' => '荆门',
),
26 =>
array (
'cs' => '长沙',
'zhuzhou' => '株洲',
'xiangtan' => '湘潭',
'hengyang' => '衡阳',
'shaoyang' => '邵阳',
),
27 =>
array (
'nc' => '南昌',
'jingdezhen' => '景德镇',
'pingxiang' => '萍乡',
'jiujiang' => '九江',
),
28 =>
array (
'km' => '昆明',
'qujing' => '曲靖',
'yuxi' => '玉溪',
),
29 =>
array (
'xj' => '乌鲁木齐',
'kelamayi' => '克拉玛依',
'tulufan' => '吐鲁番',
'hami' => '哈密',
'hetian' => '和田',
),
30 =>
array (
'xz' => '拉萨',
'changdu' => '昌都',
'shannan' => '山南',
'rikaze' => '日喀则',
'naqu' => '那曲',
'ali' => '阿里',
'linzhi' => '林芝',
),
); protected static $provinceList = array (
4 => '广东',
5 => '四川',
6 => '浙江',
7 => '贵州',
8 => '辽宁',
9 => '江苏',
10 => '福建',
11 => '河北',
12 => '河南',
13 => '吉林',
28 => '云南',
15 => '山东',
16 => '安徽',
17 => '广西',
18 => '海南',
19 => '内蒙古',
20 => '山西',
21 => '宁夏',
22 => '甘肃',
23 => '陕西',
24 => '青海',
25 => '湖北',
26 => '湖南',
27 => '江西',
14 => '黑龙江',
29 => '新疆',
30 => '西藏', ); function run()
{
$serv = swoole_server_create("192.168.2.165", 9898);
swoole_server_set($serv, array(
'worker_num' => 2,
'max_request' => 10000,
'dispatch_mode' => 3
));
swoole_server_handler($serv, 'onWorkerStart', array($this, 'onStart'));
swoole_server_handler($serv, 'onConnect', array($this, 'onConnect'));
swoole_server_handler($serv, 'onReceive', array($this, 'onReceive'));
swoole_server_handler($serv, 'onClose', array($this, 'onClose'));
swoole_server_handler($serv, 'onWorkerStop', array($this, 'onShutdown'));
swoole_server_start($serv);
} public function onStart($serv)
{
echo 'read iptables from file'.PHP_EOL;
$this->iptables = file('ip.txt');
} public function onConnect($serv, $fd, $from_id)
{
} public function onReceive($serv, $fd, $from_id, $data)
{
$ret = match_ip($data, $this->iptables, self::$cityList, self::$provinceList);
$serv->send($fd, $ret);
$serv->close($fd);
} public function onClose($serv, $fd, $from_id)
{
} public function onShutdown($serv)
{
echo 'shutdown server and free resource'.PHP_EOL;
unset($this->iptables);
}
} $server = new IpServer();
$server->run();

有一点需要注意下的PHP 的整形是个有符号的Long 所以溢出时候会产生负数,需要处理一下。

ipmatch.php

<?php

function ip2num($ip) {
return sprintf("%u",ip2long($ip));
} function match_ip($ip, $data, $cityList, $provinceList) {
$count = count($data);
$ip = ip2num($ip);
$i=0;
$j=$count-1;
while ($i<=$j) {
$mid = intval(($i+$j)/2);
$arr = preg_split('/\s+/', $data[$mid]);
$midip = ip2num(trim($arr[0]));
if ($midip>$ip) {
$j = $mid-1;
} else if ($midip<$ip) {
$i = $mid+1;
} else {
break;
}
} $temp = preg_split('/\s+/', $data[$j]);
$beginip = ip2num(trim($temp[0]));
$endip = ip2num(trim($temp[1]));
if ($ip>=$beginip&&$ip<=$endip) {
unset($temp[0]);
unset($temp[1]);
foreach ($temp as $t) {
$keyword = trim($t);
if (!empty($keyword)) {
break;
}
}
$keyword = iconv('GBK', 'UTF-8', $keyword);
//和省匹配
foreach ($provinceList as $code=>$name) {
if (strstr($keyword, $name)) {
$provinceName = $name;
$provinceCode = $code;
break;
}
}
if (isset($provinceCode)) {
//和省内城市匹配
foreach ($cityList[$provinceCode] as $code=>$name) {
if (strstr($keyword, $name)) {
return '1:'.$code.':'.$name;
}
}
} else {
//和所有城市匹配
foreach ($cityList as $arr) {
foreach ($arr as $code=>$name) {
if (strstr($keyword, $name)) {
return '1:'.$code.':'.$name;
}
}
}
}
if (isset($provinceCode)) {
return '2:'.$provinceCode.':'.$provinceName;
}
return '-1::';
}
} ?>

启动SERVER

php swoole.php

测试

client.php

class runtime
{
var $StartTime = 0;
var $StopTime = 0; function get_microtime()
{
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
} function start()
{
$this->StartTime = $this->get_microtime();
} function stop()
{
$this->StopTime = $this->get_microtime();
} function spent()
{
return round(($this->StopTime - $this->StartTime) * 1000, 1);
} } function ip2City($ip)
{
$fp = fsockopen("192.168.2.165",9898, $errno, $errstr, 1);
if (!$fp) {
echo $errno . $errstr.PHP_EOL;
} else {
fwrite($fp, $ip);
$out = '';
while (!feof($fp)) {
$out .= fgets($fp).PHP_EOL;
}
}
fclose($fp);
return $out;
}
$test = array();
$notMatch = array();
//读文件
$ips = file('access_wap_misc_20140115_part1.log');
foreach ($ips as $line) {
$ip = explode(' ', $line);
$test[] = $ip[0];
}
////随即生成
//for ($i=0;$i<10000;$i++) {
// $test[] = rand(1,255).'.'.rand(1,255).'.'.rand(1,255).'.'.rand(1,255);
//}
////指定IP
//$test[] = '122.11.37.92'; $match_count = 0;
$runtime= new runtime;
$runtime->start();
foreach ($test as $ip) {
$city = ip2City($ip);
if (strlen($city)>1) {
// $arr = explode(':',$city);
echo $ip .' locate '. $city;
$match_count++;
}else {
$notMatch[] = $ip;
}
}
$runtime->stop();
echo "match ".count($test)." ips total run time: ".$runtime->spent()." milliseconds".PHP_EOL;
echo "hits ganji citys:".$match_count .' ips'.PHP_EOL;

经测试一个IP匹配1.5毫秒。注意,PHP 的各种socket都是秒级超时,不知道是不是和select的默认最小超时时间是1秒有关系,只有高版本的curl库支持毫秒级超时。

总的来说 swoole 可以让PHP以很低编程成本起个服务。为这么草根的语言添加了新生活力~

PHP Swoole 基于纯真IP库根据IP匹配城市的更多相关文章

  1. Java使用纯真IP库获取IP对应省份和城市

    原文:http://blog.csdn.net/chwshuang/article/details/78027873?locationNum=10&fps=1 Java使用纯真IP库获取IP对 ...

  2. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

  3. 使用新浪IP库获取IP详细地址

    使用新浪IP库获取IP详细地址 <?php class Tool{ /** * 获取IP的归属地( 新浪IP库 ) * * @param $ip String IP地址:112.65.102.1 ...

  4. python 利用淘宝IP库 查询IP归属地

    #coding:utf-8 from django.test import TestCase import json import urllib ip = "114.114.114.114& ...

  5. php利用淘宝IP库获取用户ip地理位置

    我们查ip的时候都是利用ip138查询的,不过那个有时候是不准确的,还不如自己引用淘宝的ip库来查询,这样准确度还高一些.不多说了,介绍一下淘宝IP地址库的使用. 淘宝IP地址库 淘宝公布了他们的IP ...

  6. 使用纯真IP库获取用户端地理位置信息

    引言 在一些电商类或者引流类的网站中经常会有获取用户地理位置信息的需求,下面我分享一个用纯真IP库获取用户地理位置信息的方案. 正文 第一步:本文的方案是基于纯真IP库的,所以首先要去下载最新的纯真I ...

  7. lib-qqwry v1.0 发布 nodejs解析纯真IP库(qqwry.dat)

    lib-qqwry是当初学习node时用来练手的一个模块,用来解析纯真IP库的 现在发一个v1.0版本弥补我当时稚嫩的代码. 意外收获是,整理代码后发现,相比v0.x版本 急速模式下的效率提升大概20 ...

  8. qqwry - 纯真ip库的golang服务

    qqwry 纯真 IP 库的一个服务.通过http提供一个ip地址归属地查询支持 软件介绍 我们大家做网站的时候,都会需要将用户的IP地址转换为归属地址功能,而之前的作法大都是从硬盘的数据文件中读取, ...

  9. 转载纯真ip库

    http://blog.csdn.net/clin003/archive/2007/08/14/1743157.aspx 利用 QQWry.Dat 实现 IP 地址高效检索(PHP) 根据 LumaQ ...

随机推荐

  1. requests模块的一些总结

    一.cookie模拟登录的三种方式 #!/usr/bin/env python # -*- coding: utf-8 -*- #author tom import requests post_url ...

  2. JavaScript学习笔记1_基础与常识

    1.六种数据类型 5种基础的:Undefined,Null,Boolean,Number,String(其中Undefined派生自Null) 1种复杂的:Object(本质是一组无序键值对) 2.字 ...

  3. html自定义垂直导航菜单

    html自定义垂直导航菜单(目前只支持上级+下级两级菜单) 由于工作的需要,昨天花了三个多小时的事件整理了一份关于垂直导航二级菜单,可以通过js配置的方式初始化菜单box(测试环境:chrome 49 ...

  4. 记录树莓派静态IP修改

    1.操作:修改dhcpcd.conf文件 sudo nano /etc/dhcpcd.conf interface eth0 static ip_address=192.168.0.10/24 sta ...

  5. AUTO Uninstaller【教程】AUTODESK系列软件MAYA,3DSMAX,CAD,INVENTOR,REVIT修复卸载工具 Windows x64位

    小伙伴是不是遇到 MAYA/CAD/3DSMAX/INVENTOR/REVIT 安装失败或者安装不了的问题了呢?AUTODESK系列软件着实令人头疼,MAYA/CAD/3DSMAX/INVENTOR/ ...

  6. 关于跨域登录中获取COOKIES解析BUG

    FormsAuthentication.Decrypt   报错    Length of the data to decrypt is invalid. 关于同域名不同服务器之间的登录,加密配置说明 ...

  7. TOJ 1885 Triangles

    Description It is always very nice to have little brothers or sisters. You can tease them, lock them ...

  8. Bootstrap 斜体、文本对齐、缩略图、地址、列表等

    目录1.标题2.页面主体3.强调    a.小号文本    b.着重    c.斜体    d.对齐class    e.强调class4.缩略语5.地址6.列表    a.无序列表    b.有序列 ...

  9. 如何让JS变量和字符串拼接后,是变量而不是字符串

    今天有个非常有趣的事,因为我需要用JS去实现多语言,就是我在JS文件里定义了不同的变量,尝试用变量拼接字符串组成之前定义好的变量名称,结果拼接之后,显示的却是字符串,而不是变量,所以无法解析 zh_t ...

  10. Python项目中如何优雅的import

    Python项目中如何优雅的import 前言 之前有一篇关于Python编码规范的随笔, 但是写的比较杂乱, 因为提到了import语句, 在篇文章中, 我专门来讲Python项目中如何更好的imp ...