Brad Fitzpatrick (brad) wrote,
Brad Fitzpatrick

monobal 0.1; more C# questions

I've named my C# reverse proxy load balancer "monobal", sounding like "cannibal". (stress on first syllable, not 1st and 3rd) I named it that mostly because I was afraid of any legal implications of putting "sharp" or "dot" or "dot net" in the name, but also to promote mono, and because all those "SharpFoo" projects are getting lame, like KFoo and GFoo in KDE and GNOME lands, respectively.

Anyway, it kinda works now. Shitloads of FIXMEs and TODOs, but it's working some of the time now, on some types of requests. :-)

Instead of forking off a thread per client (which would've been easy, but I'm a sucker for pain), I did all async IO with callbacks. And because .NET's async IO is done with threads (thread pools), the callback can be done in another thread, I get to deal with synchronization issues as well! More fun.

At this point you're probably thinking: uh, if async IO is done with threads, why didn't you just use threads in the first place with blocking IO? I wondered the same after discovering that, and still am a little, but I observed that it's really efficient with its thread pools. There isn't a thread for each connection... it just uses a pooled thread to do IO whenever necessary. And mono is even using Linux 2.6 syscalls... saw it doing futex(). Go mono!

Um, C# wizards.... anybody know the interactions between doing async IO (BeginWrite) on a BufferedStream wrapping a NetworkStream? The callback never seems to be run after myBufferedStream.BeginWrite(...). I'd expect the BufferedSteam to at least invoke my callback saying, "Yo, I added your crap to my buffer, even if I'm not telling you whether or not I'm pushing it out to the NetworkStream yet." And I don't even get the callback(s) after doing myBufferedStream.Flush(). I mean, the whole program runs and I get the data in my test HTTP client, but I never got the callbacks to all my writes to the client. Mysterious.

Eh... I can probably just not use the BufferedStream class since I'm pretty much doing its job already, but I want to understand it.

Oh, and as an update to my earlier rant about working with strings without encodings, and doing regular expressions on buffers, ignoring but preserving 8 bit data: The Encoding class only has static instances of Encoding.ASCII, .UTF8, .UTF7 and some other Unicode-ish ones, so I didn't think to just do: Encoding.GetEncoding("ISO-8859-1"). Or any other encoding with 256 unique byte/char mappings. So I can take Mr. Anonymous Unknown8bit buffer, assume it's Latin-1, fiddle with it as a String ignoring high bytes, then go back to a byte buffer using the same encoding, even if it was actually Russian or something.

After learning C#'s networking and IO classes a bit more, next step is abstracting out the backend node selection class. (round robin vs. random vs. custom)

Fun fun.
Tags: perlbal, tech

  • Post a new comment


    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.