-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #282 from leihua996/master
add xdb erlang implementation
- Loading branch information
Showing
15 changed files
with
627 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# ip2region xdb erlang 查询客户端 | ||
|
||
### 简介 | ||
该bingding以erlang语言实现xdb查询客户端,基于Erlang OTP Application,查询逻辑由ip2region_worker工作进程实现,支持配多个工作进程来进行负载均衡。 | ||
|
||
### 应用配置 | ||
该应用可配置的参数在ip2region.app.src中,如下: | ||
``` erlang | ||
{env,[ | ||
{poolargs, [ | ||
{size, 1}, %% 工作进程默认数量 | ||
{max_overflow, 5} %% 工作进程最大数量 | ||
]} | ||
]} | ||
``` | ||
|
||
### 编译 | ||
|
||
``` | ||
$ rebar3 compile | ||
``` | ||
### 运行 | ||
将xdb文件放到priv目录下,然后启动erlang节点: | ||
``` | ||
$ rebar3 shell | ||
``` | ||
在erlang shell中调用xdb:search/1接口查询Ip地址信息, 该接口支持以list格式字符串、bianry格式字符串、tuple和整数表示的IP地址,如下: | ||
``` | ||
1> xdb:search("1.0.8.0"). | ||
[20013,22269,124,48,124,24191,19996,30465,124,24191,24030, | ||
24066,124,30005,20449] | ||
2> | ||
3> io:format("~ts~n", [xdb:search("1.0.8.0")]). | ||
中国|0|广东省|广州市|电信 | ||
io:format("~ts~n", [xdb:search(<<"1.0.8.0">>)]). | ||
中国|0|广东省|广州市|电信 | ||
4> io:format("~ts~n", [xdb:search({1,0,8,0})]). | ||
中国|0|广东省|广州市|电信 | ||
6> io:format("~ts~n", [xdb:search(16779264)]). | ||
中国|0|广东省|广州市|电信 | ||
``` | ||
|
||
### 使用方法 | ||
* 在rebar.config中引入依赖 | ||
``` | ||
{deps, [ | ||
ip2region | ||
]}. | ||
``` | ||
* 启动ip2region Application | ||
``` | ||
...... | ||
application:ensure_started(ip2region), | ||
...... | ||
``` | ||
|
||
* 调用xdb:search/1接口查询IP信息 | ||
``` | ||
...... | ||
ip2region:search("1.0.8.0"), | ||
...... | ||
``` | ||
|
||
### 单元测试 | ||
|
||
``` | ||
$ rebar3 eunit | ||
===> Verifying dependencies... | ||
===> Analyzing applications... | ||
===> Compiling ip2region | ||
===> Performing EUnit tests... | ||
=INFO REPORT==== 17-Jan-2023::11:52:59.920155 === | ||
XdbFile:/home/admin/erl-workspace/ip2region/binding/erlang/_build/test/lib/ip2region/priv/ip2region.xdb | ||
.... | ||
Finished in 0.074 seconds | ||
4 tests, 0 failures | ||
``` | ||
|
||
### 基准测试 | ||
``` | ||
$ cd benchmarks/ | ||
$ sh xdb-benchmark.sh | ||
===> Verifying dependencies... | ||
===> Analyzing applications... | ||
===> Compiling ip2region | ||
Erlang/OTP 24 [erts-12.3.2.2] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit] | ||
Eshell V12.3.2.2 (abort with ^G) | ||
1> =INFO REPORT==== 17-Jan-2023::11:37:35.631095 === | ||
XdbFile:/home/admin/erl-workspace/ip2region/binding/erlang/_build/default/lib/ip2region/priv/ip2region.xdb | ||
===> Booted ip2region | ||
===> Evaluating: "xdb_benchmark:main(\"../../data/ip.merge.txt\"), init:stop()." | ||
CPU info: | ||
model name : AMD EPYC 7K62 48-Core Processor | ||
cache size : 512 KB | ||
cpu MHz : 2595.124 | ||
bogomips : 5190.24 | ||
cores/threads : 2 | ||
Erlang info: | ||
system_version:Erlang/OTP 24 [erts-12.3.2.2] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit] | ||
load test data use 4.835593s | ||
start run benchmark tests | ||
search from file: | ||
ip count:683844, | ||
total time: 28.201699s, | ||
search 24248.326315375536 times per second, | ||
use 41.23995969841075 micro second per search | ||
search from cache: | ||
ip count:683844, | ||
total time: 0.671801s, | ||
search 1017926.4395259906 times per second, | ||
use 0.9823892583688677 micro second per search | ||
benchmark test finish | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/bash | ||
|
||
cd .. | ||
|
||
rebar3 shell --eval="xdb_benchmark:main(\"../../data/ip.merge.txt\"), init:stop()." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
-ifndef(IP2REGION_HRL). | ||
-define(IP2REGION_HRL, true). | ||
|
||
-define(NONE, none). | ||
-define(APP_NAME, ip2region). | ||
|
||
-define(XDB_VECTOR_INDEX, ets_xdb_vector_index). | ||
-define(XDB_SEGMENT_INDEX, ets_xdb_segement_index). | ||
-define(IP2REGION_CACHE, ets_ip2region_cache). | ||
|
||
|
||
-define(XDB_HEADER_SIZE, 256). | ||
-define(XDB_VECTOR_COLS, 256). | ||
-define(XDB_VECTOR_INDEX_SIZE, 8). | ||
-define(XDB_VECTOR_INDEX_COUNT, (16#10000)). %% 256*256 | ||
|
||
-define(XDB_SEGMENT_INDEX_SIZE, 14). | ||
|
||
-define(IP2REGION_POOL, ip2region_pool). | ||
|
||
-ifndef(IF). | ||
-define(IF(C, T, F), case (C) of true -> (T); false -> (F) end). | ||
-define(IF(C, T), ?IF(C, T, skip)). | ||
-endif. | ||
|
||
-endif. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{erl_opts, [ | ||
debug_info, | ||
export_all, | ||
nowarn_export_all | ||
]}. | ||
|
||
{plugins, [rebar3_hex, rebar3_ex_doc]}. | ||
|
||
{deps, [ | ||
poolboy | ||
]}. | ||
|
||
{shell, [ | ||
% {config, "config/sys.config"}, | ||
{apps, [ip2region]} | ||
]}. | ||
|
||
{ex_doc, [ | ||
{extras, ["README.md"]}, | ||
{main, "README.md"}, | ||
{source_url, "https://github.com/leihua996/ip2region/tree/master/binding/erlang"} | ||
]}. | ||
|
||
{hex, [{doc, ex_doc}]}. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{"1.2.0", | ||
[{<<"poolboy">>,{pkg,<<"poolboy">>,<<"1.5.2">>},0}]}. | ||
[ | ||
{pkg_hash,[ | ||
{<<"poolboy">>, <<"392B007A1693A64540CEAD79830443ABF5762F5D30CF50BC95CB2C1AAAFA006B">>}]}, | ||
{pkg_hash_ext,[ | ||
{<<"poolboy">>, <<"DAD79704CE5440F3D5A3681C8590B9DC25D1A561E8F5A9C995281012860901E3">>}]} | ||
]. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{application, ip2region, | ||
[{description, "ip2region xdb client application"}, | ||
{vsn, "0.1.0"}, | ||
{registered, []}, | ||
{mod, {ip2region_app, []}}, | ||
{applications, | ||
[kernel, | ||
stdlib | ||
]}, | ||
{env,[ | ||
{poolargs, [ | ||
{size, 1}, | ||
{max_overflow, 5} | ||
]} | ||
]}, | ||
{modules, []}, | ||
|
||
{licenses, ["Apache-2.0"]}, | ||
{links, [{"Github", "https://github.com/leihua996/ip2region/tree/master/binding/erlang"}]} | ||
]}. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
%%%------------------------------------------------------------------- | ||
%% Copyright 2022 The Ip2Region Authors. All rights reserved. | ||
%% Use of this source code is governed by a Apache2.0-style | ||
%% license that can be found in the LICENSE file. | ||
%% | ||
%% @doc | ||
%% @end | ||
%%%------------------------------------------------------------------- | ||
|
||
-module(ip2region_app). | ||
|
||
-behaviour(application). | ||
|
||
-export([start/2, stop/1]). | ||
|
||
start(_StartType, _StartArgs) -> | ||
ip2region_sup:start_link(). | ||
|
||
stop(_State) -> | ||
ok. | ||
|
||
%% internal functions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
%%%------------------------------------------------------------------- | ||
%% Copyright 2022 The Ip2Region Authors. All rights reserved. | ||
%% Use of this source code is governed by a Apache2.0-style | ||
%% license that can be found in the LICENSE file. | ||
%% | ||
%% @doc ip2region top level supervisor. | ||
%% @end | ||
%%%------------------------------------------------------------------- | ||
-module(ip2region_sup). | ||
-behaviour(supervisor). | ||
-include("ip2region.hrl"). | ||
|
||
-export([start_link/0]). | ||
|
||
-export([init/1, create_table/0]). | ||
|
||
-define(SERVER, ?MODULE). | ||
|
||
start_link() -> | ||
{ok, SupPid} = supervisor:start_link({local, ?SERVER}, ?MODULE, []), | ||
{ok, _PoolPid} = start_ip2region_pool(SupPid), | ||
{ok, SupPid}. | ||
|
||
%% sup_flags() = #{strategy => strategy(), % optional | ||
%% intensity => non_neg_integer(), % optional | ||
%% period => pos_integer()} % optional | ||
%% child_spec() = #{id => child_id(), % mandatory | ||
%% start => mfargs(), % mandatory | ||
%% restart => restart(), % optional | ||
%% shutdown => shutdown(), % optional | ||
%% type => worker(), % optional | ||
%% modules => modules()} % optional | ||
init([]) -> | ||
create_table(), | ||
SupFlags = #{strategy => one_for_one, | ||
intensity => 10, | ||
period => 5}, | ||
ChildSpecs = [], | ||
{ok, {SupFlags, ChildSpecs}}. | ||
|
||
%% internal functions | ||
%% | ||
create_table() -> | ||
Opts = [named_table, set, public, {read_concurrency, true}, {keypos, 1}], | ||
ets:new(?XDB_VECTOR_INDEX, Opts), | ||
ets:new(?XDB_SEGMENT_INDEX, Opts), | ||
ets:new(?IP2REGION_CACHE, Opts). | ||
|
||
start_ip2region_pool(Sup) -> | ||
{ok, PoolArgsCfg} = application:get_env(poolargs), | ||
PoolName = ?IP2REGION_POOL, | ||
PoolArgs = [{strategy, fifo}, {name, {local, PoolName}}, {worker_module, ip2region_worker} | PoolArgsCfg], | ||
WorkerArgs = [], | ||
ChildSpecs = poolboy:child_spec(PoolName, PoolArgs, WorkerArgs), | ||
supervisor:start_child(Sup, ChildSpecs). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
%%%------------------------------------------------------------------- | ||
%% Copyright 2022 The Ip2Region Authors. All rights reserved. | ||
%% Use of this source code is governed by a Apache2.0-style | ||
%% license that can be found in the LICENSE file. | ||
%% | ||
%% @doc | ||
%% ip2region utils | ||
%% @end | ||
%%%------------------------------------------------------------------- | ||
-module(ip2region_util). | ||
-export([ipv4_to_n/1]). | ||
|
||
|
||
ipv4_to_n(IntIp) when is_integer(IntIp) -> IntIp; | ||
ipv4_to_n({A, B, C, D}) -> | ||
<<N:32>> = <<A, B, C, D>>, | ||
N; | ||
ipv4_to_n(Ip) when is_binary(Ip) -> | ||
ipv4_to_n(binary_to_list(Ip)); | ||
ipv4_to_n(Ip) when is_list(Ip) -> | ||
case inet_parse:address(Ip) of | ||
{ok, Addr} -> | ||
ipv4_to_n(Addr); | ||
_ -> | ||
{error, bad_ip_format} | ||
end. |
Oops, something went wrong.