
后端GIS图计算【免费下载链接】osrm-backendOpen Source Routing Machine - C backend项目地址https://gitcode.com/gh_mirrors/os/osrm-backend点击查看免费下载导读osrm-routed是 OSRMOpen Source Routing MachineC 后端的核心 HTTP 路由服务进程负责加载预处理完成的数据集并通过 HTTP API 对外提供 route、table、nearest、match、trip、tile 等路由服务。除了命令行参数之外它还可以通过三个环境变量SHM_LOCK_DIR、SIGNAL_PARENT_WHEN_READY、DISABLE_ACCESS_LOGGING在进程启动与运行期间精细控制共享内存锁目录、就绪通知机制和访问日志输出。本文以 docs/routed.md 为主干结合源码实现与单元测试逐一拆解这三个环境变量的语义、底层调用链及在 Docker/Kubernetes、零停机升级、高流量生产环境中的实战用法帮助你更深入地掌控 osrm-routed 的运行行为。一、总览osrm-routed 与环境变量在进入细节之前先厘清 osrm-routed 在 OSRM 工具链中的位置。按官方工具文档的定位osrm-routed是HTTP 服务器加载预处理好的数据集并对外提供 OSRM HTTP API见 docs/tools.md#L124-L130。它本身已拥有丰富的命令行参数--ip、--port、--algorithm、--shared-memory、--mmap、各类查询上限等而环境变量则是一种不侵入命令行、便于被容器编排系统Docker/Kubernetes统一注入的配置通道。当前仓库中docs/routed.md 定义了三个受支持的环境变量环境变量核心作用典型场景SHM_LOCK_DIR指定共享内存锁文件目录容器化环境持久化锁文件SIGNAL_PARENT_WHEN_READY就绪后向父进程发送SIGUSR1无停机热升级 osrm-routed 二进制DISABLE_ACCESS_LOGGING关闭 HTTP 访问日志输出高流量生产环境下面逐一展开。二、SHM_LOCK_DIR掌控共享内存锁文件目录2.1 官方语义根据 docs/routed.md如果设置了SHM_LOCK_DIR环境变量OSRM 将使用它作为共享内存锁文件shared memory lock files的存放目录而不是系统临时目录system temporary directory。这在容器化环境Docker/Kubernetes中尤其有用——当从共享内存加载数据集时锁文件目录应该在容器重启后依然保留。2.2 源码级原理锁文件与共享内存的绑定关系为什么锁文件如此关键看 src/storage/shared_memory.cpp#L17-L31 的实现就明白了struct OSRMLockFile { OSRMLockFile(const ProjID proj_id) { std::filesystem::path filename std::filesystem::path(osrm- std::to_string(proj_id) .lock); lock_file getLockDir() / filename; } ... };OSRM 在 Linux 上使用 System V 共享内存xsi_shared_memory而共享内存段的标识 key 正是由xsi_key xsi_key(lock_file, proj_id)src/storage/shared_memory.cpp#L37-L38从锁文件的路径推导而来。也就是说锁文件路径一旦因系统临时目录清理如systemd-tmpfiles-clean而丢失共享内存段的 key 就再也无法重建osrm-routed --shared-memory与osrm-datastore之间的共享内存访问将直接断裂。这正是 include/storage/shared_memory.hpp#L41-L51 中注释反复强调的动机Priority:SHM_LOCK_DIRenv var /dev/shm/osrm-uid/(Linux) user home.osrmdirectory exception. Avoids lock files being cleaned by system temp directory cleanup tools (e.g. systemd-tmpfiles-clean), which would break shared memory access.2.3 目录选择优先级getLockDir() 的完整决策链src/storage/shared_memory.cpp#L231-L292 中的getLockDir()定义了严格的优先级顺序SHM_LOCK_DIR环境变量最高优先级若设置先调用tryLockDir()尝试创建目录std::filesystem::create_directories并校验其确实是一个目录若目录不可用直接抛出异常并附带提示SHM_LOCK_DIR directory is not usable: ...若可用则立即返回。只有一次日志Using shared memory lock directory: ...通过static bool logged保证只打一次。Linux 平台默认候选/dev/shm/osrm-uid//dev/shm是 RAM 后端 tmpfs始终是本地的且不会被systemd-tmpfiles-clean清理只会在重启时清空——这与 System V 共享内存段的生命周期恰好匹配。用户主目录回退$HOME/.osrmWindows 上HOME未设置时回退到USERPROFILE。全部失败则抛异常Could not determine a shared memory lock directory. Set SHM_LOCK_DIR to a writable directory.2.4 单元测试验证优先级与覆盖行为unit_tests/storage/shared_memory.cpp 用一组BOOST_AUTO_TEST_CASE直接验证了上述决策链get_lock_dir_respects_shm_lock_dir_envL67-L79设置SHM_LOCK_DIR后getLockDir()精确返回该路径get_lock_dir_shm_lock_dir_takes_priorityL81-L95即使同时设置了HOMESHM_LOCK_DIR依然胜出注释明确写道 Even if HOME is set, SHM_LOCK_DIR should winget_lock_dir_uses_dev_shm_on_linuxL97-L112仅 Linux未设置SHM_LOCK_DIR时返回路径必须包含/dev/shm/osrm-且目录真实存在get_lock_dir_uses_home_as_fallbackL114-L135非 Linux 平台或/dev/shm不可用时回退到$HOME/.osrm。测试中还通过 RAII 风格的EnvGuardL10-L61对SHM_LOCK_DIR、HOME进行设置/恢复/清除保证测试间互不污染——这也可以作为你排查环境变量问题的参考环境变量是按进程继承的务必确认注入的目标进程确实收到了该值。2.5 实战用法容器化环境在 Docker/Kubernetes 中最稳妥的用法是显式挂载一个持久卷并指向SHM_LOCK_DIR# 启动 osrm-datastore 写入共享内存 osrm-datastore --dataset-name mydataset data.osrm # 启动 osrm-routed 从共享内存加载 SHM_LOCK_DIR/var/lib/osrm-shm-locks \ osrm-routed --shared-memory --dataset-name mydataset --algorithm MLD挂载方式Kubernetes 示例语义将同一持久卷同时挂载到osrm-datastore与所有osrm-routed副本的/var/lib/osrm-shm-locks路径使锁文件在 Pod 重建后依然存在从而保证共享内存段的 key 稳定可复现。需要注意SHM_LOCK_DIR指向的目录必须是可写的否则tryLockDir()失败会导致osrm-routed启动阶段直接抛异常退出。三、SIGNAL_PARENT_WHEN_READY实现零停机热升级3.1 官方语义根据 docs/routed.md如果设置了SIGNAL_PARENT_WHEN_READY环境变量osrm-routed在完全启动并进入等待请求状态后会向父进程发送USR1信号即SIGUSR1。这一机制可用于在不产生任何服务停机、不丢失任何请求的前提下将 osrm-routed 热升级到新二进制。3.2 源码级原理信号发送的确切时机看 src/tools/routed.cpp#L387-L402 的实现信号发送时机非常精确std::packaged_taskint() server_task( [] { routing_server-Run(); return 0; }); auto future server_task.get_future(); std::thread server_thread(std::move(server_task)); #ifndef _WIN32 util::Log() running and waiting for requests; if (std::getenv(SIGNAL_PARENT_WHEN_READY)) { kill(getppid(), SIGUSR1); } sigwait(wait_mask, sig);关键点服务线程server_thread通过routing_server-Run()真正开始运行并监听请求后主线程才打印running and waiting for requests并检查环境变量——也就是说信号只在服务已就绪、可以接收请求的那一刻发出发出信号后主线程进入sigwait阻塞等待SIGINT/SIGQUIT/SIGTERML361-L368 中pthread_sigmask已预先屏蔽这三个信号收到信号后按顺序执行优雅关闭routing_server-Stop()→ 等待服务线程最多 2 秒future.wait_for(std::chrono::seconds(2))→ 超时则std::exit(EXIT_FAILURE)L415-L425该分支仅存在于非 Windows 平台#ifndef _WIN32Windows 走SetConsoleCtrlHandler的控制台控制处理路径L404-L410。3.3 实战用法无停机热升级的编排方式借助该信号典型的零停机升级编排如下在 systemd、Supervisor 或自研进程管理器中实现父进程旧版 osrm-routed 的上级先确保数据已准备就绪——若使用共享内存加载需先由osrm-datastore加载新数据集以设置了SIGNAL_PARENT_WHEN_READY1的方式启动新版osrm-routed 进程让它接管同一个端口或通过负载均衡切换流量父进程阻塞等待SIGUSR1一旦收到说明新进程已完成初始化、正在监听请求此刻流量切换不会产生空窗期随后向旧进程发送SIGTERM/SIGINT由旧进程走上述优雅关闭流程等待在途请求处理完毕服务线程最多 2 秒后退出。由于就绪信号是在服务线程已Run()之后才发出的因此没有任何请求会落到尚未准备好的进程上这正是文档所述no incoming requests will be lost的底层保证。需要注意如果旧进程仍在同一端口监听切换前需先释放端口例如通过SO_REUSEPORT或多进程负载均衡方案否则新进程可能因端口占用而启动失败——此时SIGNAL_PARENT_WHEN_READY永远不会触发编排器应设置超时兜底。四、DISABLE_ACCESS_LOGGING高流量下的日志开关4.1 官方语义根据 docs/routed.md如果设置了DISABLE_ACCESS_LOGGING环境变量osrm-routed不会向标准输出打印任何 HTTP 请求日志。这在高流量场景下非常有用——避免每请求一行的日志成为 I/O 与磁盘瓶颈。4.2 源码级原理日志的触发位置与格式访问日志的产生点在 src/server/request_handler.cpp#L280-L300位于响应发送之后SendResponse(result, current_reply, response_status); if (!std::getenv(DISABLE_ACCESS_LOGGING)) { TIMER_STOP(request_duration); std::time_t t std::time(nullptr); const auto referrer HeaderOrEmpty(current_request, bhttp::field::referer); const auto agent HeaderOrEmpty(current_request, bhttp::field::user_agent); util::Log() std::put_time(std::localtime(t), %d-%m-%Y %H:%M:%S) TIMER_MSEC(request_duration) ms remote_address.to_string() (referrer.empty() ? - : referrer) (agent.empty() ? - : agent) current_reply.result_int() // request_string // POST: append the JSON body (compacted to one line) so the request // can be replayed from the log alone. (is_post !util::LogPolicy::GetInstance().IsMute() ? CompactJsonForLog(current_request.body()) : std::string()); }由此可以得出判定方式只要环境变量存在无论取值是什么字符串std::getenv返回非空指针即视为设置日志即被跳过DISABLE_ACCESS_LOGGING1与DISABLE_ACCESS_LOGGINGanything效果相同。默认开启未设置时每个请求都会输出一行日志格式为时间戳(日-月-年 时:分:秒) 耗时ms 远端地址 Referrer User-Agent HTTP状态码 请求串对 POST 请求还会追加压缩为单行的 JSON body前提是日志策略未被静音见util::LogPolicy::GetInstance().IsMute()使得日志本身即可用于回放请求。影响范围只关闭访问日志不影响其他日志启动日志、错误日志、[disabled dataset error]警告等仍正常输出见 L310-L311。4.3 实战用法# 高流量生产环境关闭每请求访问日志仅保留启动/错误日志 DISABLE_ACCESS_LOGGING1 osrm-routed data.osrm --port 5000 --threads 8适用前提与注意点该开关牺牲可观测性换取吞吐。关闭后你将无法从标准输出追踪请求来源、耗时与状态码若仍需监控应在上游接入独立的访问日志/指标采集如 Nginx/Envoy 层或外部监控探针。与--verbosity命令行选项相互独立--verbosity控制全局日志级别见 src/tools/routed.cpp#L128-L134Release 默认INFO、Debug 默认DEBUG而DISABLE_ACCESS_LOGGING仅针对 HTTP 访问日志这一条输出。五、与 osrm-routed 其他配置的配合关系环境变量并非孤立存在它们与 osrm-routed 的命令行配置共同决定服务行为。为了在生产中正确组合建议同时理解以下 CLI 侧的关键配置完整参数表见 docs/tools.md#L132-L164Server网络层Flag短选项默认值说明--ip address-i0.0.0.0监听地址--port n-p5000监听端口--keepalive-timeout s-k5HTTP keep-alive 超时秒持久连接单连接最多 512 个请求--trial完整启动后立即退出用于校验数据集Data loading数据加载Flag短选项默认值说明--algorithm name-aCH路由算法CHContraction Hierarchy或MLDMulti-Level Dijkstra--shared-memory-soff从osrm-datastore管理的共享内存区域加载数据——这是SHM_LOCK_DIR生效的典型场景--mmap-moff直接内存映射数据文件而非载入 RAM--dataset-name name要连接的共享内存数据集名配合--shared-memory--disable-feature-dataset name跳过可选数据集以省内存可选项ROUTE_STEPS、ROUTE_GEOMETRYQuery limits查询上限防御性配置--max-viaroute-size默认 500、--max-trip-size/--max-table-size/--max-matching-size/--max-nearest-size默认 100、--max-alternatives默认 3MLD 专用、--max-matching-radius/--default-radius默认-1即 unlimited、--max-header-size与--max-request-body-size默认 0 即按坐标上限自动推导后者在 docs/http.md#L114-L115 有说明。几个值得注意的组合关系SHM_LOCK_DIR只在--shared-memory或等价场景下才有意义不使用共享内存加载时不存在锁文件生命周期问题该变量会被忽略。同时注意 src/tools/routed.cpp#L270-L281 中的校验--shared-memory与base.osrm路径参数不能同时给出会打印Shared memory settings conflict with path settings.并拒绝启动。SIGNAL_PARENT_WHEN_READY与--trial互斥--trial模式下初始化完成后直接退出L381-L384不会进入服务线程也就不会发送就绪信号。DISABLE_ACCESS_LOGGING与 POST 请求体回放关闭后依赖日志回放调试 POST 请求的流程将不可用需改用抓包或上游网关日志。六、小结docs/routed.md中定义的三枚环境变量分别对应 osrm-routed 运行期的三个关键剖面SHM_LOCK_DIR—— 共享内存加载模式的地基通过固定锁文件目录保证共享内存段 key 的稳定性源码决策链为SHM_LOCK_DIR /dev/shm/osrm-uid/Linux $HOME/.osrm有对应的单元测试覆盖unit_tests/storage/shared_memory.cppSIGNAL_PARENT_WHEN_READY—— 生产级零停机升级的信号握手协议就绪信号在服务线程Run()之后、主线程sigwait之前发出src/tools/routed.cpp#L396-L402DISABLE_ACCESS_LOGGING—— 高流量场景的吞吐开关仅关闭响应后那一条访问日志输出src/server/request_handler.cpp#L282-L300错误与启动日志不受影响。三者均以环境变量存在即生效的方式工作天然适配 Docker/Kubernetes 的env注入模式无需改动命令行或配置文件即可在部署层面完成开关控制。将它们与osrm-routed的 CLI 配置docs/tools.md#L124-L164组合使用即可构建一套具备共享内存加载、无停机升级与高吞吐能力的生产级路由服务部署方案。进一步了解 HTTP API 细节可参考 docs/http.md完整工具链用法见 docs/tools.md。赞分享后端GIS图计算【免费下载链接】osrm-backendOpen Source Routing Machine - C backend项目地址https://gitcode.com/gh_mirrors/os/osrm-backend点击查看免费下载相关推荐eventuate-tram-examples-customers-and-orders中的领域驱动设计实体与值对象实践eventuate tram examples customers and orders中的领域驱动设计实体与值对象实践 在微服务架构中领域驱动设计DDDFairy-Stockfish贡献指南如何参与开源项目开发并支持棋类AI研究Fairy Stockfish贡献指南如何参与开源项目开发并支持棋类AI研究 Fairy Stockfish是一款基于Stockfish的 棋类变体引擎 支游戏开发深度学习Hydra 配置定制指南日志、工作目录、帮助信息与运行时变量的深度解析Hydra 配置定制指南日志、工作目录、帮助信息与运行时变量的深度解析 导读Hydra 的框架能力远不止配置组合——它自身的日志配置、输出目录模式、应用帮助开发工具后端CLI上一篇CANN/asc-devkit连续对齐搬出StoreAlign下一篇Kitematic自定义容器模板快速部署常用应用的技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考