把纯真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. Robot Framework变量的使用技巧

    1.变量的使用 变量可以在命令行中设置,个别变量设置使用--variable (-v)选项,变量文件的选择使用--variablefile (-V)选项.通过命令行设置的变量是全局变量,对其所有执行的 ...

  2. 2.3 if switch for等流程控制

    if条件中可以写多个语句,语句的作用域仅限于if,不可在if之外的地方使用 package main import ( "fmt" "io/ioutil" ) ...

  3. 盒子绝对定位 position:foxed ; 居中

    方法1 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...

  4. Redis在windows下的配置

    Redis在windows下的配置(在windows-64下安装redis,请参考微软redis的github:https://github.com/MSOpenTech/redis/releases ...

  5. Python学习 day05

    数据类型划分 数据类型可分为:可变数据类型,不可变数据类型 不可变数据类型:bool.int.str.元祖         --  不可变数据类型又称为可哈希的 可变数据类型:list.dict.se ...

  6. 揭秘TDSQL全时态数据库系统的核心技术

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯技术工程官方号发表在腾讯云+社区 Design 本节讨论T-TDSQL的关键之处,即影响T-TDSQL架构的设计之处.一是新的数据 ...

  7. 深入理解JavaScript系列(33):设计模式之策略模式

    介绍 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. 正文 在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很 ...

  8. js面向对象3

    1.this的使用 核心:在js中,this表示当前对象,“谁”调用了当前函数,“this”就指向了“谁” 语法: Function 类(){ this.属性=值; } 例1.在构造器中,使用this ...

  9. 从Linux服务器下载文件到本地

    通过安装xshell,连接服务器,通过以下命令可以方便的将服务器的文件下载到本地 #下载一个文件 sz filename #下载多个文件 sz filename1 filename2 #下载dir目录 ...

  10. Redis的Lists数据类型

    Lists 就是链表,相信略有数据结构知识的人都应该能理解其结构.使用Lists结构,我们可以轻松地实现最新消息排行等功能.Lists的另一个应用就是消息队列,可以利用Lists的PUSH操作,将任务 ...