如何在Ubuntu14.04上设置OSRM服务器
介绍
OpenStreetMap 项目由数千名用户收集和汇总的原始地图数据组成。 然而,其开放获取政策引发了许多附带项目,这些项目共同涵盖了商业地图服务通常提供的许多功能。
与商业解决方案相比,使用基于 OpenStreetMap 的软件最明显的优势是经济方便,因为 OpenStreetMap 是免费的(包括啤酒和语音)软件。 缺点是需要进行一些配置才能设置工作的 Web 服务。
本教程涵盖了 Web 服务的配置和维护,可以回答以下问题:
- 与给定坐标对最近的街道是什么?
- 从 A 点到 B 点的最佳方式是什么?
- 从 A 点到 B 点开车或步行需要多长时间?
使这成为可能的软件是一个名为 Open Source Routing Machine (OSRM) 的开源项目,它基于 OpenStreetMap 数据。 OpenLayers 等 API 已经提供了在网页中嵌入 OpenStreetMaps 的功能。
先决条件
要遵循本教程,您将需要:
- 一个 Ubuntu 14.04 Droplet。
- 一个sudo非root用户,可以按照本教程创建。 本教程假设您的 sudo 非 root 用户名是
osrm
。 - 推荐 4 GB 的交换空间,如 如何在 Ubuntu 14.04 上添加交换空间。
本教程中的一些操作(例如从源代码构建 OSRM 和预处理阶段)是内存密集型的。 在低内存的 Droplet 上,这些操作可能会失败,这就是为什么需要分配交换文件的原因。
Web 服务在运行时通常不需要额外的交换,因此可以在设置完成后删除此交换文件。 但是,在提供大型地图时,实际上可能需要一个小型交换文件,尤其是在低内存 Droplet 中。 如果是这样,请按照上述教程中的说明使交换文件持久化。
第 1 步 — 更新和安全
在此步骤中,我们将为服务器配置更新。
随着时间的推移,让我们的服务器保持最新和安全是很重要的。 因此,我们首先通过运行以下命令来升级系统中的所有包。
sudo apt-get update sudo apt-get upgrade
然后,我们开启 Ubuntu 的无人值守安全升级。 为此,我们首先需要安装必要的软件包。
sudo apt-get install unattended-upgrades
接下来,通过编辑文件 /etc/apt/apt.conf.d/10periodic
打开自动升级。 我们需要使用 sudo
因为这是一个系统范围的配置文件。
sudo nano /etc/apt/apt.conf.d/10periodic
在文件末尾添加以下行,然后保存并关闭它。
APT::Periodic::Unattended-Upgrade "1";
第 2 步 — 下载地图导出
在此步骤中,我们将选择并下载地图导出。
为了保持一切整洁,创建一个专用目录来构建代码、处理地图等是个好主意。
mkdir osrm
移动到新目录。
cd osrm
我们的网络服务将基于从 OpenStreetMap 导出的地图。 有几种可能的方式来获取地图导出。
第一个选项是将浏览器指向 OpenStreetMap 的 导出页面 ,放大感兴趣的区域,然后单击 导出。 (如果本地导出不起作用,您可能需要使用其他来源之一;Overpass API 是一个不错的选择。)这将允许您精细选择要包含在地图中的区域,并且通常可以减少预处理时间。
但是,您可以从 OSRM 网站获得的导出文件的大小受到限制,因此您可能需要下载现成的导出文件。 许多服务,例如 Geofabrik 和 Mapzen 提供国家和选定大都市地区的更新和现成的地图导出,这对大多数用例都有好处。
无论您使用哪种方法,复制导出的 URL 并将其下载到您的 Droplet。
wget -O map.osm url_of_the_export
现在,您的工作目录中应该有一个名为 map.osm
的文件。
第 3 步 — 安装依赖项
在这一步中,我们将安装 OSRM 的依赖项。
OSRM 必须从源代码编译,所以我们首先需要安装必要的构建机制。 幸运的是,Ubuntu 附带了一个名为 build-essential
的便捷元包,其中包含所需的编译器工具链。 此外,我们将需要 git
来获取 OSRM 源代码,并需要 CMake
来生成构建系统。 以下命令将安装所有 3 个。
sudo apt-get install build-essential git cmake
OSRM 是一个相当复杂的软件,并且还依赖于许多库。 我们可以使用以下命令安装所需的依赖项。
sudo apt-get install libboost-all-dev libtbb-dev liblua5.2-dev libluabind-dev libstxxl-dev libxml2 libxml2-dev libosmpbf-dev libbz2-dev libprotobuf-dev
这些依赖项用于各种事情。 Lua 用于定义自定义速度配置文件脚本,例如 定义在二级公路上,在没有限制的情况下,汽车平均以 80 公里/小时的速度行驶,而在碎石路上,平均速度为 50 公里/小时。 STXXL 是 C++ 标准库的一个版本,它使用磁盘空间作为内存,用于操作大文件。 LibXML 和协议缓冲区用于加载、写入和操作 OSM 文件,而 Boost 和 TBB 用于并行化和表示数据结构。
第 4 步 — 编译 OSRM
在这一步中,我们将获取 OSRM 的源代码并进行编译。
由于 OSRM 选择的构建系统是 CMake,一旦安装了依赖项,生成构建文件和编译 OSRM 就相当容易了。
首先,我们从项目的页面克隆源代码。 该项目由几个存储库组成,处理不同的功能。 我们对后端(服务器端部分)感兴趣。
git clone https://github.com/Project-OSRM/osrm-backend.git
接下来,进入代码目录。
cd osrm-backend
下一步是使用 CMake 生成构建文件。 建议在源代码根目录下的专用 build
目录中构建 OSRM,避免临时构建文件污染源目录。
创建一个构建目录。
mkdir build
进入构建目录。
cd build
最后,我们将使用 cmake
生成构建文件。 该命令将在 build
目录树中生成多个目录和 Makefile。
cmake ..
如果您在此处收到错误,请确保您已通过先决条件中的说明启用交换。
接下来,编译并安装 OSRM。
sudo make install
注意:这可能需要 5 到 10 分钟。
此处必须使用 sudo
构建,因为安装目标将复制系统二进制路径中的一些可执行文件,包括我们需要的一些。 即:
osrm-extract
打开地图文件并对数据运行第一个预处理步骤。osrm-prepare
处理osrm-extract
的输出并根据给定的 Lua 速度曲线计算所有地图边缘的行进时间。osrm-routed
实际的 Web 服务守护进程,它允许我们查询距离和位置。
第 5 步 — 配置 STXXL
在这一步中,我们将为 STXXL 创建一个配置文件。
在运行 Web 服务之前,我们需要对地图导出进行预处理。 因为我们已经在系统路径中安装了所需的二进制文件,所以我们可以在任何地方执行此操作。 出于本教程的目的,我们将在我们创建的 osrm
目录的根目录中运行预处理。
首先,移动到 osrm
目录。
cd ~/osrm
地图预处理非常占用内存。 出于这个原因,OSRM 使用一个名为 STXXL 的库来将其内部操作映射到硬盘上。 STXXL 依赖于一个名为 .stxxl
的配置文件,该文件位于您运行软件的同一目录中,以确定 STXXL 数据结构专用的空间量。 根据我们Droplet的容量和我们希望处理的地图大小,我们需要编写一个合适的.stxxl
配置文件,为操作分配足够的内存。
创建并打开.stxxl
进行编辑。
nano .stxxl
该文件必须包含格式为 disk=path,capacity,access
的单行,其中 path
是要放置分配文件的路径,capacity
是文件的容量,access
是一个文件访问实现。
这是 .stxxl
文件的示例。 您可以将其粘贴到 .stxxl
中,但可能需要根据您使用的地图和 Droplet 的大小来更改文件的大小。 有关高级选项,请参阅 文档 。
disk=/tmp/stxxl,10G,syscall
保存并关闭 .stxxl
。
第 6 步 — 提取地图
在这一步中,我们将提取地图。
预处理的第一步是提取地图。 osrm-extract
命令需要地图导出的路径作为参数,并假定工作目录中存在名为 profile.lua
的合适速度配置文件脚本。 速度配置文件用于确定可以使用哪些可用路线(例如,卡车的速度配置文件可能会禁止某些街道)。
OSRM 后端发行版在存储库的 profiles
目录下包含许多默认速度配置文件脚本。 在本教程中,我们将使用 car.lua
配置文件,它适用于大多数用例
因为速度配置文件脚本可能依赖于配置文件库中定义的一些 Lua 函数,所以我们还通过运行以下两个命令在同一目录中创建指向它的符号链接。
ln -s osrm-backend/profiles/car.lua profile.lua ln -s osrm-backend/profiles/lib
我们的地图导出名为 map.osm
,所以接下来,运行:
osrm-extract map.osm
这一步在预处理目录下生成一堆文件,包括map.osrm
,是下一步的输入。
第 7 步 — 计算旅行时间
在这一步中,我们将计算地图的行程时间。
该步骤由 osrm-prepare
命令执行,该命令再次使用速度剖面脚本来计算地图每条边的行程时间。 为此,请运行以下命令。
osrm-prepare map.osrm
此步骤还会生成 Web 服务所需的一些附加文件,我们将在下一节中设置这些文件。
第 8 步 — 运行和测试 Web 服务
在这一步中,我们将运行 OSRM 并测试它是否可以通过浏览器运行。
OSRM 后端带有一个最终命令 osrm-routed
,它可以读取处理后的地图并允许通过 Web 服务 API 查询它。 为了测试它,运行:
osrm-routed map.osrm
现在,通过将浏览器指向 http://your_server_ip:5000
,您现在应该能够看到正在运行的 Web 服务。 它将显示类似 {"status_message":"Query string malformed close to position 0","status":400}
的错误消息,因为您没有使用正确的查询格式。
作为测试,在地图边界内选择一组经纬度坐标,然后转到以下 URL,将 latitude
和 longitude
替换为您选择的坐标。
http://your_server_ip:5000/nearest?loc=latitude,longitude
您应该会看到类似于以下内容的 JSON 输出:
{ "name": "street_name", "mapped_coordinate": [ latitude, longitude ], "status":0 }
如果您收到错误消息而不是此消息,则您可能选择了地图边界之外的一组坐标,或者您的查询语法可能是错误的。 有关更多可用查询,请查看 服务器 API 。
您现在可以使用 CTRL+C
停止 osrm-routed
。
第 9 步 — 设置 Nginx
在这一步中,我们将设置 Nginx 以使用 osrm-routed
。
我们现在有一个工作的 Web 服务,但是通过指定端口来查询它是很尴尬的。 此外,如果我们决定提供不同的地图或使用不同速度配置文件处理的地图,我们希望避免记住一组端口。
Nginx 是一个高性能的 web 服务器,它也可以作为代理和作为我们 web 服务的网关。 将其设置为与 osrm-routed
一起工作相当容易。
首先,我们安装 Nginx。
sudo apt-get install nginx
接下来,我们为我们的 Web 服务添加一个配置文件。 Nginx 为其特定站点的配置文件使用两个目录:/etc/nginx/sites-available
(所有可以服务的站点)和 /etc/nginx/sites-enabled
(所有正在服务的站点)。 添加站点的标准方法是将其配置文件添加到sites-available
,然后将其符号链接到sites-enabled
。
因此,首先,我们将 OSRM 的配置文件添加到 sites-available
。
sudo nano /etc/nginx/sites-available/osrm.conf
我们的配置文件将定义一个指向我们的 Web 服务的 upstream
和一个侦听端口 80 并将查询的子集重定向到我们的上游的服务器。
将以下配置文件粘贴到 osrm.conf
中。 您将需要指定两个变量,它们在下面突出显示:您的服务器 IP 和路径(将用于访问 Web 服务,如 http://your_server_ip/example_path
)。
upstream osrm { server 0.0.0.0:5000; } server { listen 80; server_name your_server_ip; location /example_path { proxy_pass http://osrm/; proxy_set_header Host $http_host; } }
保存文件后,移至 sites-enabled
目录。
cd /etc/nginx/sites-enabled
然后我们可以链接osrm.conf
文件。
sudo ln -s /etc/nginx/sites-available/osrm.conf
接下来,重新加载配置。
sudo service nginx reload
最后,重启 Nginx。
sudo service nginx restart
现在重新运行 osrm-routed
。
osrm-routed ~/osrm/map.osrm
通过将我们的浏览器指向 http://your_server_ip/example_path
,您应该能够访问 Web 服务。 请注意,您不再需要指定端口。 您现在可以使用 CTRL+C
停止 osrm-routed
。
通过添加更多上游和位置,并通过使用 -p
或 --port
指定端口来运行 osrm-routed
,我们可以运行更多 Web 服务实例,并将它们绑定到不同的路径. 本教程不会对此进行详细介绍,但您可以查看 OSRM 后端文档 了解更多信息。
第 10 步 — 安装和配置 Supervisor
在这一步中,我们将安装和配置 Supervisor 以保持 Nginx 运行,从而允许我们的 Web 服务通过重新启动可用。
Nginx 现在充当我们 Web 服务的网关。 但是,我们是手动启动的,所以如果我们从系统中注销,它就会停止运行。 为了使我们的 Web 服务在重新启动后仍然存在,并且通常使它们从可能的故障中恢复,我们可以使用一个名为 Supervisor 的工具。
Supervisor 是一个流程控制系统,主要负责保持服务正常运行。 设置它很容易。 首先,我们安装 Supervisor 本身。
sudo apt-get install supervisor
然后,我们通过添加一个新的配置文件将我们的 Web 服务添加到由 Supervisor 控制的服务池中。
sudo nano /etc/supervisor/conf.d/osrm.conf
配置文件必须包含我们希望监督的每个 Web 服务的这种形式的定义,并且每个 Web 服务的程序名称必须不同。
将以下配置粘贴到 osrm.conf
文件中,然后保存并关闭它。
[program:osrm] directory=/home/osrm/osrm command=/usr/local/bin/osrm-routed -p 5000 map.osrm user=osrm
这个配置的意思是我们希望用户 osrm
保持命令 /usr/local/bin/osrm-routed -p 5000 map.osrm
运行,并且它必须从指定的目录运行,/home/osrm/osrm
(这就是我们如何可以在命令中指定 map.osrm
作为相对路径)。 在此示例中,我们使用 -p
为 osrm-routed
指定了端口,以便可以通过增加端口来添加多个程序。
保存并关闭文件后,重新启动 Supervisor。
sudo service supervisor restart
然后,我们可以通过运行以下命令检查 Web 服务的状态:
sudo supervisorctl status
如果一切正常,我们应该会看到与此类似的内容
osrm RUNNING pid 12698, uptime 0:00:40
这意味着我们的 Web 服务正在运行。 因为上游指向 5000 端口,Nginx 将能够在指定路径上为其提供服务。
结论
本教程介绍了 OSRM 后端的安装,但在 this page 上提供了更多文档。
在撰写本文时,OSRM 后端仍处于测试阶段,并且对单个查询中可以包含的位置数量有一些硬编码限制(目前为 100,影响时间矩阵 API)。 可以禁用此类限制,但需要修改 osrm-routed
的源代码才能做到这一点。
根据地图的大小和 Droplet 的容量,您可能需要分配更大的交换文件或增加 .stxxl
配置文件中的容量,以便 Web 服务正常运行。 您可能需要测试一些配置以查看最适合您的设置的配置。