Tieske / uuid

A pure Lua uuid generator (modified from a Rackspace module)
http://tieske.github.io/uuid/
137 stars 50 forks source link

thread-safe mode with luasocket, microtime and central storage #6

Open develCuy opened 8 years ago

develCuy commented 8 years ago

Hello, I'm following from this https://github.com/Mashape/kong/pull/695 and https://github.com/sailorproject/sailor/issues/58

I want to propose the following solution for the seeding issue:

  1. Seeding: threads use output of require 'socket':gettime()
  2. Seed needs to be confirmed by creating a file /temp_folder/[timestamp].uuid
  3. If file exists already then get a new timestamp (retry 256 times by default)

This way we get a different seed for each thread. Production servers can run tmpfs (in-memory filesystem) to optimize speeds (no need to relay on database storage).

I know this has limitations, but who in the world is running more than 256 threads on a single microsecond?

develCuy commented 8 years ago

@Tieske, I have created an script that runs 256 processes, each of them use method above to get a unique seed:

uuid_test.lua: https://gist.github.com/develCuy/87a52426f7d2dc2b1948 run_test.sh: https://gist.github.com/develCuy/9c6e4a2e32f326f7f566

This is how to run the test:

  $ time ./run_test.sh | sort | uniq --count
Tieske commented 8 years ago

Obviously depending on the use case it could be wrapped to include such a check. But I do not think it should be part of this library.

Tieske commented 8 years ago

Instead of creating many files, why not creating a single one, and upon seeding, keep it open for several milliseconds, before closing it again. If the file cannot be created, sleep for a few milliseconds, and try again. That should keep the filesystem clean, and still ensure proper seeding. It only makes the call to the seeding code slower, but this is intended to be run only once, so shouldn't be a problem.

Tieske commented 8 years ago

anyway; remember that file based stuff can turn out to become blocking and stop a server process.

felipedaragon commented 8 years ago

"file based stuff can turn out to become blocking and stop a server process" true! This is how the session library from CGILua crashes the process if it receives a large number of requests - it makes some insecure file operations when creating a new session, so someone can trigger this and make a simple denial-of-service attack.

felipedaragon commented 8 years ago

The less it relies on file based operations the more reliable and secure it will be

develCuy commented 8 years ago

@felipedaragon, 256 processes in parallel is an extreme use case. There are about 1 to 8 threads (2 per core) in a dev server and 8 to 64 in a production server. A good setup runs one worker per thread, so the most extreme case is actually 64 processes in parallel. Also, they only compete for a unique seed when they start, as the uuid library should be loaded once per worker. The amount of file operations is pretty acceptable IMHO, no DDoS risk at all. Now, if somebody is running a CGI server, so that uuid module is loaded once per http request, such setup is risky not because of file operations, but because of CGI, we should document that CGI is not recommended for servers with more than 4 threads, so that there are only 4 processes competing for a seed.

felipedaragon commented 8 years ago

@develCuy you're probably right. I just wanted the new session library to be the most solid and resilient we can get.

PS: you put an extra D to DoS. With the CGILua thing I was just referring to the classic, non-distributed form :)