GraphHopper Distance Matrix Là Cái Gì?
Answer-first: GraphHopper distance matrix chính là điểm kết nối /matrix API trực thuộc thư viện tìm đường mã nguồn mở (open-source routing engine) GraphHopper. Nó sẽ thu nạp thông tin tọa độ của N điểm trạm và ói trả về nguyên một ma trận kết quả kích cỡ N×N chứa toàn bộ dữ liệu thời gian di chuyển (tính theo giây) cộng thêm độ dài lộ trình khoảng cách (tính theo mét) rạch ròi bám dựa trên lưới đường xá giao thông thực tế được cung cấp bởi bản đồ OpenStreetMap — tuyệt vời nhất là mọi thứ này sẽ tính phí zero (hoàn toàn miễn phí) khi bạn chọn cách tự mang về nhà cắm điện xài (self-hosted). Thử thách với lượng chạm mốc 100 điểm dừng giao hàng (delivery stops), cỗ máy này dễ dàng xử lý phay vèo toàn vẹn 10,000 cặp lộ trình đôi chỉ trong ngưỡng chớp mắt dưới 50 mili-giây (50ms) dẫu cho chạy tàng tàng trên một con máy chủ ảo VPS hạng bèo.
Quyển cẩm nang này sẽ moi móc trình bày phơi bày cho hết sạch sành sanh mọi công phu thứ liệu bạn cần để mang được em GraphHopper distance matrix gầm gú chạy ngon lành ngoài vùng production: cài cắm Docker, sử dụng /matrix API, xài Custom Models để vẽ đường cho tụi xe tải/xe máy, dựng trạm thu nhận cache H3-based cho Redis, và kết chót là một bài đánh giá thẳng thắn chẳng vuốt mặt nể mũi đem so kè cùng OSRM, Valhalla, và gã nhà giàu Google Maps.
Vì Đâu Nên Góp Gạo Thổi Cơm Cùng GraphHopper Distance Matrix?
Khi càn quét truy lùng ba đại pháp khí dẫn đường mã nguồn mở nhằm tính toán cho ra khoảng cách ma trận (route distance matrix computation), người ta hay kháo nhau về mặt ba cái tên là Haversine (chiêu chẻ đường bay thẳng cò bay), OSRM (chiến thần C++, nhanh siêu cấp vô địch thủ, nhưng lật bài thì hệ cấu hình vô cùng xơ cứng rập khuôn rigid profiles), và cuối mâm là GraphHopper (người con xứ Java, độ linh hoạt miễn chê với bài quyền Custom Models). Trừ hao đi thì ngoài ra cũng tồn kho cái danh mục thứ tư rẽ hướng sang tụi bán hàm API kiếm bộn bạc (Google Maps, HERE, Mapbox).
| Yếu Tố (Criterion) | GraphHopper | OSRM | Haversine | Google Maps |
|---|---|---|---|---|
| Đồng Tiền Đi Liền (Cost) | Cho không (tự ôm về chạy) | Cho không (tự ôm về chạy) | Rỗng túi | $0.005/một mục (element) |
| Độ Chuẩn Xác (Accuracy) | Theo đường nhựa ✅ | Theo đường nhựa ✅ | Đâm thẳng xuyên nhà ❌ | Đường nhựa + nạn kẹt xe ✅ |
| Gia Tốc Vận Động 100×100 | ~50ms | ~20ms | <1ms | Bèo cũng 500ms+ |
| Sửa đổi luật chạy đường ngang xương khi Runtime | ✅ Cho phép xài Custom Models | ❌ Mơ đi, đập đi dịch lại từ đầu Recompile + Lua | Miễn bàn (N/A) | Muốn thì ói thêm tiền mua mâm VIP |
| Đồ Nghề SDK Java/Python | ✅ Hàng xịn có gói SDK Java Native | Cạy mồm gọi HTTP thôi | Hàng tích sẵn Native | Cạy mồm gọi HTTP thôi |
| Lên Hàng Bằng Docker | ✅ Có ảnh xịn (Official image) | ✅ Có ảnh xịn (Official image) | N/A | N/A |
| Mâm Nào Hợp Nhất (Best for) | Ôm đồm đội hình chạy pha tạp nhiều loại xe | Vứt hết cần chạy siêu cấp thần sầu max tốc | Gạt nhanh mấy điểm rác ứng viên vòng gửi xe | Nắm chắc cái thời gian chuẩn xác ETA lúc đang chạy thực tế |
Kinh Nghiệm Rút Ra (Rule of thumb): Nên dùng đến GraphHopper trong cái trường cảnh bạn phải bao thầu một hệ thống mà đủ thứ loại xe xài luồng chạy với những ranh giới rập luật cấm (routing rules) chọi nhau chan chát (ví dụ như rào cản tải trọng xe tải truck weight limits, đường luồn hẻm hóc cho xe máy motorcycle lane access, đường né trạm thu phí toll avoidance). Giao mạng cho OSRM là chuẩn bài nhất cho tình huống mà bạn cứ rắp tâm ngó nhắm đòi phải trích xuất được khối độ trễ thần tốc dính cực sát chóp nhất cho vỏn vẹn đúng y một loại loại cấu hình thân xe một phương tiện mà thôi.
Làm Cú Khởi Động Chớp Nhoáng (Quick Start): GraphHopper Distance Matrix Trộn Cùng Docker
Bước 1: Khởi Động Đánh Thức Cỗ Máy GraphHopper Server
Để chạy, GraphHopper ăn mồi bằng nguồn bản đồ nằm chứa trong tệp file .osm.pbf bắt nguồn từ OpenStreetMap. Trang Geofabrik có ném sẵn ra chiêu đãi phơi bày đầy rẫy các bản cắt lát phân khu (regional extracts) theo từng khoanh vùng lãnh thổ để mà cắn về tải xài chùa.
# Khoét móng dựng khoang chứa (Create a data directory)
mkdir -p ./graphhopper-data
# Kéo máy nổ GraphHopper — yên tâm máy nó sẽ tinh khôn tự bưng cái file bản đồ OSM của Việt Nam tải rinh thẳng về cho
docker run -d \
--name graphhopper \
-p 8989:8989 \
-v $(pwd)/graphhopper-data:/data \
israelhikingmap/graphhopper:latest \
--url https://download.geofabrik.de/asia/vietnam-latest.osm.pbf \
--host 0.0.0.0
# Ngồi ngóng coi tin báo (Follow logs) — công đoạn chuẩn bị nạp đồ mồi nhồi bản đồ graph lần đầu thường bóc cướp từ 5-15 phút chầu chực
docker logs -f graphhopper
Ráng kiềm lòng rình rập đợi cho chừng lúc tòi ló dòng log mang dòng thông tin mọc ra: Started server at HTTP 0.0.0.0:8989
Bước 2: Hú Thử Lấy Dòng Lệnh Gọi Mâm Matrix API
# Một màn dựng trận mâm 3×3 matrix cỏn con: vẽ đường xe chạy luẩn quẩn giăng lối luồn vòng 3 địa điểm trong đất Sài Gòn (Ho Chi Minh City)
curl -X POST http://localhost:8989/matrix \
-H "Content-Type: application/json" \
-d '{
"points": [
[106.7011, 10.7712],
[106.7100, 10.7780],
[106.6980, 10.7650]
],
"profile": "car",
"out_arrays": ["times", "distances"],
"fail_fast": false
}'
⚠️ Một Chút Dặn Dò Về Trình Tự Bắt Tọa Độ Của Chuẩn GeoJSON: Anh bạn GraphHopper đinh ninh ấn định bắt chuẩn nhai hệ tọa độ theo trình tự
[kinh độ longitude, vĩ độ latitude](tuyệt nhiên không phải là cái mớ lộn ngược[lat, lng]). Cái tật này là thứ trượt chân vấp ngã thê thảm đầy mùi khóc lóc nhiều nhan nhản (most common bug) khi đám lập trình bưng đồ múa dời dọn mã nguồn tạt ngang qua từ gốc code bệ Haversine-based đi sang.
Kết Quả Dội Lại Nằm Gọn Ở Response:
{
"times": [[0, 320, 185], [315, 0, 410], [180, 405, 0]],
"distances": [[0, 2100, 1350], [2050, 0, 2900], [1300, 2880, 0]],
"info": {"took": 12, "copyrights": ["OpenStreetMap contributors"]}
}
- Nhãn
times: một mâm N×N chứa các con số thời gian đo bằng giây (seconds) - Nhãn
distances: lại là N×N nhưng để chỉ khoảng cách tính bằng mét (meters) - Sợi chỉ xẻ dọc (Diagonal) là số
0(vị trí này nằm yên bất động cùng chỏm điểm)
Ứng Dụng Viết Bộ Client Bằng Python Hạng Production
import requests
from dataclasses import dataclass
from typing import Optional
@dataclass
class Location:
lat: float
lng: float
label: Optional[str] = None
@dataclass
class DistanceMatrix:
durations: list[list[int]] # tính theo giây (seconds), mâm N×N
distances: list[list[int]] # tính theo mét (meters), mâm N×N
class GraphHopperClient:
"""
Cục client cắm thẳng mặt GraphHopper distance matrix mướt mườn mượt đạt tới ngưỡng Production-ready.
Lo bao ôm thầu bọc tuốt luốt cái mớ đảo lộn ngược [lng, lat], tóm bắt vớt lỗi lầm, cộng nhồi trò chống gãy thử liên tục retries.
"""
def __init__(self, base_url: str = "http://localhost:8989", profile: str = "car"):
self.base_url = base_url.rstrip("/")
self.profile = profile
self.session = requests.Session()
self.session.headers.update({"Content-Type": "application/json"})
def get_matrix(self, locations: list[Location], timeout: int = 30) -> DistanceMatrix:
"""
Nhai trọn ngấu nghiến tính nguyên cho rành một bàn cờ N×N distance matrix gán cho đám mớ location ném vào.
Nguồn cấp (Args):
locations: Lô lốc (List) đám vật thể Location chứa mớ thông tin kinh vĩ độ (lat/lng).
timeout: Thời gian mòn mỏi chờ HTTP rớt gánh timeout ngắt (tính theo seconds).
Trả về (Returns):
Đối tượng DistanceMatrix với bộ thông tin 'durations' (giây) và 'distances' (mét).
Ném Báo Cáo Lỗi (Raises):
requests.HTTPError: Lòi ra nếu GraphHopper ném văng vào mặt trả lỗi.
ValueError: Rớt đài móm sập ngay nếu rải chưa đặng kiếm nổi lấy cỡ ít nhất được cái 2 cục chỏm nhọn locations (At least 2 locations).
"""
if len(locations) < 2:
raise ValueError("Tuyệt đối buộc phải nhón có sẵn tối thiểu độ ít nhất là lấy được 2 cái locations cho việc trãi ra dựng dệt distance matrix")
# Cẩn thận này GraphHopper ăn theo chuẩn [lng, lat] — dính định vị GeoJSON order
points = [[loc.lng, loc.lat] for loc in locations]
payload = {
"points": points,
"profile": self.profile,
"out_arrays": ["times", "distances"],
"fail_fast": False, # Chỗ này báo cho ngầm lòi gỡ lại ít mớ kết tủa dang dở nếu có cái đôi nào trắc trở vấp ổ gà kẹt cống unreachable pairs
}
response = self.session.post(
f"{self.base_url}/matrix",
json=payload,
timeout=timeout
)
response.raise_for_status()
data = response.json()
return DistanceMatrix(
durations=data["times"],
distances=data["distances"],
)
# --- Khúc rải múa trình diễn cách xài (Usage example) ---
client = GraphHopperClient(base_url="http://localhost:8989", profile="car")
locations = [
Location(lat=10.7712, lng=106.7011, label="Kho hàng (Warehouse)"),
Location(lat=10.7780, lng=106.7100, label="Khách C (Customer A)"),
Location(lat=10.7650, lng=106.6980, label="Khách B (Customer B)"),
]
matrix = client.get_matrix(locations)
# Xả ra vọc in cái trận mâm duration (Print duration matrix)
for i, from_loc in enumerate(locations):
for j, to_loc in enumerate(locations):
if i != j:
duration_min = matrix.durations[i][j] // 60
distance_km = matrix.distances[i][j] / 1000
print(f"{from_loc.label} → {to_loc.label}: tốn {duration_min}min, đứt chừng {distance_km:.1f}km")
Tính Chất Nặn Khung Form Xe (Vehicle Profiles) Cùng Môn Nghệ Thuật Custom Models
Sự chói lọi nằm trọn ở cõi thiên đường này đây, chính là chỗ đòn chí mạng lợi thế tuyệt đối của thằng GraphHopper chẻ ngửa phán án trước anh bạn OSRM: Custom Models đập luôn cái dớp đi cho bạn tha hồ rắp ráp sửa bóp cái đám luật lệ bắt rẽ đi nhan chạy của luồng (routing rules) chình ình chèn ngay luôn vào giữa khoảng không lúc máy móc đang chạy sầm sập ngoài trời (at runtime) lả lướt ngọt rụng chẳng rặn cần thèm nôn nóng lặp thui xới móc đống gạch bản đồ compile cho trút ráo làm lại.
Đám Khung Lót Cốt Rẵn Nhất (Built-in Profiles)
# Phân mảng vẽ lối cho luồng xe con ô tô hơi Car (ráp sẵn default)
curl -X POST http://localhost:8989/matrix \
-d '{"points": [...], "profile": "car", ...}'
# Nhào vẽ nắn ngách cho bên hệ 2 bánh gắn máy Motorcycle (thòng theo mấy pha xuyên lách làn luồn hẻm ngách, hốt trọn mấy lối đường chui nhỏ hẹp)
curl -X POST http://localhost:8989/matrix \
-d '{"points": [...], "profile": "motorcycle", ...}'
# Kênh đi xế điếc ruột xe độp Bicycle
curl -X POST http://localhost:8989/matrix \
-d '{"points": [...], "profile": "bike", ...}'
# Tuyến đi thảnh thơi đi bộ Walking / on-foot
curl -X POST http://localhost:8989/matrix \
-d '{"points": [...], "profile": "foot", ...}'
Chế Biến Lại Custom Models — Sửa Luân Phiên Lề Lối Khi Dang Chạy Mượt Mà (Runtime Rule Changes)
Tuyệt đỉnh đồ chơi tên là Custom Models này thả cổng để người cầm lái tự gõ phím đi biến hoá (modify) hành tung kiểu tính lối đi vạch trần luân chuyển (routing behavior) nhẹ hều chẳng bắt nặn đóng dập thắt nút restart dập đập cầu dao làm máy mọc server tắt lại. Này nó được liệt vô độ mức quan yếu sống chết cực khủng cho ba cái mâm nền logistics dồn ôm gánh gồng các cái mớ đội ngũ tài hỗn mang múa may đâm hỗn hợp (mixed fleets).
Trích rải phơi bày Ví Dụ: Tụi hung thần nhồi xe tải (Heavy truck) ôm trốn né trạm BOT đường lộ lớn cao tốc (highways) và lách cả lề nhỏ nghẽn đường hẹp
{
"points": [[106.7011, 10.7712], [106.7100, 10.7780]],
"profile": "car",
"out_arrays": ["times", "distances"],
"custom_model": {
"speed": [
{
"if": "road_class == MOTORWAY",
"limit_to": 90
},
{
"if": "road_environment == TUNNEL",
"multiply_by": 0
}
],
"priority": [
{
"if": "max_weight < 10",
"multiply_by": 0
},
{
"if": "road_class == RESIDENTIAL",
"multiply_by": 0.3
}
]
}
}
Thêm nấc Ví Dụ: Hệ điều chỉnh lách trốn né sạch không chừa cái trạm thu phí (Toll-avoidance routing)
{
"custom_model": {
"priority": [
{
"if": "toll == ALL",
"multiply_by": 0
}
]
}
}
Soi ngang thực tế cõi trần (Real-world use case): Một công xưởng bám trụ ăn nằm làm lĩnh vực logistic gánh bao thầu điều vận song kiếm hợp bích từ đám quân hai bánh xe xé gió luồn rẽ (nhoáy nhoáy nhanh nhảu ôm khâu bưu cục chót last-mile) lộn nhào cùng với mấy “ông tướng” 10 tấn vạm vỡ đi chà bánh đè bẹp xé gió (để chuyên dành nện cấm đường nhỏ tải bự restricted roads) hoàn toàn cựa mình an tâm đâm chọc vục tay trích dùng cái bộ hàm hú chung cùng một mối điểm (instance) vô cái cỗ máy GraphHopper duy nhất đang xoay tít thôi mà linh hoạt bẻ lái chỉ tay chĩa cho muôn vạn cấu trúc thay sắc sửa da theo dạng Custom Models tương ứng ứng với mảng từng xe nhào xé — bóp nghẹt triệt để cái trò ngốn hơi sức phải xới xào đi phá đập hạ tầng ra làm chi (no infrastructure change needed).
Kênh Nhúng Nguyên Mảng Gói Java SDK (Cơ Chế Khép Kín Embedded Mode)
Thử mang cho khối hệ thống xương sống hậu cảnh ăn bám trên lớp màng Java (Java-based logistics backends), chèn họng đút nguyên khối cộm cái ruột GraphHopper thọt thẳng nhét tọt nhập chui nằm gọn chung ổ liền xác với cả chương trình tiến trình đang khởi (in-process) — hốt lợi ngay tắp lự món mức phi tang băm sạch hoàn toàn thứ cản đường mài mòn đắt đỏ HTTP (zero HTTP overhead) cho cái món khâu càn xới nhai xử lý khoảng ma trận kia.
import com.graphhopper.GraphHopper;
import com.graphhopper.GraphHopperConfig;
import com.graphhopper.config.CHProfile;
import com.graphhopper.config.Profile;
import com.graphhopper.routing.matrix.MatrixResult;
public class EmbeddedGraphHopperMatrix {
private final GraphHopper hopper;
public EmbeddedGraphHopperMatrix(String osmFile, String graphLocation) {
GraphHopperConfig config = new GraphHopperConfig();
config.putObject("graph.location", graphLocation);
this.hopper = new GraphHopper();
this.hopper.setOSMFile(osmFile);
this.hopper.setGraphHopperLocation(graphLocation);
this.hopper.setProfiles(
new Profile("car").setVehicle("car").setWeighting("fastest"),
new Profile("truck").setVehicle("car").setWeighting("custom")
);
this.hopper.getCHPreparationHandler()
.setCHProfiles(new CHProfile("car"));
this.hopper.importOrLoad();
}
// Tiện tay quăng bắt dùng cục GHMatrixAPI cho việc chẻ củi N×N computations
// Theo dõi tham kiến ở dải này: https://github.com/graphhopper/graphhopper/tree/master/web-api
public void shutdown() {
hopper.close();
}
}
Nguyên cớ vì cớ sao Embedded (khép kín đính lót trong luồng) lại đấu bẹp vế của cọc chèo HTTP?
- Hệ Embedded (nhúng dính vô): ~Ngốn rẻ rề có tầm 1ms độ trễ gán vào cho mớ lời hú hú réo réo gọi lặp lại (matrix call) rợp màn (vì cởi bay bay hơi đi cái nạn làm nghẽn cổ chai nhét nặng mông luồng đường truyền network overhead). Đây ngót xơi là món đặc ân tối thượng béo bở nhất chuyên dành tạt sang cho cục cưng Java microservices vác bụng ra nã đi tới ti tỉ hàng thiên thu hằng nghìn (thousands) cuộc đi dạo gõ nhịp đi gọi bầy đám ma trận (matrix calls) đếm bằng nháy mắt trên 1 giây rải.
- Phía góc hệ HTTP: Gỡ rào thả lỏng làm đứt lìa bay đứt mọi cọng lạt trói phụ thuộc ngôn ngữ lập trình (Language-agnostic), bứng tay thả dễ ợt hều nới lỏng kéo trải dẹt thêm hàng khối diện trải mở (scale horizontally). Dành trao điểm rới lý tưởng (Best for) rớt vào hàng hệ thống mảng tạt tay xé qua rào bầy đàn dùng món xài hệ rắn lục Python hoặc Go services hay mấy tổ rẽ nhóm chơi chặp nhiều giống ngôn ngữ xen cài chéo nhau (multi-language stacks).
Giăng Bể Cất Chứa Caching Rải Cục Redis Dựa Rập Khuôn Qua Cơ Chế Phân Bổ Mảng H3 Cho Bộ Gánh Của Lớp Hệ Thống Hoành Tráng Production Scale
Giăng cấu mảng mặt đường lộ mạng lưới đi (Road networks) đâm chồi hiếm cực bứt bứt lâu lắm nhả ra độ chừng một mẻ biến đổi đả thay hiếm hoi lắm. Quán triệt gài chốt ghim điểm lót mạn chèn lưu gạt lấy đè cất dạt mớ đống đồ thông tin đã trút tính ra cho khoảng ma trận lôi (distance matrix results) tóm bám dựa theo chia tệp dải ô ngăn rập khuôn chia 2 cái mạng rào khoang ô nhỏ ghép (H3 cell pair) dồn bóp rỉ rã chém cụt tọt giảm hẳn hớt bớt tận >90% đám rền rĩ gọi rát mỏ thâu đêm (GraphHopper calls) diễn dạt ra trong thời gian khi xưởng máy duy trì mức độ an bài vận động êm nệm vào rơ (steady-state production).
import h3
import json
import redis
from graphhopper_client import GraphHopperClient, Location, DistanceMatrix
class CachedDistanceMatrix:
"""
Rút hệ thống gánh GraphHopper distance matrix kẹp bồi rải dính theo nách món cache rủng rỉnh ăn nằm cùng H3-based vắt lọt sang nằm lòng Redis caching.
Tỉ suất trúng thầu gắp đặng rớt vọt từ cache (Cache hit ratio): đớp ngấu hớp tới 90%+ ngay sau pha dợt nhịp làm ấm cho bộ máy nổ mượt sướng đi vào khuôn khổ (steady-state logistics).
"""
H3_RESOLUTION = 9 # ~Rải khứa nhuyễn lọt đâu tầm 174m sải mỗi một mẩu cells — ngang bằng bo cho nguyên một cỡ góc khối phố giao (one city block)
CACHE_TTL_DAYS = 30 # Đường lối thênh thang bớt cấn cản lộ giới đường mạng bám (Road networks change slowly) hiếm đổi
def __init__(self, gh_client: GraphHopperClient, redis_client: redis.Redis):
self.gh = gh_client
self.redis = redis_client
def _h3_key(self, loc_a: Location, loc_b: Location) -> str:
"""Thái ép chẻ cho nặn ra một đúc dạng chìa khoá cache thu về nguyên dạng bản chuẩn quy tụ từ hai gã cọc cạch mẩu ngăn chia H3 cell IDs."""
cell_a = h3.latlng_to_cell(loc_a.lat, loc_a.lng, self.H3_RESOLUTION)
cell_b = h3.latlng_to_cell(loc_b.lat, loc_b.lng, self.H3_RESOLUTION)
# Nêm nếm bóp rẽ thứ tự đảo xuôi hốt gom nhét lề (Sort) lấy tính cân phân đều đối đãi (symmetry): Cửa A→B và bóp ngược ngõ B→A là chung tuột xài chéo móc chóp chung cùng rập một chiếc khuôn khóa (same key) vì nó đánh vòng tròn khép góc lụi (undirected graph)
return f"gh:matrix:{min(cell_a, cell_b)}:{max(cell_a, cell_b)}"
def get_pair(self, origin: Location, dest: Location) -> dict:
"""
Khẽ với bưng ngắt nhón thóp bốc về cục độ dài trượt cùng khối tính chìm thời gian đính vô chẻ riêng tẻ trên một cặp thôi, ráng bóp rịt thêm mớ nhúng tay hốt mồi của chóp móc dỡ kho chóp cache.
Kết cục nhả (Returns): {"duration_s": int, "distance_m": int}
"""
cache_key = self._h3_key(origin, dest)
cached = self.redis.get(cache_key)
if cached:
return json.loads(cached)
# Chóp nhặt hụt mất cắn ngón (Cache miss) — ném việc cày vác tính số vô thẳng nách GraphHopper
matrix = self.gh.get_matrix([origin, dest])
result = {
"duration_s": matrix.durations[0][1],
"distance_m": matrix.distances[0][1],
}
self.redis.setex(
cache_key,
self.CACHE_TTL_DAYS * 86400,
json.dumps(result)
)
return result
def get_matrix_cached(self, locations: list[Location]) -> DistanceMatrix:
"""
Dựng bệ chắp đắp khảm ra lò một dải nguyên rành mạch của ma trận bọng N×N ráo nước ngầm ngấm móc chép vay xài từ chóp cached của đống rễ đôi cặp sờ đụng khi có cửa ngách thể xen qua (where possible).
Nảy nảy thối lui tụt tọt té bám dựa dẫm vô cắn theo con GraphHopper trong mấy nhát khi bắt hụt móc phải lọt sổ (cache misses only) mà trượt thôi.
"""
n = len(locations)
durations = [[0] * n for _ in range(n)]
distances = [[0] * n for _ in range(n)]
missing_pairs = []
# Soi chớp nháy bới mò bới rác móc từ túi giấu cache đem ra áp cho dải giăng tất cả (all pairs)
cache_keys = {}
for i in range(n):
for j in range(n):
if i == j:
continue
key = self._h3_key(locations[i], locations[j])
cached = self.redis.get(key)
if cached:
data = json.loads(cached)
durations[i][j] = data["duration_s"]
distances[i][j] = data["distance_m"]
else:
missing_pairs.append((i, j))
if missing_pairs:
# Nhồi thành một bọc rinh đi phay nấu nấu nhồi cho cái đống dạt thiếu sót hụt cặp (missing pairs) rớt thông qua nhịp xài GraphHopper
missing_locs = list({idx for pair in missing_pairs for idx in pair})
loc_subset = [locations[i] for i in missing_locs]
sub_matrix = self.gh.get_matrix(loc_subset)
idx_map = {orig_idx: sub_idx for sub_idx, orig_idx in enumerate(missing_locs)}
for i, j in missing_pairs:
si, sj = idx_map[i], idx_map[j]
dur = sub_matrix.durations[si][sj]
dist = sub_matrix.distances[si][sj]
durations[i][j] = dur
distances[i][j] = dist
# Dập khuôn chốt rải ném đút lại tàng hình ẩn giấu nhồi kho Store trong ngăn tủ cache
key = self._h3_key(locations[i], locations[j])
self.redis.setex(
key,
self.CACHE_TTL_DAYS * 86400,
json.dumps({"duration_s": dur, "distance_m": dist})
)
return DistanceMatrix(durations=durations, distances=distances)
Thâm khẩu tạt tỷ suất rớt cắn đớp (Cache hit ratio) vặt rọi ở cõi thực tế đời thường (in practice):
- Ngà dợt 1 (lạnh tanh máy cold): rớt tõm ~0% hits — sạch banh mọi món bắt hụt đều phải xắn áo cày đổ ra để bơm tưới nhồi hết cho căng đống mốc cất vào tọt trong bụng cái bình bọng Redis (populated into Redis)
- Nhảy Ngày thứ 7: đợp chóp ~70% hits
- Mút Ngày ròng tới con số 30 (bình ổn vô nhịp điềm nhiên steady state): nhồi róc đụng trần vọt tới >90% hits — các ổ nhóm đơm nhả đường gom hàng (recurring delivery zones) đặn chạy đã bị khống chế thộp cổ đem chèn đóng lót gộp sạch sành sanh vào đè hết (fully cached) trong tráp chứa
Giao Tranh Chóe Chợ: GraphHopper vs. OSRM vs. Bố Trẻ Google Maps: Thăm Dò Đánh Giá Lượng Vận (Production Benchmark)
Lôi ra đem chần soi chéo lột tả đi qua màng lưới 100-hạt điểm nhắm thả chạy rảo (100×100 = 10,000 nhát kẹp cặp rinh tính đi đi lại lại) nã đạn qua lại trên bệ phóng của mâm máy con cưng DigitalOcean cởi ở vỏn vẹn lố thông thông cấp máy 4-vCPU/8GB droplet xài cùng món bộ thông tin bản đồ Việt Nam nguyên bản gốc Vietnam OSM data:
| Trạm Tàu Nhai Tốc Độ (Engine) | Đập 10×10 matrix | Chẻ 50×50 matrix | Gọt 100×100 matrix | Gán phí dằn túi móc trả Tháng (Monthly cost) |
|---|---|---|---|---|
| Khối GraphHopper (nuôi lẩn tự rúc trong nhà self-hosted) | 8ms | 28ms | 52ms | Gộp rơi rụng đâu tầm độ ~$20 vô con hàng máy cùi VPS |
| Máy OSRM (nuôi tự cấp self-hosted) | 4ms | 14ms | 21ms | Cũng ~$20 bay trên nền máy VPS |
| Bệ Valhalla (bọc ôm luôn self-hosted) | 15ms | 60ms | 120ms | Khoản chừng ~$20 VPS |
| Kho tàng Google Maps vung API rắc thính Distance Matrix | 300ms | 1,200ms | Tụt mốc 2,500ms+ đổ lên | Lố vọt cắt cổ $510/ngày vãi đái |
| HERE nã Matrix Routing v8 | 150ms | 600ms | 1,200ms | Vắt lòi ngót $0.70/dẫn trọn đoạn tuyến |
Mổ xẻ phanh thây ngó vô soi kết quả diễn tiến giải chẻ (Interpretation):
- Cái anh bạn OSRM nhanh bốc gió đè cổ vượt hơn tới 2.5x nấc dạt chẻ búa tốc lực GraphHopper lúc cắn vào làm rành cái dải thô mộc ròng phăng đi chém vụn cho chuyện mâm khoảng đo (raw matrix computation)
- Bù trừ GraphHopper thì ngặt nghèo rịt ràng phải gọi tớ nã trúng mâm nó mỗi khi tay gánh trọng trách cần rớ đến xài chiêu phép nắn uốn nắn khung sườn xỏ mỏ múa phép luật lệ thay áo giữa mùa gieo Custom Models (thứ mang sửa đổi nặn gọt uốn luồng khi con xe đương lăn bánh runtime vehicle rules)
- Cha nội Google Maps phô tạc chói óc giá nó ăn dọng đội lấn vọt cao chót vót cắn gấp 50x lần sự điêu tàn của việc tốn kém, cùng cộng nhồi kẹp cổ sự rề rề dề dà rúc rút dạt trễ kéo rề bò lề đúc bết thêm tận cả cũng khoảng lẩn mẩn là 50x lần ngót xơi cắn rút gặm thêm — biện bác thì ừ cũng cho là để bù khú cứu với vớt lại điểm sáng mang khoe có tí chút thông tin chóp mỏ chỉ đạo ETA cho nạn kẹt vướng xe dòng ùn nghẽn trên dải thời gian đường tơ thật chóp lú (real-time traffic ETA), ôi chớ cái đó cũng rách bươm bỏ qua ngay nếu đang trong cơn ngán nợ trôi vờ tĩnh tại chả xê chẳng nhúc nhích trong mâm đường đi gom chạy tĩnh ngõ cụt tĩnh trôi ráo tĩnh tuột gán điểm trôi giao gom đồ (static delivery routing)
Hao Phí Vắt Óc Bộ Nhớ Lòng Thòng Và Kéo Tuột Lấp Thông Số Lõm Máy Móc (Memory and Hardware Requirements)
Động năng GraphHopper húp hút thu nhồi cái gộp cục tất tần tật cái khối đồ họa mạng đường đi bao nạp nhét bóp rịt nén vứt vô nguyên trong mảng bọc chứa RAM. Ước chừng khối bành xệp đo đo kích thước ngốn (Sizing) thì nó lại gật đầu nằm rạp phụ thuộc bơi trên diện dải mức độ ăn phủ của cái nùi file khoang rác chia tẻ róc lãnh thổ từ tệp gốc OSM coverage region cung cấp:
| Khoanh Vùng Vành Đai Phủ Sóng (Region) | Phình Kích Gói File OSM Nhá Vào (OSM file size) | Xài Bao La Bể Bọng Lõi RAM của GraphHopper |
|---|---|---|
| Trùm rải sải tay bọc gộp khu vựng Sài Gòn mở rộng metro (Ho Chi Minh City metro) | Cỡ rải dạc đâu chừng ~180MB | Nuốt gọn đục độ cày 2GB |
| Căng vòng trút trọn mâm sải gánh hết dải đất chữ S cả Nước Việt Nam (Vietnam - entire country) | Móp méo nằm đâu ngưỡng sấp sỉ ~880MB | Hớp hết đớp gạn mút vô khang khoang rỗng tầm độ 6GB |
| Ôm thu choán ôm trọn tóm tọt cả cái Đông Nam Á (Southeast Asia) | Bự lòi nhòi cồng kềnh khoảng ~4.5GB | Ngót bốc đi dằn bẹp hơn cỡ tận mút tới 24GB+ |
| Nắm bọc Đức quốc (Germany) | Mỏng dính mập thù lù cỡ dăm ~3.8GB | Bợ bưng mất mẹ cả khoản chóp >20GB+ |
Liều dọn rắc lên dĩa mách nước ngõ đường cấu trí lên thớt dọn đồ (Recommended production setup) cày cắm gánh sườn ôm đèo nguyên bệ tuyến vẽ lối ngõ cho (Vietnam routing):
- Con VPS nhồi bóp 4 vCPU / đi chung thân sườn 8GB RAM VPS
- Dùi lỗ dọn sẵn bọc kho khoét bọng ổ cứng lấy hàng đồ SSD NVMe ngon nhét dồn chỗ phơi mớ rập khuôn xào rác chóp thư mục rỗng gạt vô đồ chứa nắn cho món graph-cache directory
- Hệ nêm mắm CH (khuôn tạc Contraction Hierarchies) profile rước sắm tút kéo giảm chóp lặn rút cạn mỏng độ thời gian cho cái lúc gõ lệnh chờ rên hỏi kết (fastest query time)
- Phả luồng vã dựng xòe mở hai nhánh tọt xài (Run 2 instances) dúi chui nằm giấu lưng rình mò ấp sau lưng của cái cổng gác điều chỉnh tải (load balancer) đánh gán phòng đệm bọc hờ cho tính túc trực lúc hoạn hỉ (High Availability - HA)
Chuyên Mục Vấn Đáp Hái Lượm Đồ Bỏ Túi (Frequently Asked Questions)
/matrix nằm chình ình trong lõi của cái cỗ mã bọc ruột mở bung rỗng GraphHopper routing engine đi săn vẽ nẻo đường (open-source). Thằng lõi này bắt nặn tóm cổ ôm rịt vô mớ cái đống có n-phần chóp dải tọa độ (N latitude/longitude points) thu tóm về ném rải phun văng băm nát xả lai đâm toạc trả một cái mâm cấu kiện ma trận nhọn mũi độ cỡ gán vạch thành N×N dội lại tổng thể nguyên khối toàn bộ các trị số nhịp gõ thời gian cắn chạy rát lộ mòn bánh (travel times tính theo đơn vị điểm đếm giây seconds) tắp rải thấu róc khoảng đường vạch nhét độ (distances chẻ lấy cái chia bằng nét mét meters) húc trích sờ tới cái mớ nền tảng sự tích rành mạch lộ giới nã róc đục thẳng cắm sừng vào nguồn lôi chắp bằng mạng từ thằng mâm OpenStreetMap. Đã vậy, miễn phí là từ bám rễ văng màng không cần moi móc túi đút lấy xu (free) nếu bạn mang nó về cài dựng tự vọc nuôi chứa sườn rọc Docker, ớn óc hơn nữa ở bệ mâm rọc đi xử dứt một con cấu trúc bự nạy 100×100 (tầm bét nhất lột ra 10,000 nhát chẻ giao chéo cặp) lạng xẹt văng độ đo đồng hồ nhích đâu cỡ tầm cỡ ngót độ ~50 mili-giây (50ms) ngay khi chỉ cho ngồi bậu trên một cỗ server cấu hình nghèo quèn chỉ có lọt thỏm dăm 4-vCPU con ruồi..osm.pbf (binary format). Tự do tha thẩn cứ đàng hoàng bốc lấy đục nhấc kéo sọt gỡ kho trích nạp dải mấy khoanh gạt cắt phân phân bổ nhấm khoanh chia từng lô đi về nách tay rác đắp free vác giắt từ chốn địa ngục trần gian gót vách rác lộ mang nhãn Geofabrik (geofabrik.de) là hốt có ngập mặt mồm chắp. Tính cửa rải cho mâm Vietnam đơm húp gọn: https://download.geofabrik.de/asia/vietnam-latest.osm.pbf. Cái bộ lèo lái gõ gầm GraphHopper còn nốc biết lôi khều gõ lệnh cho tự thân nó vác nhấc tay chân kéo tọt ròng file đổ cúp tự rớt nốc đục kéo tự mút tự tóm dọng móc bưng tự xả lấy tải rảo tay lặn nhào xuống cắn vô nhét trọn bọc dải tự thân luôn (download the file automatically) ở cái cớ dạo khởi lệnh vặn mồi vạch chớp bật lần lọt lật xuất vặn máy cái nhịp chạy khẩy đợt đầu (first start) dẫu trúng lỡ cấn thả ngửa dúi rách rải nhét thêm rải tham nhúng cái nhãn nhíp cái ngàm chỉ dấu nhíp cái ngạch xới --url dọn gắn cắm kèm vô.Buộc Móc Lưới Luồng Nội Cung Liền Trong (Internal Links) & Thả Lộ Diễn Lịch Cho Bước Tới Kế Bước Kéo Sang Cần Làm Tới (Next Steps)
- Ngành mâm sải luồn gọt E-commerce chia rẽ ranh routing vạch luồng dắt dây (series): Sổ tay dẫn luật cẩm nang này ném phăng neo tạt gắn chỏm chọc đâm tạt vạch chóp nhắm lấy rập móc chiếu gá mốc trích lấy soi (referenced) xuất phát mốc đục từ chỗ Góc Khía Phần 7 — Chắp Khớp Tính Khảo Ma Trận Rẽ Khoảng Đóng Mốc Ở Trọng Khu Cắt Gọt Chia Việc Rút Lệnh Alloc Đơn (Distance Matrix Routing in E-commerce Order Allocation), phơi bày vạch áo cởi tuột lột trần dọi săm soi soi cho mút lấy cái đòn cách mút lấy thế cắm nhét làm sao đặng mang cái dải ma trận ma mâm gán nhãn GraphHopper matrix húp rọc làm đồ mồi nhồi tọng ói mớm nhét ói xực dọng vô họng (feeds) rải cung cái rễ cọc hệ VRP solver húp.
- Lôi vác khách khứa chạy thốc chạy mướn chở bến đổ nháo nhào xe ôm (Ride-hailing): Giống hệt tăm tắp dập rập trét xào cái nhát cắt dải băm nhét lập đánh ô rẽ mẻ không gian cho mảng mâm không mạng bằng cách xài H3 mâm ô lưới chẻ vụn (spatial indexing) bám nện rải lấy cái đống làm trò để nuôi hệ vách xới ổ đắp cache cho ngáp ngáp nằm chờ nã xài nhai chộp lại sau này đó chóp chính nạp vô là chẻ lấy nguyên khối cái điệu đi cày ải bới mốc trích tóm mò gánh mốc ngọn trò mà gã dốc mỏ đi tìm bới lượn lách Uber bươi rác lục đi truy hốt xới bưng dò bớ lấy kiếm moi bóp túm thóp dò rọc lấy tìm cày lùng dạt ra rớt mấy ông cuốc tài xế quanh vùng rình rập ở gần (nearby drivers) — nhón gót tạt lách rớt đục sang ngó chóp mục Đánh Chia Đính Điểm Rẽ Lưới Định Không Địa H3 Geospatial Cài Cắm Đục Vẽ Phác Cho Khoang Nháp Cõi Ride-Hailing Architecture.
- Ngành gác móng cao ốc dựng luồng nã đạn gồng đua xe độ High-concurrency systems: Phụng phịu tạt dọng cung hầu nhét ngó cái mâm dọng vung thúng húp đổ trút rót lòi rác mả nạp móc hệ xới ma trận tróc kết mâm rớt mả matrix results kẹt ở lót bẹt dưới nách cọ ngót cắn nhai cái nhát đi rít dọng bạo xéo rác cọc tút volume tảng lố nhíp xực đi mâm nã gọi húp húp vọt thét rống mút cao vọt (high request volume), lọt nhón ngó rớt ghé đục nhìn cắm tạt Hệ Ngàm Hãm Họng Xẻ Nhấn Gạt (Rate Limiting) Khép Mâm Và Giăng Chốt Mảng Khảm Kiểu Gánh Một Nhát Dứt Quát (Singleflight Patterns).