Publicidad
Publicidad

Más contenido relacionado

Publicidad

Fast CGI for humans

  1. FastCGI for humans incomplete dive in
  2. What is it? FastCGI is a binary protocol for interfacing interactive programs with a web server. - wikipedia That‘s it! HTTP FastCGI
  3. How it works Multithreaded application application running as daemon Easy! Socket connection (potentially multiplexed) FastCGI Data Streams of FastCGI Records Web server (Nginx)
  4. Let’s dive in
  5. FastCGI record general structure typedef struct { unsigned char version; unsigned char type; unsigned char requestIdB1; unsigned char requestIdB0; unsigned char contentLengthB1; unsigned char contentLengthB0; unsigned char paddingLength; unsigned char reserved; unsigned char contentData[contentLength]; unsigned char paddingData[paddingLength]; } FCGI_Record; Multi-byte data split across singular bytes One byte of data
  6. Restoring multi-byte data across 2 bytes: number = (b1 << 8) + b0 across 4 bytes: number = ((b3 & 0x7f) << 24) + (b2 << 16) + (b1 << 8) + b0 unsigned char contentLengthB1; unsigned char contentLengthB0;
  7. FastCGI message structure Header (8 bytes) Body (content length + padding length bytes) FastCgimessage [ ] Each message (basically a piece of data) starts with a Header record
  8. FastCGI header structure typedef struct { unsigned char version; unsigned char type; unsigned char requestIdB1; unsigned char requestIdB0; unsigned char contentLengthB1; unsigned char contentLengthB0; unsigned char paddingLength; unsigned char reserved; } FCGI_Record; Multi-byte data split across singular bytes 8 bytes Record type Body length
  9. Types of record types ● BeginRequest ● Params ● GetValues ● StdIn / Data ● GetValuesResult ● StdOut ● StdErr ● EndRequest ● AbortRequest ● UnknownType Incoming Outgoing Has body Management record types: - GetValues - GetValuesResult - UnknownType Application record types: - BeginRequest - Params - StdIn - StdOut - StdErr - Data - AbortRequest - EndRequest
  10. BeginRequest structure typedef struct { unsigned char roleB1; unsigned char roleB0; unsigned char flags; unsigned char reserved[5]; } FCGI_BeginRequestBody; Application role Responder Authorizer Filter Keep connection flag Always 8 bytes
  11. Params visual structure Name length info 1 byte or 4 bytes Value length info 1 byte or 4 bytes Name ( N bytes) Value ( N bytes) nameLengthB0 >> 7 == 0 nameLengthB3 >> 7 ==1 valueLengthB0 >> 7 == 0 valueLengthB3 >> 7 ==1
  12. Params structure (name and value length 1 byte each) typedef struct { unsigned char nameLengthB0; /* nameLengthB0 >> 7 == 0 */ unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */ unsigned char nameData[nameLength]; unsigned char valueData[valueLength]; } FCGI_NameValuePair11; Byte 0 Byte 1 Bytes 2-13 Bytes 14-16 12 3 FCGI_VERSION 1.1 Name length <= 127 Value length <= 127
  13. Params structure (4 bytes name length and 1 byte value length) typedef struct { unsigned char nameLengthB3; /* nameLengthB3 >> 7 == 1 */ unsigned char nameLengthB2; unsigned char nameLengthB1; unsigned char nameLengthB0; unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */ unsigned char nameData[nameLength ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0]; unsigned char valueData[valueLength]; } FCGI_NameValuePair41; 2’147’483’647 >= Name length > 127 Value length <= 127
  14. Params structure (1 byte name length and 4 bytes value length) typedef struct { unsigned char nameLengthB0; /* nameLengthB0 >> 7 == 0 */ unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */ unsigned char valueLengthB2; unsigned char valueLengthB1; unsigned char valueLengthB0; unsigned char nameData[nameLength]; unsigned char valueData[valueLength ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0]; } FCGI_NameValuePair14; 2’147’483’647 >= Value length > 127 Name length <= 127
  15. Params structure (4 bytes name and value length) typedef struct { unsigned char nameLengthB3; /* nameLengthB3 >> 7 == 1 */ unsigned char nameLengthB2; unsigned char nameLengthB1; unsigned char nameLengthB0; unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */ unsigned char valueLengthB2; unsigned char valueLengthB1; unsigned char valueLengthB0; unsigned char nameData[nameLength]; ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0]; unsigned char valueData[valueLength ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0]; } FCGI_NameValuePair14; 2’147’483’647 >= Value length > 127 Name length <= 127
  16. GetValuesResult structure = Params structure in reversed order Cool formulas to split number across 2 or 4 bytes: across 2 bytes: byte0 = number & 0xff byte1 = (number >> 8) & 0xff across 4 bytes: byte0 = (number >> 24) & 0xff byte1 = (number >> 16) & 0xff byte2 = (number >> 8) & 0xff byte3 = number & 0xff
  17. StdIn / StdOut / StdErr / Data It’s pretty simple to read from and to write to these record types. Just read everything! (<= contentlength + paddingLength)
  18. End Request structure typedef struct { unsigned char appStatusB3; unsigned char appStatusB2; unsigned char appStatusB1; unsigned char appStatusB0; unsigned char protocolStatus; unsigned char reserved[3]; } FCGI_EndRequestBody; Custom application status Protocol status Can’t multiplex connection Overloaded Request complete Unknown role
  19. Sample message flow Header (BeginRequest) BeginRequest Body Header (Params) Params Body (Server variables, headers and etc.) Header (StdIn / Data) Raw content (Form data, file transfers and etc., usually in a raw HTTP message format) Header (StdOut / StdErr) Raw content (Form data, file transfers and etc., usually in a raw HTTP message format) Header (EndRequest) EndRequest body with “Request Complete” status
  20. Hey, speedy! or biased benchmarking $ ab -k -c 10 -n 1000 http://127.0.0.1:8080/ Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 2 95% 2 98% 2 99% 2 100% 3 (longest request)
  21. Thanks!
Publicidad