一、需求场景
大数据平台的成熟使得更多种类的非结构化、半结构化的数据分析成为可能,其中应用非常广泛的一种场景就是把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地址库数据,并做初始化
代码片段如下:
publicvoidsetup(ExecutionContextctx) throwsUDFException, IOException { //IPV4if(ipV4ObjsArray==null) { BufferedInputStreambufferedInputStream=ctx.readResourceFileAsStream("ipv4.txt"); BufferedReaderbr=newBufferedReader(newInputStreamReader(bufferedInputStream)); ArrayList<IpV4Obj>ipV4ObjArrayList=newArrayList<>(); Stringline=null; while ((line=br.readLine()) !=null) { String[] f=line.split("\\|", -1); if(f.length>=5) { longstartIp=IpUtils.StringToLong(f[0]); longendIp=IpUtils.StringToLong(f[1]); Stringcity=f[3]; Stringprovince=f[4]; IpV4ObjipV4Obj=newIpV4Obj(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=newIpV4Obj[basicIpV4DataList.size()]; ipV4ObjsArray=basicIpV4DataList.toArray(ipV4Objs); } //IPV6if(ipV6ObjsArray==null) { BufferedInputStreambufferedInputStream=ctx.readResourceFileAsStream("ipv6.txt"); BufferedReaderbr=newBufferedReader(newInputStreamReader(bufferedInputStream)); ArrayList<IpV6Obj>ipV6ObjArrayList=newArrayList<>(); Stringline=null; while ((line=br.readLine()) !=null) { String[] f=line.split("\\|", -1); if(f.length>=5) { StringstartIp=IpUtils.StringToBigIntString(f[0]); StringendIp=IpUtils.StringToBigIntString(f[1]); Stringcity=f[3]; Stringprovince=f[4]; IpV6ObjipV6Obj=newIpV6Obj(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=newIpV6Obj[basicIpV6DataList.size()]; ipV6ObjsArray=basicIpV6DataList.toArray(ipV6Objs); } }
2、实现evaluate方法,完成用户数据IP地址到归属地的转换逻辑
代码片段如下:
publicStringevaluate(Stringip){ if(ip==null||ip.trim().isEmpty()||!(ip.contains(".")||ip.contains(":"))) { returnnull; } intipV4OrV6=0; try { ipV4OrV6=IpUtils.isIpV4OrV6(ip); } catch (Exceptione) { returnnull; } //如果是IPV4if(ipV4OrV6==4) { inti=binarySearch(ipV4ObjsArray, IpUtils.StringToLong(ip)); if(i>=0) { IpV4ObjipV4Obj=ipV4ObjsArray[i]; returnipV4Obj.city+","+ipV4Obj.province; }else{ returnnull; } }elseif(ipV4OrV6==6)//如果是IPV6 { inti=binarySearchIPV6(ipV6ObjsArray, IpUtils.StringToBigIntString(ip)); if(i>=0) { IpV6ObjipV6Obj=ipV6ObjsArray[i]; returnipV6Obj.city+","+ipV6Obj.province; }else{ returnnull; } }else{//如果不符合IPV4或IPV6格式returnnull; } }
四、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.IpLocationcreate function function_name as'com.aliyun.odps.udf.udfFunction.IpLocation' using 'ipv4_ipv6_aton.jar, ipv4.txt, ipv6.txt';
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
(2)注册函数
五、UDF函数测试
六、函数源码
MaxCompute IPv4-IPv6地址转换UDF源码请点击下载:
七、参考文档
MaxCompute IP地址转换历史参考文档:
1、【大数据技巧】MaxCompute中实现IP地址归属地转换
八、MaxCompute开发者社区交流群
欢迎加入“MaxCompute开发者社区2群”,点击链接MaxCompute开发者社区2群申请申请加入或扫描以下二维码加入。