Writing a REST server to run on FreeBSD -- how to structure for concurrency?


 
Thread Tools Search this Thread
Top Forums UNIX for Advanced & Expert Users Writing a REST server to run on FreeBSD -- how to structure for concurrency?
# 1  
Old 09-07-2016
Writing a REST server to run on FreeBSD -- how to structure for concurrency?

Hi All,

I want to write a domain specific REST/HTTP server to run on FreeBSD. I have control over both the server side and the primary client intended to consume the service.

My question is: how do you think it should be designed to support multiple connections, given:
  1. It will run on a modern x86 chip (I7 6700K) which has 4 cores, each running two threads.
  2. REST transactions are short-lived, request/response, which are basically HTTP requests (GET, POST, DELETE).

Is fork() too costly for each connection?
Is kqueue the wrong tool, given that the connections are not really long-lived and do not consist of repeated updates/polling?
Should I use a thread approach where I have the master, and then create a new thread for each connection and then terminate the thread after the response is sent back?

I am really at a loss as to what the most effective approach to take is. While it may never be used, I'd at least like to design it to be efficient and capable of supporting as many concurrent connections as possible!

Thanks for any suggestions.

(I want to write it for multiple reasons: to learn, to challenge myself, to build something minimalistic, because the sun rises, etc. I realize I could just grab and go with an existing web server but I don't want to do that.)

Last edited by rbatte1; 09-14-2016 at 06:10 AM.. Reason: Converted to formatted number-list
# 2  
Old 09-08-2016
fork is expensive.

Take a lool at the Erlang programming language and Cowboy or Yaws webserver.
The language is built for highly concurrent applications.
# 3  
Old 09-09-2016
Quote:
Originally Posted by LittleCookieMon
1. It will run on a modern x86 chip (I7 6700K) which has 4 cores, each running two threads.
Hyperthreading does not work that way. The eight "threads" are not program threads, just a side-effect of how the OS manages the four cores in hyperthreading mode. Four cores, four threads.

Since this is I/O and network related though, those threads may spend a lot of time waiting anyway though.
Quote:
Is fork() too costly for each connection?
Yes.

Quote:
Is kqueue the wrong tool, given that the connections are not really long-lived and do not consist of repeated updates/polling?
They may not be long-lived, but HTTP still means lots of waiting for responses. You can have thousands of threads which spend 99% of their time waiting, or a few threads which spend most of their time working.

That's what makes aggregation routines like select and kqueue efficient. You can watch a set of things, waiting for any of them to become ready, without wasting time creating surplus threads which all sit around waiting.

Assigning one thread to multiple sockets can be efficient -- you can handle whichever one becomes ready out of a large set and handle it. One thread can do a lot of work in a short amount of time if you don't interrupt them by creating and killing them all the time. You can even do this in a single-threaded approach to make something surprisingly responsive.

Quote:
Should I use a thread approach where I have the master, and then create a new thread for each connection and then terminate the thread after the response is sent back?
That's almost the same problem as creating processes. Don't create a new anything for each connection.

Quote:
I am really at a loss as to what the most effective approach to take is.
If there was a perfect 'most effective' approach everyone would use it and throw out the rest. Approaches can and do vary.

My approach would be to have one thread which loops on accept() and puts the socket in a queue of some sort, for one of a fixed number of worker threads to grab it from and add it to the pile of sockets each worker thread is communicating with.

If you wanted to build something minimalistic, how about a single-threaded approach using select or kqueue to respond to connections and I/O as they become ready, rather than first-come-first-serve? People assume it's necessary to multithread to do anything but FCFS these days, but that's not strictly true, especially for lots of short-lived tasks. That's why a single thread can still be so effective at dealing with lots of small tasks -- given enough work, all the time it'd waste on waiting can actually get used.

Last edited by Corona688; 09-09-2016 at 06:23 PM..
# 4  
Old 09-12-2016
Sorry for the delayed response.

A very big thank you to Corona688 and unficyp for the suggestions!

I'm still going to give it a shot; really busy right now so unable to implement it but I've bookmarked your advice, Corona688 and will definitely try some of the suggestions.

I think I may start with a two-thread approach: one listening, one processing (worker).

Might there be a benefit to using two threads over two processes in this case? (listener and worker) ? Or is it simply stylistically (choosing to use a shared shared heap & stack vs building inter process communication)
This User Gave Thanks to LittleCookieMon For This Post:
# 5  
Old 09-13-2016
Shared memory can happen in IPC, too. What isn't shared between processes is file/socket handles. Theoretically, you can copy a file handle from one process to another, but the procedure for doing so without resorting to fork() makes me smell burnt toast... Threads of course don't have this problem, they share everything.

IPC is also a can of worms in some ways, their synchronization primitives have read/write bits just like files do, if you're not building your own private client/server model they can be more complicated than needed.
# 6  
Old 09-18-2016
Corona688 -- an additional question for you:

As to your advice on "My approach would be to have one thread which loops on accept() and puts the socket in a queue of some sort, for one of a fixed number of worker threads to grab it from and add it to the pile of sockets each worker thread is communicating with."

Is there a recommended queue or messaging feature to accomplish this that I should research?

I see quite literally there are message queues (system V?), and the use of msgget() msgsnd() and msgrcv(). Is this particularly what you had in mind, and if so, is there any things to be mindful of to send socket descriptors through a message queue?

Thanks again!

---------- Post updated at 06:25 PM ---------- Previous update was at 04:42 PM ----------

Corona668 / others:

Is this a reasonable way?

Parent process starts worker processes
Listens on a socket for incoming connections and accept()s them

On accepting new connection:

Using UNIX Domain socket, using SCM_RIGHTS send descriptor to child worker process that is running. Worker process is decided by simple counter, e.g. i++ that resets once i == #worker processes. Very basic round-robin approach.

Would this suffice over the message queue approach?

Last edited by LittleCookieMon; 09-18-2016 at 07:36 PM..
# 7  
Old 09-19-2016
sysvcipc is very high-overhead. I just meant building a queue out of memory and pthread mutexes, linux semaphores, or whatever kind of lower level IPC you had available.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Run rest of script after parallel steps have completed

Hello gurus, I produce a number of .loc files in parallel depending on number of .csv in the folder for file in *csv do ./process.sh $file > $file.loc & done then I want to compile all the output from the previous step into a single masterlocfile and then perform the rest of the steps... (2 Replies)
Discussion started by: senhia83
2 Replies

2. Shell Programming and Scripting

Help with writing a script to run java commands in sequence in UNIX

Hi, Brand new to these forums, and I hope that someone can help me out. I'm trying to run the following command in UNIX java -jar GenomeAnalysisTK.jar -T SplitSamFile -dt NONE -R reference.fa -I my.bam --outputRoot /my/path/SampleFiles/Sample_ It executes the SplitSamFile from GATK, but I... (3 Replies)
Discussion started by: Wixaros
3 Replies

3. Shell Programming and Scripting

Run command without over-writing

I have a script called script.sh that has the following in it. cat /home/auto/script.sh #!/bin/bash ARGA=$1 if ; then echo "${ARGA}:Confirmed" else echo "${ARGA}:Unconfirmed" fi I need a way to run this script, and then, after script has confirmed the... (9 Replies)
Discussion started by: SkySmart
9 Replies

4. UNIX for Dummies Questions & Answers

copying the dir/subdir structure from one server to another?

Hi All, I want to copy the dir/subdir structure from SERVER-A to SERVER-B without copying all the files in each dir. Is it possible using SCP / SFTP command? For example, SERVER-A has following two dir/subdirectories and files under each subdir. ... (1 Reply)
Discussion started by: Hangman2
1 Replies

5. Shell Programming and Scripting

Need to copy a directory structure from one server to another

Hello All, I have got a dev server and a production server will call it as D server and P server. I have a dir structure in my D server and i need to create the same dir structure in P server also using a shell script. If i do a find . in my D server, i am getting an o/p like :- . ./vio... (9 Replies)
Discussion started by: Renjesh
9 Replies

6. Shell Programming and Scripting

Run SED for all index.jsp files across a directory structure.

Hi, I am a novice and require help once again. I have a over 200 file all called index.jsp placed in different directories The following Sed command gives me the data of all included jsp files in index.jsp sed -n -e 's/^.*page="\(*\).*$/\1/p' index.jsp How can I run the above... (6 Replies)
Discussion started by: rajkdutta
6 Replies

7. UNIX for Advanced & Expert Users

Has anyone run the linux boinc client on FreeBSD

The reason I ask is because the einstein client in the freash ports is not the current one with boinc. No new work is being assigned. They sugested or asked if I could run boinc 6.10.17 linux in emulation and if so, I would be able to crunch einstein data. so, anyone done the linux emulation of... (0 Replies)
Discussion started by: droolin
0 Replies

8. Shell Programming and Scripting

Script to run a command on all txt files present in a dir structure

Hi, I have a directory structure like the one given below root\a\b1 root\a\b2 root\b\b1 root\b\b2 . . . root\j\b1 root\j\b2 Now, there are a txt files in each dir and subdir, there is a root.txt I have to write a script where in i have to run a command called "genrb <filename>"... (6 Replies)
Discussion started by: vikramsinghnegi
6 Replies

9. Shell Programming and Scripting

Shell script for a writing the directory structure to a file

Hi All, I am new user of shell scripting has come up with a problem. that I have a directory structure like : Home | |--------A | |----trunk | |-------A_0_1/ | | | |-------A_0_2/ | |--------B | ... (6 Replies)
Discussion started by: bhaskar_m
6 Replies

10. UNIX for Dummies Questions & Answers

I'm looking for a 64-bit Desktop that will run Windows, Linspire, FreeBSD and Solaris

Ok, I've been shopping around and I've seen some nice one's, but they are either too expensive or they are not 64-bit; I want to be prepared for the future at the right price (under $3,000 with a decent configuration)! :D Where can I find a good 64-bit desktop or workstation that will run the... (0 Replies)
Discussion started by: Mr. Nice Guy
0 Replies
Login or Register to Ask a Question