使用 laravel 队列即时进行 Google 地理编码

Posted

技术标签:

【中文标题】使用 laravel 队列即时进行 Google 地理编码【英文标题】:Google geocoding on the fly using laravel queue 【发布时间】:2017-08-31 19:27:00 【问题描述】:

我有大约 100 个 GPS 设备每 10 秒定期发送坐标。我的客户想要实时反向地理编码来查看他的车辆以及表格视图上的位置。在添加地理编码脚本之前,我已经设置了一个队列以将所有这些数据包保存在 db 中,如下所示

    使用 websocket 接收 TCP IP 消息

    public function onMessage(ConnectionInterface $conn, $msg) 
     //get the message
     // send the dispatch job to save it in db
     $this->dispatch(new SavePacketsToDb($key_1, json_encode(
                                            array(
                                                'company_id' => $key_1,
                                                'vehicle_id' => $company->vehicle_id,
                                                'tracker_id' => $company->tracker_id,
                                                'lat' => $lat,
                                                'lng' => $lng,
                                                'imei' => $imei,
                                                'datetime' => $datetime,
                                                                                )
                             )));   
    

    运行队列

    public function handle()
            $lat=$obj->lat;
            $lng=$obj->lng;
    
    
    
    $url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" . $lat . "," . $lng . "&key=mykey";
                    $json = file_get_contents($url);
                    $data = json_decode($json);
                    $status = $data->status;
                    $address = '';
                    if ($status == "OK")   
                       // echo "from geocode address";
                        echo $address = $data->results[0]->formatted_address;
                    
                    else
                        $address=NULL;
                    
    
         //save to db
      
    

如果我在队列中包含此地理编码,我只是担心它是否适用于 1000 个并发设备,有没有更好的方法?

【问题讨论】:

我觉得可以通过supervisor的config设置numprocs=8来限制并发进程的数量。不完全确定这是否是您想要的。 我看到了一些至少可以改善这一点的方法,但给你一些建议:1)你可以检查一个工作是否仍在(等待)车辆队列中并获得当您在队列中放置新工作时,摆脱任何待处理的车辆工作 2)您可能不想每次都调用 google api。例如,考虑检查坐标是否仍然相同,因为如果是这种情况,则车辆没有移动并且您已经知道位置。 三思而后行;当前端需要显示实际位置时,我只会对谷歌进行 API 调用。 (只需保存坐标) google api 的使用有每天和每秒的限制,因此通过按需点击 api(当我们需要在前端显示并将坐标保存在数据库中时)。 敲击 Google API 是否有意义,或者有本地调用来反向地理编码位置是否有意义?请参阅 download.geonames.org/export/dump 或 zipcodedownload.com - 我想答案可以归结为您需要的结果有多准确? 【参考方案1】:

我们开发了类似的东西,最初使用 google maps api,但我搬走了,因为它在我的位置(巴西)不太准确。

对于谷歌地图,如果您没有发现任何准确性问题,您可以排队并处理数据,但每天的数量有限(请注意我相信的 2500 次查找限制)免费服务或购买所需的查找。

如果您需要所有设备的实时信息,您需要在谷歌地图中支付更大的费用,我会为此使用排队服务。我们使用 RabbitMQ 队列来接收坐标,然后我们有小型客户端/工作人员从队列中获取项目并处理它们(还涉及其他 API)。

我不相信您的客户会整天在屏幕前,所以也许您可以:

始终存储坐标 仅当他/她/某人在该页面中时才运行 API 调用 在屏幕的查看区域(在前端查看的地图边界)中使用 GPS 坐标优先系统 在尽力而为的窗口上运行低优先级坐标(基于 API 可用性、使用限制等),甚至可能在非优先级的辅助 API 上运行

顺便说一句,我们正在使用 HereMaps,它是付费的,但您可以创建一个为期 3 个月的演示/测试帐户。

【讨论】:

【参考方案2】:

我认为对每个坐标进行反向地理编码效率很低。我宁愿尝试在某些包中对一些坐标进行分组,并使用类似 thephpleague/geotools 批处理 api 的东西来对这些数据进行反向地理编码,如果需要的话。

而且我不会只依赖谷歌地图。我认为一个好的建议是有一个后备,因为谷歌地图不知道每个地址,你可以在速率限制中轻松退出(有这么多的数据)。看看 [geocoder-php/Geocoder] 包,它支持许多地理编码服务。

请注意一个网站说明:我是维护这个项目的人之一。

【讨论】:

以上是关于使用 laravel 队列即时进行 Google 地理编码的主要内容,如果未能解决你的问题,请参考以下文章

Google App Engine 302状态仅限生产中的任务队列

用消息队列实现即时通讯2

用消息队列实现即时通讯3

IM即时通讯开发MQ消息队列

在 laravel 4 中即时克隆数据库或运行 sql 转储

使用 Laravel Livewire 和 Laravel Fortify 进行登录