Experimenting Uber Like Application Architecture

Hello, Good people. Hope you all are fine.

You may hear about Uber, Grab, Pathao or other ride sharing applications. If you are curious you may be interested to know how this applications work.

Today I am going to write on this. This is not how exactly these application works as they use different technologies. I am just writing a prototype that how these kind of application works.

So, Lets start. First clear the basic idea what these kind of application do.

Assume there are few people X, A, B, C, D, E, F. X want to go somewhere and A, B, C, D, E, F are the ride sharers. Lets count A, B, C is near X (within radius). So when X will ask to connect the system will lookup for nearest one and send him/her request to get connected. There could be other weights (like rating, distance etc) to priorities which one to connect. After getting approval from other side system will connect each other. Assume C is the one to connect to X. After connecting to C, C will go to the place of X and pick X and finally drop X to expected place.

So first we need a user management system. There are basically two kind of user.

A. Who want to take the ride ( Rider ),
B. Who want to share the ride ( Driver )

  1. We need to share location of users. So we need a system which can handle these location sharing event. For that we can use MQTT protocol, which is stateful and designed to handle large concurrent user base. To store these location need a database supporting geolocation. There are lots of implementation for that but we are counting here MongoDB to store location data. MongoDB is a noSQL database having geolocation storage support.

  2. There are other data to store like user info, ride info, etc. We will keep them in postgresql database. You can use any other sql database.

Consider the above architecture.
Lets say user X comes in. After successful registration and verification X will share location with system and ask for nearby driver to view in app. Follow chain ( <- BA -> ). Same thing for driver as well. But the difference is driver location will be saved in database.

Now user X wants to make a ride. X will set pick point -> Set Destination -> This data will be send to Worker via MQTT broker (A -> B -> C). Now worker will search in database nearby drivers of pick point. If worker finds some driver nearby, worker will send request to drivers via MQTT (E -> F). If the driver accept/cancel the request that will be send back to worker (G -> H). Now worker will make a ride entry in SQL database via Rest Service ( i1 ). At the same time will notify user X (i2) and driver (i3). User and driver is connected now. Driver will goto pick point and pick the user , start the trip and drop to destination. At the end of trip driver have to calculate cost and few other tasks that will be served by restful API. Besides user will provide feedback thats via restful API too. There could be other tasks too but is not considering here.

####### Insert & find Geo Partial Data in MongoDB

As we are going store gps data (longitude, latitude), we must create index first.

// Query for Indexing
db.geoentries.createIndex({ loc: "2dsphere"})
// Output
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1

loc is the field to index and index type is 2dsphere.

Now insert few data,

// Query, coordinates: [longitude, latitude]
db.geoentries.insert({ driverId: "1234556", loc: { type: "Point", coordinates: [90.361006, 23.752726]}})
// Output
WriteResult({ "nInserted" : 1 })

Finally Find data,

// Query
// Output
{ "_id" : ObjectId("59b5b0ea811ce3259075d8e4"), "driverId" : "1234556", "loc" : { "type" : "Point", "coordinates" : [ 90.361006, 23.752726 ] } }
{ "_id" : ObjectId("59b5b0f2811ce3259075d8e5"), "driverId" : "1234557", "loc" : { "type" : "Point", "coordinates" : [ 90.358338, 23.757645 ] } }
{ "_id" : ObjectId("59b5b130811ce3259075d8e6"), "driverId" : "1234558", "loc" : { "type" : "Point", "coordinates" : [ 90.367173, 23.755822 ] } }
{ "_id" : ObjectId("59b5b138811ce3259075d8e7"), "driverId" : "1234559", "loc" : { "type" : "Point", "coordinates" : [ 90.367482, 23.753204 ] } }
{ "_id" : ObjectId("59b5b146811ce3259075d8e9"), "driverId" : "1234550", "loc" : { "type" : "Point", "coordinates" : [ 90.37591, 23.75699 ] } }
{ "_id" : ObjectId("59b5b1d8811ce3259075d8ea"), "driverId" : "1234555", "loc" : { "type" : "Point", "coordinates" : [ 90.373146, 23.759503 ] } }

Ok, Lets find nearest locations of a point,

// Query, distance is in meters
db.geoentries.find({loc: {$near: {$geometry: {type: "Point", coordinates: [90.366322, 23.755469]}, $maxDistance: 10}}})
Output will be empty as there is no location near this point within 10 meters. Now lets Increase the distance to 100 meters.
// Query
db.geoentries.find({loc: {$near: {$geometry: {type: "Point", coordinates: [90.366322, 23.755469]}, $maxDistance: 100}}})
// Output, 1 location within 100 meters
{ "_id" : ObjectId("59b5b130811ce3259075d8e6"), "driverId" : "1234558", "loc" : { "type" : "Point", "coordinates" : [ 90.367173, 23.755822 ] } }

Note : Its not a production ready implementation. There could be lots of security issues. Besides implementation is not complete, there could be other operations todo.