MaxCompute中实现IPv4和IPv6地址归属地转换

一、需求场景

大数据平台的成熟使得更多种类的非结构化、半结构化的数据分析成为可能,其中应用非常广泛的一种场景就是把IP地址转换为归属地又是极为常见的一种场景。那么利用MaxCompute如何实现IPv4和IPv6地址向归属地的转换呢?

本文通过MaxCompute UDF方式来实现IPv4和IPv6地址转换。首先,要实现IPv4和IPv6地址与归属地的转换必须要有IP地址库。没错,我们首先要把IPv4和IPv6地址库下载到本地,分别命名为ipv4.txt和ipv6.txt。

二、实现思路

1、将ipv4.txt和ipv6.txt地址库中IPv4和IPv6分别转换为数值和数值字符串做排序。 

2、采用二分查找找到ip所属的范围,根据ipv4.txt和ipv6.txt库输出对应范围所归属的省份和城市信息。

三、UDF编写

MaxCompute如何实现UDF可以参考官方文档:MaxCompute UDF

实现UDF需要继承com.aliyun.odps.udf.UDF类,并实现evaluate方法。

1、实现setup方法加载IP地址库数据,并做初始化

代码片段如下:

    public void setup(ExecutionContext ctx) throws UDFException, IOException {
        //IPV4
        if(ipV4ObjsArray==null)
        {
            BufferedInputStream bufferedInputStream = ctx.readResourceFileAsStream("ipv4.txt");

            BufferedReader br = new BufferedReader(new InputStreamReader(bufferedInputStream));
            ArrayList<IpV4Obj> ipV4ObjArrayList=new ArrayList<>();
            String line = null;
            while ((line = br.readLine()) != null) {
                String[] f = line.split("\\|", -1);
                if(f.length>=5)
                {
                    long startIp = IpUtils.StringToLong(f[0]);
                    long endIp = IpUtils.StringToLong(f[1]);
                    String city=f[3];
                    String province=f[4];
                    IpV4Obj ipV4Obj = new IpV4Obj(startIp, endIp, city, province);
                    ipV4ObjArrayList.add(ipV4Obj);
                }
            }
            br.close();
            List<IpV4Obj> collect = ipV4ObjArrayList.stream().sorted(Comparator.comparing(IpV4Obj::getStartIp)).collect(Collectors.toList());
            ArrayList<IpV4Obj> basicIpV4DataList=(ArrayList)collect;
            IpV4Obj[] ipV4Objs = new IpV4Obj[basicIpV4DataList.size()];
            ipV4ObjsArray = basicIpV4DataList.toArray(ipV4Objs);
        }

        //IPV6
        if(ipV6ObjsArray==null)
        {
            BufferedInputStream bufferedInputStream = ctx.readResourceFileAsStream("ipv6.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(bufferedInputStream));
            ArrayList<IpV6Obj> ipV6ObjArrayList=new ArrayList<>();
            String line = null;
            while ((line = br.readLine()) != null) {
                String[] f = line.split("\\|", -1);
                if(f.length>=5)
                {
                    String startIp = IpUtils.StringToBigIntString(f[0]);
                    String endIp = IpUtils.StringToBigIntString(f[1]);
                    String city=f[3];
                    String province=f[4];
                    IpV6Obj ipV6Obj = new IpV6Obj(startIp, endIp, city, province);
                    ipV6ObjArrayList.add(ipV6Obj);
                }
            }
            br.close();
            List<IpV6Obj> collect = ipV6ObjArrayList.stream().sorted(Comparator.comparing(IpV6Obj::getStartIp)).collect(Collectors.toList());
            ArrayList<IpV6Obj> basicIpV6DataList=(ArrayList)collect;
            IpV6Obj[] ipV6Objs = new IpV6Obj[basicIpV6DataList.size()];
            ipV6ObjsArray = basicIpV6DataList.toArray(ipV6Objs);
        }

    }

2、实现evaluate方法,完成用户数据IP地址到归属地的转换逻辑

代码片段如下:

    public String evaluate(String ip){
        if(ip==null||ip.trim().isEmpty()||!(ip.contains(".")||ip.contains(":")))
        {
            return null;
        }
        int ipV4OrV6=0;
        try {
            ipV4OrV6= IpUtils.isIpV4OrV6(ip);
        } catch (Exception e) {
            return null;
        }
        //如果是IPV4
        if(ipV4OrV6==4)
        {
            int i = binarySearch(ipV4ObjsArray, IpUtils.StringToLong(ip));
            if(i>=0)
            {
                IpV4Obj ipV4Obj = ipV4ObjsArray[i];
                return ipV4Obj.city+","+ipV4Obj.province;
            }else{
                return null;
            }
        }else if(ipV4OrV6==6)//如果是IPV6
        {
            int i = binarySearchIPV6(ipV6ObjsArray, IpUtils.StringToBigIntString(ip));
            if(i>=0)
            {
                IpV6Obj ipV6Obj = ipV6ObjsArray[i];
                return ipV6Obj.city+","+ipV6Obj.province;
            }else{
                return null;
            }
        }else{//如果不符合IPV4或IPV6格式
            return null;
        }

    }

四、UDF函数注册

MaxCompute UDF函数操作可以参考官方文档:MaxCompute函数操作

这里通过两种方式注册MaxCompute UDF函数

1、通过odpscmd

odpscmd客户端下载安装以及使用请参考:客户端

--上次资源:
add file ipv4.txt -f;
add file ipv6.txt -f;
add jar ipv4_ipv6_aton.jar;

--注册函数:
--类名:com.aliyun.odps.udf.udfFunction.IpLocation
create function function_name as 'com.aliyun.odps.udf.udfFunction.IpLocation' using 'ipv4_ipv6_aton.jar, ipv4.txt, ipv6.txt';

MaxCompute中实现IPv4和IPv6地址归属地转换

2、DataWorks

DataWorks注册MaxCompute函数请参考文档:DataWorks注册MaxCompute函数

(1)上传MaxCompute资源

这里需要上传的资源列表:ipv4_ipv6_aton.jar, ipv4.txt, ipv6.txt

参考上述文档上传资源截图如下:
       其中ipv4_ipv6_aton.jar选择 MaxCompute-->JAR

ipv4.txt, ipv6.txt选择MaxCompute-->File

MaxCompute中实现IPv4和IPv6地址归属地转换

MaxCompute中实现IPv4和IPv6地址归属地转换

(2)注册函数

MaxCompute中实现IPv4和IPv6地址归属地转换

MaxCompute中实现IPv4和IPv6地址归属地转换

五、UDF函数测试

MaxCompute中实现IPv4和IPv6地址归属地转换

六、函数源码

MaxCompute IPv4-IPv6地址转换UDF源码请点击下载:

IPv4-IPv6 UDF源码

IPv4-IPv6地址库

七、参考文档

MaxCompute IP地址转换历史参考文档:

1、【大数据技巧】MaxCompute中实现IP地址归属地转换

八、MaxCompute开发者社区交流群

欢迎加入“MaxCompute开发者社区2群”,点击链接MaxCompute开发者社区2群申请申请加入或扫描以下二维码加入。

MaxCompute中实现IPv4和IPv6地址归属地转换




上一篇:阿里云商标安心注册申请有必要吗?不通过退全款商标专家1对1还是很值的


下一篇:阿里云服务器ECS、轻量应用服务器和虚拟主机的区别及对比