Debian 11上的开源路径规划引擎
OSRM (开源路径规划引擎) 是一款适用于开放街道地图(OSM)道路网络的超快路径规划引擎。在之前的教程中,我们讲解了如何在 Debian 12上搭建自托管的开放街道地图 瓦片服务器 和 开源路径规划引擎。本教程将向您展示如何在 Debian 11上设置开源路径规划引擎。 安装和运行开源路径规划引擎所需的最低硬件配置:2 个虚拟中央处理器、1 GB 内存和 8 GB 硬盘空间。
1. 从源代码构建OSRM
安装依赖包。
sudo apt-get update
sudo apt-get -y --no-install-recommends install ca-certificates cmake make git gcc g++ libbz2-dev libxml2-dev wget libzip-dev libboost1.74-all-dev lua5.4 liblua5.4-dev -o APT::Install-Suggests=0 -o APT::Install-Recommends=0
NPROC=${BUILD_CONCURRENCY:-$(nproc)}
sudo ldconfig /usr/local/lib
git clone --branch v2021.3.0 --single-branch https://github.com/oneapi-src/oneTBB.git
cd oneTBB
mkdir build
cd build
cmake -DTBB_TEST=OFF -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
sudo cmake --install .
创建osrm 用户。(该用户无需设置密码。)
sudo useradd -d /srv/osrm -s /bin/bash -m osrm
授予您自己的用户账户权限。请将此处的用户名替换为您的实际Linux用户名。
sudo apt install acl
sudo setfacl -R -m u:username:rwx /srv/osrm/
切换到/srv/osrm/目录。
cd /srv/osrm/
从Github仓库下载OSRM源代码。git clone --branch v5.27.1 https://github.com/Project-OSRM/osrm-backend.git
创建build目录。mkdir build
切换到build目录并配置编译环境。cd build
cmake /srv/osrm/osrm-backend/
sudo fallocate -l 4G /debianswapfile ; sudo chmod 600 /debianswapfile ;
sudo mkswap /debianswapfile && sudo swapon /debianswapfile ;
sudo sed -i '$a\/debianswapfile swap swap defaults 0 0' /etc/fstab
编译源代码。(如果看到TBB警告:已弃用信息,可以忽略。)编译过程需要很长时间,因此您可以使用 screen 命令来保持进程持续运行。
make
[ 0%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/assert.cpp.o [ 0%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/conditional_restrictions.cpp.o [ 0%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/coordinate.cpp.o [ 0%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/coordinate_calculation.cpp.o [ 0%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/exception.cpp.o [ 4%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/fingerprint.cpp.o [ 4%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/geojson_debug_policies.cpp.o [ 4%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/guidance/bearing_class.cpp.o [ 4%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/guidance/entry_class.cpp.o [ 4%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/guidance/turn_lanes.cpp.o [ 4%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/log.cpp.o [ 8%] 正在构建 CXX 对象 CMakeFiles/UTIL.dir/src/util/opening_hours.cpp.o …… /usr/include/boost/function_output_iterator.hpp:14:1: 注意: ‘#pragma message: 此头文件已弃用。 请改用 <boost/iterator/function_output_iterator.hpp>。’ 14 | BOOST_HEADER_DEPRECATED(“<boost/iterator/function_output_iterator.hpp>” | ^~~~~~~~~~~~~~~~~~~~~~~ 13% 正在构建 CXX 对象 CMakeFiles/EXTRACTOR.dir/src/extractor/extractor.cpp.o 在包含自 /usr/include/boost/smart_ptr/detail/sp_thread_sleep.hpp:22 的文件中, yield_k.hpp:23, spinlock_gcc_atomic.hpp:14, spinlock.hpp:42 …… 21% 正在构建 CXX 对象 CMakeFiles/EXTRACTOR.dir/src/extractor/raster_source.cpp.o 21% 正在构建 CXX 对象 CMakeFiles/EXTRACTOR.dir/src/extractor/restriction_graph.cpp.o 21% 正在构建 CXX 对象 CMakeFiles/EXTRACTOR.dir/src/extractor/restriction_parser.cpp.o 21% 正在构建 CXX 对象 CMakeFiles/EXTRACTOR.dir/src/extractor/scripting_environment_lua.cpp.o 在包含自 /usr/include/boost/smart_ptr/detail/sp_thread_sleep.hpp:22 的文件中, 来自 /usr/include/boost/smart_ptr/detail/yield_k.hpp:23, 来自 /usr/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp:14, 来自 /usr/include/boost/smart_ptr/detail/spinlock.hpp:42, 来自 /usr/include/boost/smart_ptr/detail/spinlock_pool.hpp:25, 来自 /usr/include/boost/smart_ptr/shared_ptr.hpp:29, 来自 /usr/include/boost/shared_ptr.hpp:17, 来自 /usr/include/boost/format/alt_sstream.hpp:22, 来自 /usr/include/boost/format.hpp:38, 来自 /srv/osrm/osrm-backend/include/util/exception.hpp:38, 来自 /srv/osrm/osrm-backend/include/extractor/extraction_relation.hpp:4, 来自 /srv/osrm/osrm-backend/include/extractor/scripting_environment_lua.hpp:4, 来自 /srv/osrm/osrm-backend/src/extractor/scripting_environment_lua.cpp:1: /usr/include/boost/detail/no_exceptions_support.hpp:17:1: 注意: ‘#pragma message: 此头文件已弃用。 Use <boost/core/no_exceptions_support.hpp> instead.’ 17 | BOOST_HEADER_DEPRECATED(“<boost/core/no_exceptions_support.hpp>”) | ^~~~~~~~~~~~~~~~~~~~~~~ ……安装二进制文件。
sudo make install
将安装以下二进制文件:- /usr/local/bin/osrm-extract
- /usr/local/bin/osrm-partition
- /usr/local/bin/osrm-customize
- /usr/local/bin/osrm-contract
- /usr/local/bin/osrm-datastore
- /usr/local/bin/osrm-routed
2. 安装 GNU 屏幕工具
下一步,我们需要从开放街道地图中提取道路网络,这可能需要很长时间。您的计算机可能会断开网络连接,因此建议使用 GNU 屏幕工具来保持会话连接。在 Debian 服务器上安装屏幕工具:sudo apt install screen
然后是启动屏幕:screen
首次启动时,您会看到一段介绍文字,只需按下 Enter 结束即可。之后,您就可以像往常一样运行命令了。3. 生成OSRM路径数据
现在我们需要下载开放街道地图数据并使其可用于路径规划。 如果您想要某个国家/州/省/市,请访问 http://download.geofabrik.de。比如,用以下命令下载新泽西的地图数据(148MB)。
wget -c https://download.geofabrik.de/north-america/us/new-jersey-latest.osm.pbf -P /srv/osrm/osrm-backend/
请确保您位于 /srv/osrm/osrm-backend/ 目录中。cd /srv/osrm/osrm-backend/
从开放街道地图中提取图表。osrm-extract new-jersey-latest.osm.pbf --threads=2
默认情况下,它将使用 car.lua 配置文件。现在您可能不需要在服务器上执行其他操作了。由于您正在使用屏幕工具,您可以按 Ctrl+A,松开这两个键,然后按 D 键即可脱离当前的屏幕会话。您将看到类似如下的消息。
[已从 32113.pts-1.focal 分离]
这告诉我之前的屏幕会话 ID 是 32113。您可以注销SSH会话,甚至关闭计算机。不要担心,进程 osrm-extract process 仍在运行。当您需要返回查看进度时,请通过 SSH 连接到服务器并运行以下命令来获取之前的屏幕会话 ID。screen -ls
然后您可以重新连接到之前的屏幕会话。screen -r 32113
完成后,会生成文件名相同但是扩展名不同的文件,包括一个 .osrm 扩展名的文件。运行以下命令,将此图递归分割成单元格。osrm-partition new-jersey-latest.osrm
通过计算所有单元格的路径规划权重来自定义单元格。sudo apt-get install libtbb2
osrm-customize new-jersey-latest.osrm
osrm-routed --algorithm=MLD new-jersey-latest.osrm
如您所见,它监听的是TCP端口 5000。4. 创建 systemd 服务
我们可以使用手动方式运行OSRM 路径规划引擎: osrm-routed --algorithm=MLD new-jersey-latest.osrm,但更方便的做法是在后台以系统守护进程运行 osrm-routed。按下 Ctrl+C 停止当前进程,并使用以下命令为 osrm-routed 创建一个系统守护进程。
sudo vi /etc/systemd/system/osrm-routed.service
将以下几行内容添加到文件中。[Unit]
Description=Open Source Routing Machine
Wants=network-online.target
After=network.target network-online.target
[Service]
ExecStart=/usr/local/bin/osrm-routed --algorithm=MLD /srv/osrm/osrm-backend/new-jersey-latest.osrm
User=osrm
Group=osrm
Restart=always
RestartSec=5s
[Install]
WantedBy=multi-user.target
sudo chown osrm:osrm /srv/osrm/osrm-backend/ -R
现在我们可以启动并启用 osrm-routed 系统守护进程了。sudo systemctl start osrm-routed
sudo systemctl enable osrm-routed
systemctl status osrm-routed
5. 设置反向代理
我们可以将Nginx 网络服务器配置为 osrm-routed 服务的反向代理,这样我们就可以使用域名来访问路径规划服务,并启用 HTTPS 加密。sudo apt install nginx
然后为 OSRM 创建服务器块文件。sudo vi /etc/nginx/conf.d/osr.conf
将以下内容添加到文件中。将 osr.your-domain.com 替换为您的实际域名,并且不要忘记为其创建 DNS A 记录。
server {
listen 80;
listen [::]:80;
server_name osr.your-domain.com osr.eastus.cloudapp.azure.com;
access_log /var/log/nginx/osrm.access;
error_log /var/log/nginx/osrm.error;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
}
}
保存并关闭文件。然后测试 Nginx 配置。
sudo nginx -t
如果测试成功,请重新加载 Nginx 以使更改生效。sudo systemctl reload nginx
6. 启用 HTTPS
我们可以通过安装 Let’s Encrypt 颁发的免费TLS证书来启用 HTTPS。首先,在 Debian 11上安装 Let’s Encrypt 客户端(certbot)。sudo apt install certbot
因为我们使用的是 Nginx 网络服务器,所以我们也需要安装 Nginx 插件。sudo apt install python3-certbot-nginx
然后运行以下命令来获取和安装 TLS 证书。sudo certbot --nginx --agree-tos --email your-account@example.com -d osr.your-domain.com -d osr.eastus.cloudapp.azure.com
其中:- --nginx: 使用 Nginx 插件。
- --agree-tos: 同意服务条款。
如果您希望在运行 Certbot 后同时保留 HTTP 和 HTTPS,您可以删除返回 301 和 404 的行,然后再添加回原始的反向代理行。
7. 将 OSRM 与滑动地图集成
要将OSRM与滑动地图集成,我们可以使用名为 Leaflet Routing Machine 的插件。首先,将 Leaflet routing machine 的 JavaScript 和 CSS 文件添加到您的滑动地图中。请注意,它们应该放在 Leaflet 主 JavaScript 文件之后。下载 leaflet-routing-machine.css、 leaflet-routing-machine.min.js、 leaflet.routing.icons.png 和 routing-icon.png 到 dist 文件夹:
sudo mkdir /var/www/html/dist
cd /var/www/html/dist
sudo wget https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet-routing-machine.css
sudo wget https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet-routing-machine.js
sudo wget https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet.routing.icons.png
sudo wget https://unpkg.com/leaflet-routing-machine@latest/dist/routing-icon.png
<html>
<head>
....
....
<link rel="stylesheet" href="dist/leaflet-routing-machine.css" />
<script src="dist/leaflet-routing-machine.js"></script>
</head>
<body>
....
....
</body>
</html>
接下来,将以下几行代码添加到 <script>...</script> HTML 正文中的代码片段中。
start = [39.891215, -74.968797]; // 斯普林代尔农场
end = [39.89478, -74.93103]; // 美国银行
L.Routing.control({
serviceUrl: 'https://osr.your-domain.com/route/v1',
waypoints: [
L.latLng(start[0], start[1]),
L.latLng(end[0], end[1])
],
routeWhileDragging: true
}).addTo(map);
像这样:
<html>
<head>
....
....
<link rel="stylesheet" href="dist/leaflet-routing-machine.css" />
<script src="dist/leaflet-routing-machine.js"></script>
</head>
<body>
<div id="map"></div>
<script>
....
....
start = [39.891215, -74.968797]; // 斯普林代尔农场
end = [39.89478, -74.93103]; // 美国银行
L.Routing.control({
serviceUrl: 'https://osr.your-domain.com/route/v1',
waypoints: [
L.latLng(start[0], start[1]),
L.latLng(end[0], end[1])
],
routeWhileDragging: true
}).addTo(map);
</script>
</body>
</html>
保存并关闭文件。 然后在浏览器中重新加载地图,你应该会在右上角看到一个控制面板,您可以与路径交互。
您可以拖动地图上的航点, OSRM 将自动重新计算路线。
如何更新路线数据
停止 osrm-routed。sudo systemctl stop osrm-routed
切换到 osrm 用户。
sudo -u osrm -i
请确保您位于 /srv/osrm/osrm-backend/ 目录中。cd /srv/osrm/osrm-backend/
删除旧地图文件:rm new-jersey-latest.osm.pbf
下载新地图。wget http://download.geofabrik.de/north-america/us/new-jersey-latest.osm.pbf
从开放街道数据中提取图表。osrm-extract new-jersey-latest.osm.pbf --threads=2
运行以下命令,将此图递归地分割成单元格。osrm-partition new-jersey-latest.osrm
通过计算所有单元格的路径规划权重来自定义单元格。osrm-customize new-jersey-latest.osrm
退出 osrm 用户。exit
重启 osrm-routed。sudo systemctl restart osrm-routed
交换空间
Swappiness 是 Linux 内核的一个参数,它控制 Linux 将空闲进程交换到硬盘上的交换空间的频率。交换空间使用率(swappiness)的值介于 0 到 100 之间。值越低,Linux 使用交换空间的频率就越低;值越高,Linux 使用交换空间的频率就越高。Ubuntu 和 Debian 的默认值为 60,这意味着当计算机使用 40% 的物理内存时,Linux 内核才会开始使用交换空间。
您可以使用以下命令检查当前值。cat /proc/sys/vm/swappiness
建议将交换分区(swappiness)的值设置得较低,以便 Linux 内核尽可能多地使用物理内存。编辑 /etc/sysctl.d/99-sysctl.conf 文件。sudo vi /etc/sysctl.d/99-sysctl.conf
在此文件的末尾,添加以下行。vm.swappiness=1
这告诉 Linux 内核,只有当物理内存使用率达到 99% 或以上时才使用交换空间。你也可以将该值设置为 0,这样 Linux 就只会在所有物理内存都用完时才使用交换空间。vm.swappiness=0
保存并关闭文件。然后运行以下命令以应用更改。sudo sysctl -p
请注意,htop 工具无法准确报告 Linux 系统上的可用内存量。它不会将共享内存、缓冲区或缓存计算在内。要显示 Linux 服务器上的准确可用内存量,请使用 top 或 free -m 命令。故障排除
如果您的 nginx 状态显示以下错误:nginx.service: 无法从 /run/nginx.pid 解析PID: 无效参数
可能的原因和解决方案:- 时序问题:Systemd 可能在 Nginx 完全启动并将其 PID 写入文件之前尝试读取PID文件。
- 解决方案:在 systemd 服务配置中添加少量延迟,以便让 Nginx 有更多时间启动。为 Nginx 服务创建一个覆盖文件:
sudo mkdir -p /etc/systemd/system/nginx.service.d
printf "[Service]\nExecStartPost=/bin/sleep 0.1\n" | sudo tee /etc/systemd/system/nginx.service.d/override.conf
sudo systemctl daemon-reload
sudo systemctl restart nginx
下一步
希望这篇教程能帮助你在 Debian 11 上搭建开源路径规划引擎。你可能还需要设置带有网页界面的地理编码服务器来提供搜索功能。使用此推荐链接注册 Hetzner 即可获得 20 美元的云服务积分。