【Flink-需求】KafkaSource根据经纬度查询高德API关联位置信息

简介: 【Flink-需求】KafkaSource根据经纬度查询高德API关联位置信息

一、需求分析


1.KafkaSource根据经纬度查询高德API关联位置信息

2.查询一条数据及时没有及时的返回,也可以异步Flink IO


1.1 数据样式


user001,A1,2020-10-10 10:10:10,1,115.963,39.3659

user002,A2,2020-10-10 10:10:10,1,123.544,36.2356

user003,A3,2020-10-10 10:10:10,1,123.568,47.3215


二、高德地图key准备


2.1 进入开发者中心


20200923124600863.png


20200923125235751.png


2.2 引入http的依赖

        <!--引入httpClient的依赖-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>

三、Flink开发


3.1 ActivityBean.java

public class ActivityBean {
    public String uid;
    public String aid;
    public String activityName;
    public String time;
    public int eventType;
    public String province;
    public double longitude;
    public double latitude;
    public ActivityBean() {
    }
    public ActivityBean(String uid, String aid, String activityName, String time, int eventType, double longitude,double latitude,String province) {
        this.uid = uid;
        this.aid = aid;
        this.activityName = activityName;
        this.time = time;
        this.eventType = eventType;
        this.province = province;
        this.latitude = latitude;
        this.longitude = longitude;
    }
    @Override
    public String toString() {
        return "ActivityBean{" +
                "uid='" + uid + '\'' +
                ", aid='" + aid + '\'' +
                ", activityName='" + activityName + '\'' +
                ", time='" + time + '\'' +
                ", eventType=" + eventType +
                ", province='" + province + '\'' +
                ", longitude=" + longitude +
                ", latitude=" + latitude +
                '}';
    }
    public static ActivityBean of(String uid,String aid,String activityName,String time,int eventType,double longitude,double latitude,String province){
        return new ActivityBean(uid,aid,activityName,time,eventType,longitude,latitude,province);
    }
}

3.2 RichMapFunction.java

public class GeoToActivityBeanFunction extends RichMapFunction<String,ActivityBean> {
    private CloseableHttpClient httpClient = null;
    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        httpClient = HttpClients.createDefault();
    }
    @Override
    public ActivityBean map(String line) throws Exception {
        String[] fields = line.split(",");
        String uid = fields[0];
        String aid = fields[1];
        String time = fields[2];
        int eventType = Integer.parseInt(fields[3]);
        String longitude = fields[4];
        String latitude = fields[5];
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=32451f2e804ded152cef65c3cd16452d&location=" + longitude + "," + latitude;
        String province = null;
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpClient.execute(httpGet);
        try{
            int status = response.getStatusLine().getStatusCode();
            if (status == 200) {
                //获取请求的json字符串
                String result = EntityUtils.toString(response.getEntity());
                System.out.println(result);
                JSONObject jsonObject = JSONObject.parseObject(result);
                JSONObject regeocode = jsonObject.getJSONObject("regeocode");
                if (regeocode != null && !regeocode.isEmpty()) {
                    JSONObject address = regeocode.getJSONObject("addressComponent");
                    //获取省市区
                    province = address.getString("province");
                    //String city = address.getString("city");
                    //String businessAreas = address.getString("businessAreas");
                }
            }
        }finally {
            response.close();
        }
        return ActivityBean.of(uid,aid,"未查询数据库",time,eventType,Double.parseDouble(longitude),Double.parseDouble(latitude),province);
    }
    @Override
    public void close() throws Exception {
        super.close();
        httpClient.close();
    }
}


3.3 Flink执行程序

public class GeoQueryLocationActivityCount {
        public static void main(String[] args) throws Exception {
            //1.获取环境
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            //2.kafka配置
            String topic = "activity";
            Properties prop = new Properties();
            prop.setProperty("bootstrap.servers", "192.168.52.200:9092");//多个的话可以指定
            prop.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
            prop.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
            prop.setProperty("auto.offset.reset", "earliest");
            prop.setProperty("group.id", "consumer1");
            FlinkKafkaConsumer<String> myConsumer = new FlinkKafkaConsumer<String>(topic, new SimpleStringSchema(), prop);
            //3.获取数据
            DataStream<String> lines = env.addSource(myConsumer);
            SingleOutputStreamOperator<ActivityBean> beans = lines.map(new GeoToActivityBeanFunction());
            beans.print();
            //7.执行
            env.execute("GeoQueryLocationActivityCount");
        }
}

3.4 测试


1.开启kafka生产者


bin/kafka-console-producer.sh --broker-list 192.168.52.200:9092,1.168.52.201:9092,19


测试结果:


20200923133307141.png

这里我们想一个问题,每次flink查询计算时候,需要依赖于查询高德地图的返回结果,如果没有返回结果,那么是不是flink程序就会一直卡在这里,不会执行下去


四、Flink异步Async I/O

2020092313403940.png


4.1 引入异步的httpclient依赖

        <!--引入高效的异步httpClient的依赖-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpasyncclient</artifactId>
            <version>4.1.4</version>
        </dependency>

4.2 RichAsyncFunction.java

public class AsyncGeoToActivityBeanFunction extends RichAsyncFunction<String,ActivityBean> {
    private transient CloseableHttpAsyncClient httpAsyncClient;
    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        //1.初始化异步的httpclient
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(3000)
                .setConnectTimeout(3000)
                .build();
        httpAsyncClient = HttpAsyncClients.custom()
                .setMaxConnTotal(20)
                .setDefaultRequestConfig(requestConfig).build();
        httpAsyncClient.start();
    }
    @Override
    public void asyncInvoke(String line, ResultFuture<ActivityBean> resultFuture) throws Exception {
        String[] fields = line.split(",");
        String uid = fields[0];
        String aid = fields[1];
        String time = fields[2];
        int eventType = Integer.parseInt(fields[3]);
        String longitude = fields[4];
        String latitude = fields[5];
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=32451f2e804ded152cef65c3cd16452d&location=" + longitude + "," + latitude;
        HttpGet httpGet = new HttpGet(url);
        Future<HttpResponse> future = httpAsyncClient.execute(httpGet, null);
        CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                try{
                    HttpResponse response = future.get();
                    String province = null;
                    if (response.getStatusLine().getStatusCode() == 200) {
                        //获取请求的json字符串
                        String result = EntityUtils.toString(response.getEntity());
                        System.out.println(result);
                        JSONObject jsonObject = JSONObject.parseObject(result);
                        JSONObject regeocode = jsonObject.getJSONObject("regeocode");
                        if (regeocode != null && !regeocode.isEmpty()) {
                            JSONObject address = regeocode.getJSONObject("addressComponent");
                            //获取省市区
                            province = address.getString("province");
                            //String city = address.getString("city");
                            //String businessAreas = address.getString("businessAreas");
                        }
                    }
                    return province;
                } catch (Exception e) {
                    return null;
                }
            }
        }).thenAccept((String province) ->{
            resultFuture.complete(Collections.singleton(ActivityBean.of(uid,aid,null,time,eventType,0,0,province)));
        });
    }
    @Override
    public void close() throws Exception {
        super.close();
        httpAsyncClient.close();
    }
}

4.3 Flink主程序

public class AsyncGeoQueryLocationActivityCount {
        public static void main(String[] args) throws Exception {
            //1.获取环境
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            //2.kafka配置
            String topic = "activity";
            Properties prop = new Properties();
            prop.setProperty("bootstrap.servers", "192.168.52.200:9092");//多个的话可以指定
            prop.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
            prop.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
            prop.setProperty("auto.offset.reset", "earliest");
            prop.setProperty("group.id", "consumer1");
            FlinkKafkaConsumer<String> myConsumer = new FlinkKafkaConsumer<String>(topic, new SimpleStringSchema(), prop);
            //3.获取数据
            DataStream<String> lines = env.addSource(myConsumer);
            // 无序的异步
            SingleOutputStreamOperator<ActivityBean> beans = AsyncDataStream.unorderedWait(lines, new AsyncGeoToActivityBeanFunction(), 0, TimeUnit.MICROSECONDS, 10);
            beans.print();
            //7.执行
            env.execute("AsyncGeoQueryLocationActivityCount");
        }
}

4.4 总结


异步请求MYSQL 【线程池】

异步请求ES

异步请求…

目录
相关文章
|
移动开发 算法 API
淘宝/天猫:使用物流查询API实时显示包裹位置,减少客服咨询量
电商平台中物流咨询占客服工作40%以上,用户频繁追问包裹位置。本文介绍通过物流查询API实现包裹实时追踪,降低75.6%咨询量,提升用户体验与复购率,助力降本增效。(238字)
|
人工智能 JSON API
淘宝/天猫:使用物流查询API实时显示包裹位置,减少客服咨询量
在电商竞争激烈的环境下,淘宝、天猫通过集成物流查询API,实现实时追踪包裹位置,显著减少用户咨询量。本文解析其原理、实现步骤与效益,展示如何以技术手段提升用户体验、降低客服压力,助力平台高效运营。(238字)
|
监控 安全 算法
快递查询API|一次接通2700+快递服务商的物流轨迹
在物流数字化的浪潮中,企业对接多家快递服务商的痛点日益凸显:每新增一家合作物流商,技术团队就要投入 5-7 个工作日进行接口开发,不同服务商的接口协议差异导致系统稳定性差,物流轨迹数据分散在各平台难以整合分析。快递鸟快递查询 API 通过标准化接口架构,创新性地实现了 2700 + 国内外快递服务商的一键接入,将传统模式下的周级开发周期压缩至小时级,彻底重构了物流数据对接的技术范式。
793 0
|
缓存 数据可视化 定位技术
快递鸟快递API技术指南:获取物流轨迹信息与轨迹地图的解决方案
在当今电商竞争激烈的环境中,物流体验已成为提升用户满意度的关键因素。研究表明,超过 75% 的消费者会因物流信息不透明而放弃下单。
2467 1
|
JSON 前端开发 API
汽车配件:使用VIN码查询API精准匹配车型配件,提升用户信任
VIN码是汽车的唯一“身份证”,通过API可精准解析车型信息,实现配件99.5%以上匹配度。本文详解VIN码API的工作流程、技术实现与信任提升价值,助力汽配销售从经验判断迈向数据驱动,降低退货率,提升用户体验与复购。
1342 0
|
机器学习/深度学习 存储 API
唯品会:利用订单地址API校验收货信息,降低因地址错误导致的退货率
在电商中,地址错误常导致退货率升高,影响用户体验与运营效率。唯品会通过集成订单地址API,在用户下单时实时校验收货信息,有效减少因地址问题引发的退货。本文解析该方案的工作原理与实际效益,展示其如何助力平台降低退货率、节约成本并提升用户满意度。
|
JSON 监控 API
淘宝/天猫:使用订单查询API实时追踪包裹状态,自动推送物流通知至用户
在淘宝/天猫平台,通过集成订单查询API实现物流状态实时监控,结合定时轮询与自动推送通知功能,可有效减少用户频繁刷新页面,提升购物体验。本文详解API调用原理、状态判断及Python代码实现,助力开发者构建高效、智能的物流通知系统。
1444 0
|
SQL API 流计算
Flink关系型API简介
在接触关系型API之前,用户通常会采用DataStream、DataSet API来编写Flink程序,它们都提供了丰富的处理能力,以DataStream为例,它有如下这些优点: 富有表现力的流处理,包括但不限于:转换数据,更新状态,定义窗口、聚合,事件时间语义,有状态且保证正确性等; 高度自定义.
1875 0
|
运维 数据处理 数据安全/隐私保护
阿里云实时计算Flink版测评报告
该测评报告详细介绍了阿里云实时计算Flink版在用户行为分析与标签画像中的应用实践,展示了其毫秒级的数据处理能力和高效的开发流程。报告还全面评测了该服务在稳定性、性能、开发运维及安全性方面的卓越表现,并对比自建Flink集群的优势。最后,报告评估了其成本效益,强调了其灵活扩展性和高投资回报率,适合各类实时数据处理需求。
|
存储 分布式计算 数据处理
「48小时极速反馈」阿里云实时计算Flink广招天下英雄
阿里云实时计算Flink团队,全球领先的流计算引擎缔造者,支撑双11万亿级数据处理,推动Apache Flink技术发展。现招募Flink执行引擎、存储引擎、数据通道、平台管控及产品经理人才,地点覆盖北京、杭州、上海。技术深度参与开源核心,打造企业级实时计算解决方案,助力全球企业实现毫秒洞察。
1214 0
「48小时极速反馈」阿里云实时计算Flink广招天下英雄

热门文章

最新文章