This microservice is a small, independent software application designed to determine the geographic location of a device based on its IP address. It achieves this by using a free public database called db-ip.com (free version provides about 77% accuracy), which contains a vast amount of information linking IP addresses to specific locations.
- Automatic Database Updates: The microservice regularly updates its local copy of the db-ip.com database to ensure that the location data is always accurate and up-to-date.
- Fast Lookup: It is optimized to perform quick searches within the database, allowing it to efficiently determine the location associated with a given IP address.
- HTTP and gRPC Support: The microservice can be accessed and interacted with using both protocols, providing flexibility in how it can be integrated into other systems or applications.
- Rate limiting: The microservice provides per-client rate limits and sends a 429 HTTP response when the client makes requests too frequently.
- Caching: The microservice implements caching to improve availability and reduce database load.
Start postgresql and ip-info containers:
$ docker-compose up -d
We are waiting for the database to be updated:
$ docker logs -f ip-info-container
IP_INFO: 2024/09/22 16:41:44 HTTP server listening at :8080
IP_INFO: 2024/09/22 16:41:44 gRPC server listening at [::]:50051
IP_INFO: 2024/09/22 16:41:45 ip database update started
IP_INFO: 2024/09/22 16:41:45 truncate ip_to_city_one table before importing update
IP_INFO: 2024/09/22 16:41:45 droping ip_to_city_one_ip_start_gist_idx index
IP_INFO: 2024/09/22 16:41:45 import ip database updates
IP_INFO: 2024/09/22 16:43:41 creating ip_to_city_one_ip_start_gist_idx index on ip_to_city_one table
IP_INFO: 2024/09/22 16:45:18 switching backup and working tables
IP_INFO: 2024/09/22 16:45:18 updating database config
IP_INFO: 2024/09/22 16:45:18 ip database update completed, next update through 223.2h
And we can make several test requests:
$ curl localhost:8080/ip-info?ip=8.8.8.8
{
"error": "",
"content": {
"ip": "8.8.8.8",
"continent": "NA",
"country": "US",
"state_prov": "California",
"city": "Mountain View",
"latitude": -122.085,
"longitude": 37.4223
}
}
$ grpcurl -plaintext -d '{"ip": "211.27.38.98"}' 127.0.0.1:50051 IpInfo/GetIpInfo
{
"ip": "211.27.38.98",
"continent": "OC",
"country": "AU",
"stateProv": "New South Wales",
"city": "Sydney",
"latitude": 151.209,
"longitude": -33.8688
}
IP randomization is not supported for security reasons, the difference in tests is about 10% for cases where 1 IP is requested and when the IP is requested randomly.
- http benchmarking with hey - HTTP load generator tool without cache:
$ hey -c 2 -n 10000 http://127.0.0.1:8080/ip-info?ip=8.8.8.8
Total: 3.7542 secs
Slowest: 0.0097 secs
Fastest: 0.0005 secs
Average: 0.0007 secs
Requests/sec: 2663.6510
when redis cache used:
Total: 2.1551 secs
Slowest: 0.0355 secs
Fastest: 0.0003 secs
Average: 0.0004 secs
Requests/sec: 4640.0855
when memory cache used:
Total: 1.0665 secs
Slowest: 0.0032 secs
Fastest: 0.0001 secs
Average: 0.0002 secs
Requests/sec: 9376.7398
- gRPC benchmarking with ghz - Simple gRPC load testing tool without cache:
$ ghz -c 2 -n 10000 127.0.0.1:50051 --call IpInfo.GetIpInfo -d '{"ip":"8.8.8.8"}' --insecure
Total: 6.73 s
Slowest: 8.95 ms
Fastest: 0.61 ms
Average: 1.09 ms
Requests/sec: 1485.69
when redis cache used:
Total: 4.40 s
Slowest: 3.55 ms
Fastest: 0.37 ms
Average: 0.63 ms
Requests/sec: 2270.86
when memory cache used:
Total: 3.04 s
Slowest: 2.41 ms
Fastest: 0.19 ms
Average: 0.37 ms
Requests/sec: 3285.49
You could choose limiter between redis_rate (redis should be present) and golimiter, using -limiter-provider flag or IP_INFO_LIMITER_PROVIDER environment variable. To enable rate limiting run ip-info microservice with the -enable-limiter flag or IP_INFO_ENABLE_LIMITER environment variable. The default rate limit value is 10 requests per second per client, you can adjust it with the -rate-limit flag or IP_INFO_RATE_LIMIT environment variable.
version: "3.4"
services:
ip-info:
image: streamdp/ip-info:v0.2.0
container_name: ip-info
environment:
- IP_INFO_DATABASE_URL=postgresql://postgres:postgres@postgres:5432/dbip?sslmode=disable
- IP_INFO_ENABLE_LIMITER=true
- IP_INFO_RATE_LIMIT=15 # default 10 requests per second per client
- IP_INFO_LIMITER_PROVIDER=redis_rate # default "golimiter"
- REDIS_URL=redis://:qwerty@redis:6379/0
ports:
- "8080:8080"
- "50051:50051"
restart: always
redis:
image: redis
container_name: redis
ports:
- "6379:6379"
command: redis-server --save "" --maxmemory 64mb --maxmemory-policy allkeys-lfu --requirepass qwerty
restart: always
$ docker-compose up -d
Caching in-memory with microcache library is enabled by default, to disable you need to run ip-info microservice with the -disable-cache flag or IP_INFO_DISABLE_CACHE=true environment variable. The default TTL value is 3600 seconds, you can adjust it with the -cache-ttl flag or IP_INFO_CACHE_TTL environment variable. You could choose cache provider between redis and microcache, using -cache-provider flag or IP_INFO_CACHE_PROVIDER environment variable.
version: "3.4"
services:
ip-info:
environment:
- IP_INFO_CACHE_TTL=1800 # default 3600 seconds
- IP_INFO_CACHE_PROVIDER=redis # default "microcache"
- REDIS_URL=redis://:qwerty@redis:6379/0
You can see all available command flags when you run the application with the -h flag.
$ ./bin/app -h
ip-info is a microservice for IP location determination
Usage of ./bin/app:
-cache-provider string
where to store cache entries: redis, microcache (default "microcache")
-cache-ttl int
cache ttl in seconds (default 3600)
-disable-cache
disable cache
-enable-limiter
enable rate limiter
-grpc-port int
grpc server port (default 50051)
-grpc-read-timeout int
gRPC server read timeout (default 5000)
-h display help
-http-port int
http server port (default 8080)
-http-read-timeout int
http server read timeout (default 5000)
-limiter-provider string
what use to limit queries: redis_rate, golimiter (default "golimiter")
-rate-limit int
rate limit, rps per client (default 10)
-rate-limit-ttl int
rate limit entries ttl in seconds (default 60)
-read-header-timeout int
http server read header timeout (default 5000)
-redis-db int
redis database
-redis-host string
redis host (default "127.0.0.1")
-redis-port int
redis port (default 6379)
-v display version
-write-timeout int
http server write timeout (default 5000)
Contributions are welcome! If you encounter any issues, have suggestions for new features, or want to improve ip-info, please feel free to open an issue or submit a pull request on the project's GitHub repository.
ip-info is released under the GPL 3.0 License. See the LICENSE file for complete license details.
DigitalOcean referral link.