Rapportdokumenteret arbejde. Webserver med caching i JCSP



Relaterede dokumenter
PHP Quick Teknisk Ordbog

dmasark Aflevering - Uge 50

Arkitektur for begyndere

EG Data Inform. Byggebasen. WCF og webservices. Jens Karsø

PHP 3 UGERS FORLØB PHP, MYSQL & SQL

DM507 Algoritmer og datastrukturer

Procesbeskrivelse - Webprogrammering

OpenTele Server Performance Test Rapport

Internet vs WWW. Internettet er IKKE det samme som www. Internettet Er et netværk af computere Gør det muligt af dele information

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

FairSSL Fair priser fair support

DM507 Algoritmer og datastrukturer

- Installationsvejledning for SOSIGW 1.1, NSP

RMI avanceret. Denne artikel beskriver nogle mere avancerede features i RMI. Den gør det muligt at lave mere realistiske applikationer.

PID2000 Archive Service

JSP, Tomcat. Tutorial lavet af Jákup W. Hansen TSU semester 10.october 2007

Navision Stat (NS 9.2)

Mindstekrav til udstyr (fase 1) Løsningsbeskrivelse

Vejledning til Teknisk opsætning

Virksomhedspræsentation for IDA

Design Systemkald. User-mode Linux, The Linux kernel/

DM507 Algoritmer og datastrukturer

2. SEMESTER PROJEKT 3 INTERAKTIONSUDVIKLING

SYSTEMDOKUMENTATION AF POC

DM507 Algoritmer og datastrukturer

Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt.

Godkendelsesdato Version Rettet af Rettelse(r)

Netværk & elektronik

It og informationssøgning Forelæsning november 2006 Jakob Grue Simonsen. Hypertekst og Python. Andersen & Simonsen: kap. 12

SmartFraming Et vindue til nationale sundhedssystemer. Version 3.0

Digital Print Room Implementering og tilretning. 11. Sep TMC Plot-SIG

Test af It-komponent

Opdatering af ISOWARE til version 6.1.0

Guide til Umbraco CMS

Digital post Snitflader Bilag A5 - REST HTTP returkoder Version 6.3

Computer Networks Specielt om Infrastrukturer og Teknologi

Databaseadgang fra Java

TCP & UDP. - de transportansvarlige på lag 4. Netteknik 1

MANUAL. Præsentation af Temperaturloggerdata. Version 2.0

Kaminsky DNS exploit

Network Services Location Manager. Håndbog for netværksadministratorer

STS Designdokument. STS Designdokument

Hvordan vælger jeg dokumentprofilen?

DKAL Snitflader REST HTTP returkoder

IDAP manual Emission

DM507 Algoritmer og datastrukturer

Software 1 with Java. Recitation No. 7 (Servlets, Inheritance)

A Profile for Safety Critical Java

3. PROJEKT, 2 SEMESTER

Listen over reserverede ord er meget lang, men de væsentligste vil jeg beskrive her i denne artikel:

BOULEVARDEN 19E 7100 VEJLE LERSØ PARKALLE KØBENHAVN Ø TLF Webservices Installationsvejledning

Tech College Aalborg. ASP.NET Hjemmeside. Projekt Smart Zenior Home - Guide til ASP.NET hjemmeside med Visual Studio

Opsætning af MobilePBX med Kalenderdatabase

Fjernadgang til BEC s systemer via Portal2

DK-Cartridge 1.0. Distributionsformat for digital læringsindhold VERSION: 1.0

TM Tandpleje. Borger.dk modul

Ethereal Intro && Ethereal HTTP. René Hansen Anders Bjerg Pedersen Michael Nilou Hold 1 September 12, 2007

Google Tag Manager tracking

FairSSL Fair priser fair support

Rx: Treating bugs as allergies a safe method to survive software failures. DIKU, Datalogisk Institut, Københavns Universitet 04/01/2006

Web-baseret metadata redigeringsmodul

Eksamen, DSDS, efterår 2007

DM507 Algoritmer og datastrukturer

DM507 Eksamen Obligatorisk Opgave Rejseplanlægning

Password-beskyttelse af visse filer

Fjernadgang til BEC s systemer via Portal2

Modern Concurrency Abstractions for C#

Bemærk! Et PHP script har kun brug for at forbinde én gang til databaseserveren. Det kan så sagtens udføre flere kommandoer vha. denne forbindelse.

DM507 Algoritmer og datastrukturer

Introduction til.net remoting i C#

Introduktion til OPC Access

Kom i gang med SAS STPbaserede

OIOREST webservice design. Guideline til design af REST-baserede webservices. Udgivet af: IT- & Telestyrelsen

JavaScript. nedarvning.

Schedulering af SAS job i MS Task Scheduler, som sender med log og statuskode ved fejl

Gode praksisser og arkitekturer i Android-programmering. Android - praksisser og arkitekturer Copyright Lund & Bendsen A/S

Opstartsvejledning ATS aktørudgave

Lav dine egne hjemmesider/websider

IT projekt uge 4 9. Marie Vinter, Roskilde Tekniske Gymnasium, klasse 2.6 IT, bw, uge

Send fra Java. Denne artikel fortæller hvad man skal bruge og hvordan man skal kode for at sende fra Java.

DANMARKS TEKNISKE UNIVERSITET

SOSIGW. - Administrationskonsol for SOSIGW Indeks

Program Dokumentation PC Software Skrevet af. Gruppen. Version 1.0

Denne rapport er skrevet af:

Hassansalem.dk/delpin User: admin Pass: admin BACKEND

IT Support Guide. Installation af netværksprinter (direkte IP print)

Vilkår for dialogintegration SAPA

Byggeriets Evaluerings Center

FairSSL Fair priser fair support

Web sider. Introduktion: Har du nogensinde spekuleret over, hvordan det verdesomspændende internet virker og hvordan man snakker med det?

Principper for Samtidighed og Styresystemer

Løsning af møntproblemet

Tech College Aalborg. HomePort. Projekt Smart Zenior Home Guide til udvikling af nye adaptere til HomePort

DM507 Algoritmer og datastrukturer

Abstrakte datatyper C#-version

Processer og tråde. dopsys 1

Transkript:

Rapportdokumenteret arbejde Webserver med caching i JCSP Espen Højsgaard Rune Højsgaard Jacob Munk-Stander 4. juni 2006 Indhold 1 Indledning 4 2 Projektbeskrivelse 4 2.1 Projektafgrænsning............................... 5 3 CSP formulering 6 3.1 CSP WebServer................................. 6 3.2 Procesgrupper.................................. 7 3.3 Kanaler..................................... 8 3.4 Processer og procesnetværk.......................... 8 3.4.1 Logger.................................. 8 3.4.2 Connector................................ 9 3.4.3 SocketHandler............................. 9 3.4.4 RequestHandler............................ 10 3.5 Detaljeret CSP WebServer........................... 11 3.6 Valg af implementationssprog......................... 11 3.7 Sammenligning med relateret arbejde..................... 12 4 Implementation i JCSP 13 4.1 Kanaler..................................... 13 4.2 Fra CSP design til implementation...................... 14 4.3 Afvigelser fra CSP............................... 15 4.4 CSP WebServer procesbeskrivelser....................... 15

4.4.1 Logger.................................. 15 4.4.2 Connector................................ 15 4.4.3 ResponseSender............................ 15 4.4.4 RequestReader............................. 17 4.4.5 RequestMultiplexer.......................... 17 4.4.6 FileCache................................ 17 4.4.7 FileFetcher.............................. 19 4.4.8 Executer................................ 19 4.5 Brugervejledning................................ 21 4.6 Afprøvning................................... 21 4.6.1 Logger test............................... 22 4.6.2 Connector test............................. 22 4.6.3 ResponseSender test.......................... 22 4.6.4 RequestReader test.......................... 22 4.6.5 RequestMultiplexer test....................... 22 4.6.6 FileCache test............................. 22 4.6.7 FileFetcher test............................ 23 4.6.8 Executer test.............................. 23 5 Evaluering 24 5.1 Opstilling.................................... 24 6 Konklusion 26 6.1 Fremtidigt arbejde............................... 27 7 Litteratur 28 A Evaluering af Any2Any kontra multiple One2Any kanaler 29 A.1 Kildekode.................................... 29 A.1.1 Any2AnyTest.mRSL.......................... 29 A.1.2 Any2AnyTest.java........................... 30 A.1.3 MultipleOne2AnyTest.java....................... 31 B Kildekode, CSP WebServer 33 B.1 CachedFileSystem.java............................. 33 B.2 Connector.java................................. 33 B.3 Executer.java.................................. 34 B.4 FileCache.java.................................. 34 B.5 FileFetcher.java................................. 36 B.6 LogChannel.java................................ 36 B.7 LogEntry.java.................................. 37 B.8 Logger.java................................... 37 B.9 Pair.java..................................... 38 2

B.10 Request.java................................... 38 B.11 RequestMultiplexer.java............................ 40 B.12 RequestReader.java............................... 40 B.13 Response.java.................................. 43 B.14 ResponseSender.java.............................. 44 B.15 SocketHandler.java............................... 46 B.16 StreamReader.java............................... 46 B.17 WebServer.java................................. 48 C Kildekode, afprøvning 50 C.1 LoggerTest.java................................. 50 C.2 ConnectorTest.java............................... 50 C.3 ResponseSenderTest.java............................ 51 C.4 RequestReaderTest.java............................ 51 C.5 RequestMultiplexerTest.java.......................... 52 C.6 FileCacheTest.java............................... 53 C.7 FileFetcherTest.java............................... 54 C.8 ExecuterTest.java................................ 55 D Kildekode, evaluering 56 D.1 RequestGeneratorMain.java.......................... 56 3

1 Indledning Denne rapport dokumenterer arbejde udført under kurset Ekstrem multiprogrammering, foråret 2006. Kurset har til formål at introducere brugen af multi-trådning som det basale designparadigme for applikationer. Rent praktisk tages der udgangspunkt i algebraen for Communicating Sequential Processes (CSP), som sikrer mod deadlocks og race-conditions. Som projekt har vi valgt at implementere en HTTP/1.1 webserver [4] med understøttelse af HEAD- og GET-metoderne i Java CSP (JCSP) [3]. HTTP-protokollen er en tilstandsløs protokol, som udmærker sig til brug i vores opgave, da det tillader at hver forespørgsel kan behandles af en separat proces. Udover implementationen af webserveren vil vi se nærmere på, hvordan man ved brug af caching kan mindske tilgangen til disken. I det følgende vil vi i afsnit 2 afgrænse projektet efter at have analyseret HTTP/1.1 protokollen med henblik på at afdække hvordan CSP kan bruges i netop denne kontekst. I afsnit 3 vil vi gennemgå det overordnede design af CSP-netværket i vores implementation, herunder brugen af caching, hvilket vi da konkretiserer i afsnit 4, hvor selve implementationen og specifikke designvalg i forhold til JCSP beskrives. I afsnit 4.6 afprøves implementationen og en evaluering foretages i afsnit 5 med fokus på de designvalg der tidligere er truffet. I afsnit 6 konkluderes på de erfaringer vi har opnået igennem projektforløbet og fremtidigt arbejde beskrives. 2 Projektbeskrivelse Da Tim Berners-Lee i 1991 opfandt World Wide Web (WWW) var det ved brug af simple midler. Grundpillerne består af HTML til at formatere og linke sider sammen, som da bliver vist i en browser. Ressourcer som indholdssider og billeder refereres til ved brug af Uniform Resource Identifiers (URI). Disse hentes da fra en webserver vha. HTTP-protokollen. Eksempelvis vil en browser hente ressourcen http://www.diku.dk/index.html ved at forbinde til serveren www.diku.dk på TCP-portnummer 80 (dvs. at der nu er en sokkel 1 imellem de to) og dernæst anmode om ressourcen ved brug af kommandoen GET /index.html HTTP/1.0 og evt. efterfølgende headere. To på hinanden følgende linjeskift 2 markerer afslutningen af forespørgslen. Webserveren går nu igang med at behandle forespørgslen og returnerer en statuskode, eksempelvis HTTP/1.0 200 OK 1 eng: socket 2 linjeskift angives i HTTP protokollen med to tegn: vognretur (decimalværdi 13) og linjeskift (decimalværdi 10). 4

efterfulgt af headere samt selve indholdet, baseret på typen af den forespurgte ressource (statiske HTML-sider, dynamisk genereret indhold f.eks. ved brug af CGI scripts, PHP, ASP.NET o.l.). Afslutningsvist lukkes forbindelsen mellem browser og webserver. Set i lyset af CSP er det oplagt at lade en proces håndtere hver forbindelse og dermed undgå en mulig flaskehals ved at behandle disse sekventielt. Dette gøres allerede i eksisterende webservere som f.eks. Apache og Microsoft Internet Information Services (IIS) ved at lade en separat tråd håndtere forespørgsler som de kommer evt. ved at have en gruppe 3 af tråde. Med tiden er det blevet mere og mere almindeligt at inkludere billeder og andre eksterne filer som f.eks. cascading style sheets (CSS), JavaScripts osv. i HTML en. Ved brug af HTTP/1.0 fører dette til et stort overhead i at oprette og lukke forbindelser mellem browser og webserver. HTTP/1.1 løser dette ved at tillade pipelining, dvs. at man over den samme forbindelse udfører multiple forespørgsler på ressourcer og angiver i en header når man ønsker at lukke forbindelsen eller blot lukker forbindelsen. På denne måde kan en browser hente en indholdsside og lade forbindelsen være åben. Idet den returnerede HTML bliver tolket, hentes hver af ressourcerne, der skal hentes fra samme server, over den samme forbindelse. Det er nu webserverens rolle at holde styr på rækkefølgen af forespørgsler og returnere indholdet i den samme rækkefølge som de kom, dvs. i en FIFO 4 ordning. Vi kan med HTTP/1.1 se muligheden for ikke blot at lade forbindelsen blive håndteret af en separat proces, men også lade hver enkelt forespørgsel fra en klient blive håndteret af en separat proces. For at opsummere giver det overordnet mulighed for at indføre samtidighed ved: Hver nye forbindelse disse håndteres af separate processer Hver ny forespørgsel i en forbindelse disse håndteres af separate processer Dette skulle bl.a. gerne komme til udtryk ved skalerbarhed, hvilket vi vil evaluere i afsnit 5. 2.1 Projektafgrænsning Hovedformålet med opgaven er at få praktisk erfaring med CSP og de tilhørende designparadigmer. For at opnå denne erfaring må projektet have et vist omfang, men for samtidig at kunne bevare overblikket er det nødvendigt at afgrænse dette omfang. Vi vælger at implementere en webserver i CSP, der understøtter en delmængde af HTTP/1.1-protokollen, som den er defineret i [4]. Specifikt vælger vi ikke at tage højde for alle fejlkilder og sikkerhed vil ikke være en del af vores analyse. Vores primære mål er at kunne håndtere og behandle mange samtidige forbindelser og forespørgsler. Dette vil være fokus for vores design, som det bliver analyseret i afsnit 3. 3 eng: pool, som det bruges i litteraturen om multiprogrammering 4 First In, First Out 5

Succeskriteriet er at kunne browse en hjemmeside der bliver udbudt fra vores webserver ved brug af en webbrowser som f.eks. Mozilla Firefox eller Microsoft Internet Explorer. Indholdet vil være af statisk karakter (HTML-filer, billeder, osv.), hvorfor vi begrænser os til at understøtte GET og HEAD forespørgsler. Vi vil i den forbindelse benytte en software cache af ydelseshensyn. Da caching ikke er hovedfokus i opgaven, vil den valgte caching strategi være af simpel karakter. For at udvide opgaven vælger vi også at give mulighed for dynamisk indhold ved at tillade kald til eksterne applikationer, dog uden brug af Common Gateway Interface (CGI) [6]. Dette vil give et mere realistisk design i forhold til komplette webservere som f.eks. Apache eller Microsoft Internet Information Services. Vi vælger at implementere en simpel form for logning, hvortil alle CSP processer kan skrive. Dette gør vi med øje for at kunne afluse i løbet af udviklingsfasen. Da en webserver er kendetegnet ved at være tilstandsløs, ville det tilføje unødig kompleksitet at implementere poisoning til kontrolleret nedlukning af CSP netværket. Ved at indføre logning kan en abrupt nedlukning medføre tab af log-data, men da dette primært er til egen brug finder vi dette acceptabelt. 3 CSP formulering I det følgende vil en analyse føre til et CSP design af et procesnetværk, der opfylder projektets målsætninger, som de er beskrevet og afgrænset i forrige afsnit. Med dette som udgangspunkt træffes et valg af implementationssprog. Efterfølgende beskrives forskellene mellem designet og occwebserv [1], en webserver skrevet i occam. 3.1 CSP WebServer Et af de primære designmål er at behandle mange samtidige forbindelser til serveren. Dette kan håndteres ved at have én proces, der håndterer etableringen af nye forbindelser og afleverer hver ny sokkel videre til en arbejderproces, der behandler indkomne forespørgsler og sender svar tilbage til klienten. Det andet primære designmål er at håndtere mange forespørgsler samtidigt, således at en enkelt webside inklusive tilhørende ressourcer kan leveres hurtigt; det skal altså være muligt for klienten at sende en lang række forespørgsler, uden at gøre ophold til svar mellem hver forespørgsel. Webserveren skal returnere svarene i den rækkefølge forespørgslerne er modtaget. Da en sokkel ikke kan deles og da det er nødvendigt at koordinere svarene, kan soklen ikke blot sendes videre til arbejderprocesser. I stedet sendes de enkelte forespørgsler videre til arbejderne, der så behandler disse og afleverer svaret tilbage til den uddelegerende proces. Denne sørger da for at sende svarene tilbage i den rigtige rækkefølge. En webserver, der håndterer ovenstående, kan opbygges af: 6

Connector SocketHandler-gruppe RequestHandler-gruppe en proces, der håndterer indkomne forbindelser en gruppe af processer, der håndterer kommunikationen over forbindelserne en gruppe af processer, der håndterer forespørgsler Et sådan procesnetværk er afbildet i figur 1, hvor der desuden er tilføjet en proces, der kan føre log (Logger). Da diagrammet ikke afbilder de enkelte processer, men i stedet afbilder grupper, benyttes 1 og * til at angive antallet af kanalender, de steder hvor der kan være tvivl. En One2Any-kanal er således markeret med 1 ved pilens rod og en * ved pilens hoved osv. Den stiplede kanal angiver den flytbare kanalende, der benyttes til at levere svar tilbage til den SocketHandler, der er tilknyttet den givne forespørgsel. Figur 1: WebServer procesnetværk 3.2 Procesgrupper I vores design anvender vi, for at opnå en høj grad af samtidighed, grupper af processer og procesnetværk. Hver af disse grupper består af et antal identiske processer/procesnetværk, der deles om in- og output-kanaler. En gruppe har således samme opførsel, som en enkelt af gruppens processer, med den undtagelse at rækkefølgen af output-beskeder ikke nødvendigvis svarer til rækkefølgen af input-beskeder. I figur 1 er antallet af forbindelser, som webserveren kan håndtere samtidigt, afgrænset af antallet af SocketHandler-processer i SocketHandler-gruppen. Ligeledes er antallet af forespørgsler, der kan behandles samtidig, afgrænset af størrelsen af RequestHandlergruppen. Størrelsen af de enkelte grupper i en given instans af webserveren kommer i 7

høj grad an på webserverens forventede brugsmønster. Størrelsen af grupperne skal derfor kunne konfigureres på opstartstidspunktet. Dette design giver mulighed for at webserveren i meget høj grad kan tilpasses til det forventede brugsmønster. 3.3 Kanaler Designet i figur 1 benytter en Any2Any-kanal mellem SocketHandler-gruppen og RequestHandler-gruppen. Dette kan være en flaskehals, da der kun kan afleveres én besked af gangen over kanalen. Der er to mulige løsninger på dette problem: 1. Hver SocketHandler-proces har sin egen RequestHandler-gruppe. Denne løsning har de fordele at alle SocketHandler-processer kan aflevere forespørgsler samtidig. Ulempen ved denne løsning er, at en SocketHandler-proces kan løbe tør for ledige RequestHandler-processer, mens andre SocketHandleres RequestHandlerprocesser er ledige. 2. Hver SocketHandler-proces er forbundet til alle RequestHandler-processer med en One2Any-kanal. Hver RequestHandler-proces vælger så retfærdigt mellem deres input-kanaler. Denne løsning tillader at alle SocketHandler-processer samtidig afleverer en forespørgsel, men uden at begrænse antallet af RequestHandler-processer, som den enkelte SocketHandler-proces har til rådighed. Hvorvidt disse alternativer giver en bedre løsning, i forhold til vores målsætning, kan vi ikke umiddelbart afgøre. Derfor udskydes beslutningen til implementationsafsnittet (se afsnit 4), hvor de forskellige varianter kan afprøves i det valgte sprog. 3.4 Processer og procesnetværk I dette afsnit vil hver proces opgave blive beskrevet. Hvor der kan opnås bedre parallelitet, samtidighed eller modularitet, vil processerne blive opdelt i procesnetværk. 3.4.1 Logger Denne proces modtager logbeskeder og skriver dem til disken i den rækkefølge de bliver modtaget. Samtlige processer i webserveren kan aflevere beskeder til Logger-processen over en Any2One-kanal. Denne log kan hurtigt blive en flaskehals, hvis der afleveres mange logbeskeder. For at reducere dette problem, kan logbeskederne fordeles over flere Logger-processer og kanalerne kan være buffered. Da vi som nævnt i afsnit 2.1 hovedsageligt har medtaget logning til eget brug under udviklingen, vil vi blot at benytte én log med en bufferet kanal. I et produktionssystem kan logning slås fra, hvorved flaskehalsen forsvinder. 8

3.4.2 Connector Denne proces lytter efter indkomne forbindelser. Når den modtager en forbindelse oprettes en sokkel og denne afleveres til SocketHandler-gruppen. Det er ikke muligt at oprette mere end én forbindelse af gangen, hvorfor der ikke kan oprettes en gruppe af Connectorer og dermed opnå større samtidighed omend der ikke er noget i CSP-designet, der forhindrer det. 3.4.3 SocketHandler Denne proces modtager sokler og håndterer igennem disse al ind- og udgående kommunikation. Indgående kommunikation er HTTP-forespørgsler, der afleveres videre til RequestHandler-gruppen. Udgående kommunikation er HTTP-svar, som modtages fra RequestHandler-gruppen. For at kunne læse og skrive til soklen samtidig og for at kunne aflevere beskeder til og modtage beskeder fra RequestHandler-gruppen samtidig, laves SocketHandler som et procesnetværk. Dette består af en proces, der læser de indkomne forespørgsler (RequestReader) og en proces, der kan sende svarene (ResponseSender). Dette netværk er afbildet i figur 2. Figur 2: SocketHandler procesnetværk ResponseSender modtager soklen og afleverer inddatastrømmen 5 videre til RequestReader. Desuden oprettes en One2One-kanal fra RequestReader til ResponseSender, således at det totale antal af beskeder kan kommunikeres til ResponseSender en, så denne kan lukke sin sokkel efter det sidste svar er sendt. Hvis inddatastrømmen (og dermed soklen) lukkes af klienten, sendes -1 i stedet for antallet af beskeder. 5 eng: stream 9

3.4.4 RequestHandler Denne proces modtager en forespørgsel, behandler den og returnerer svaret til den respektive SocketHandler via en flytbar kanalende. For at opnå et modulært design med nem mulighed for understøttelse af forskellige processer til forskellige typer ressourcer laves RequestHandler som et procesnetværk. For hver type af ressource, som serveren kan håndtere (.html,.exe osv.) oprettes en gruppe af processer, der kan håndtere den givne type; CachedFileSystem-gruppen håndterer biblioteker, filer med endelsen.html samt ukendte typer mens Executer-gruppen håndterer filer med endelsen.exe og.sh. For CachedFileSystem-gruppen har det betydning, hvilken proces der modtager forespørgsler på en given ressource. Anvendes en Any2Any-kanal, vil det være tilfældigt, og der vil derfor kunne være kopier af den samme fil i forskellige caches, hvilket er spild af hukommelse. Dette kan løses ved at sørge for, at forespørgsler efter en given fil altid bliver sendt til den samme cache. Ulempen ved denne løsning er, at en cache, der holder en hyppigt hentet fil, vil udgøre en flaskehals. Hvilken løsning der er mest hensigtsmæssig, vil kræve en evaluering af begge løsninger. Da caching ikke er fokus for opgaven, vælger vi den løsning, der tilgodeser hukommelsesforbuget; dvs. at én bestemt cache vil modtage alle forespørgsler på en given fil. Til at fordele forespørgslerne efter ressourcetype bruges RequestMultiplexer, der ud fra filendelsen kan afgøre, hvilken kanal en forespørgsel skal afleveres til. RequestHandler-netværket er afbildet i figur 3. En streg over en kanal angiver, at der er flere identiske kanaler. Til f.eks. CachedFileSystem-gruppen er der altså lige så mange Any2One-kanaler, som der er processer i gruppen. Figur 3: RequestHandler procesnetværk CachedFileSystem modtager en filforespørgsel, behandler den og returnerer svaret til den respektive SocketHandler. Dette gøres i et procesnetværk som afbildet i figur 4. Der oprettes én uddelegerende proces, FileCache, der holder en cache med filer i hukommelsen, og derfor med det samme kan sende et svar til den respektive SocketHandler, 10

hvis den har filen i sin cache. Desuden oprettes en gruppe af FileFetcher-processer, som kan hente filer fra filsystemet. FileFetcher-processer sender så svar til både FileCacheprocessen samt til den respektive SocketHandler. Figur 4: CachedFileSystem procesnetværk Executer modtager en forespørgsel på at afvikle et program og afvikler det. Programmets standard uddata (stdout) afleveres til den givne SocketHandler. RequestMultiplexer modtager en forespørgsel og sender den videre til en proces eller procesgruppe baseret på typen af den efterspurgte ressource (bestemt udfra endelsen). 3.5 Detaljeret CSP WebServer I de forrige afsnit har vi udvidet webserveren fra figur 1 med en række procesnetværk. Det endelige CSP-design er gengivet i figur 5, hvor Logger-processen, som alle processer kan skrive til over en Any2One-kanal, dog er udeladt af hensyn til overskueligheden. 3.6 Valg af implementationssprog Givet ovenstående analyse af selve projektet vil vi i det følgende argumentere for valg af implementationssprog ud fra de i kurset præsenterede muligheder for CSP-udvikling, dvs. occam, JCSP, C++ CSP og libcsp. Et overordnet krav til implementationssproget er, at det giver mulighed for håndtering af sokler og læsning af filer. Dette er understøttet i alle sprog, hvorfor valget er baseret på andre faktorer. 11

Figur 5: Samlede design for CSP WebServer. Hvor occam giver en tæt relation mellem CSP-algebra og sproglig syntaks, er implementationerne af CSP i de tre resterende sprog ikke lige så rene. Af de tre sprog ligger vores erfaring primært inden for Java, hvorfor vi vælger at fokusere på denne implementation kontra occam. occam giver en programmeringsmæssig udfordring set i forhold til syntaks og udvikling. I modsætning hertil stiller Java en række veldokumenterede faciliteter til rådighed, som giver mulighed for udvikling af mere funktionalitet på kortere tid. Her tænkes specielt på håndtering af sokler, filer og implementationen af caching. Af [2, p. 36] er det åbenlyst at Java ikke vil være det oplagte valg ud fra et ydelsesmæssigt synspunkt her vil Javas overhead være for stort. Givet en målsætning om at kunne håndtere mange forbindelser og forespørgsler samtidig, vil dette dog ikke være det springende punkt, da en evaluering af implementationen vil vise potentialet for skalering af designet hvormed dette i et andet sprog kan give bedre ydelse. Dog viser det sig, at Java ikke kan håndtere et større antal processer/kanaler [2, p. 41], hvilket man da må have in mente under afprøvning og evaluering af implementationen. occam-kanaler er stærkt typede, hvorved man sikrer sig imod fejl på kompileringstidspunktet. Dette er ikke muligt i JCSP, hvorfor det introducerer en mulig fejlkilde idet alt undtagen heltal vil være repræsenteret som Objecter og dernæst skal kastes til den korrekte type, med dertilhørende ydelsestab, etc. Ved brug af generics i JCSP biblioteket ville man kunne introducere stærkt typede kanaler på kompileringstidspunktet. Dette er dog ikke understøttet i den nuværende implementation af JCSP. Givet projektets relativt store omfang samt gruppens erfaring med Java vælger vi Java og JCSP som basis for vores implementation. Givet Javas platformsuafhængighed vil det samtidig være muligt at udføre evaluering af implementationen på den til kurset opstillede Sun Ultra SPARC T1 maskine på MiG. 3.7 Sammenligning med relateret arbejde Det er interessant kort at sammenligne designet af CSP WebServer med occwserv. For at tilegne os egen viden og erfaring har vi valgt først at kigge på denne efter at vores design 12

var færdiglavet. På sin vis er der mange ligheder mellem de to, men i forbindelse med håndteringen af forespørgsler er der en fundamental forskel. Som nævnt i afsnit 3.4.3 gives der i designet mulighed for at håndtere multiple forespørgsler fra samme forbindelse. I modsætning hertil er designet af occwserv baseret på at der håndteres én forespørgsel af gangen på en given forbindelse [1, p. 253]. Dette gøres ved at forbindelsen sendes rundt i netværket fra en front-end procesgruppe til den håndterende proces og afslutningsvist til en back-end proces, der afgør om forbindelsen skal lukkes. Hvis dette ikke er tilfældet sendes forbindelsen tilbage til front-end gruppen og den næste forespørgsel på forbindelsen kan da håndteres. Hvor CSP WebServer har haft ydelse som primært designmål, har occwebserv udover ydelse haft et enkelt design og en simpel implementation som mål. Set fra et ydelsesmæssigt synspunkt finder vi det mere optimalt at benytte den model vi har brugt, men erkender at designet dermed bliver mere komplekst. Udover denne forskel er occwserv mere dynamisk i forhold til vores relativt statiske design. Antallet af processer til håndtering af forespørgsler justeres i occwserv dynamisk ud fra den nuværende belastning. 4 Implementation i JCSP Ud fra det i forrige afsnit analyserede CSP design, vil vi i det følgende beskrive, hvordan vi har grebet implementationen i JCSP an og beskrive protokollerne for de enkelte processer. Da kursets formål har været at stifte bekendtskab med CSP ud fra en praktisk vinkel vil afsnittet udelukkende omhandle implementationsspecifikke detaljer for CSP-designet, dvs. de udfordringer der været i at implementere designet, samt de afvigelser fra grundprincipperne i CSP der har været nødvendige. 4.1 Kanaler Designet benytter en Any2Any kanal mellem SocketHandler-gruppen og RequestHandlergruppen. Som nævnt i afsnit 3.3 udgør denne en mulig flaskehals. Derfor har vi opstillet en simpel test, der skal afdække hvilken af de i afsnit 3.3 beskrevne løsninger, der yder bedst på Ultra SPARC T1 maskinen. JCSP tillader ikke at ALTe på One2Any-kanaler [5, p. 38], hvorfor denne metode er udelukket. De to resterende løsninger testes med de i figur 6(a) og 6(b) beskrevne procesnetværk, hvor 10.000.000 heltal afleveres fra Masterprocesserne til Worker-processerne. Begge tests er afviklet fem gange på Ultra SPARC T1 maskinen på MiG og køretiderne for samtlige kørsler kan findes i bilag A. Testen med én Any2Any-kanal tog i gennemsnit 782,7 sekunder mens testen med multiple One2Any-kanaler i gennemsnit tog 90,0 sekunder. Spredningen for begge måleserier er ubetydelig, og forholdet mellem de to gennemsnitsværdier antages derfor at give et godt billede af overheadet ved én Any2Any-kanal ift. multiple One2Any-kanaler. Da løsningen med multiple One2Any-kanaler afvikler næsten 9 gange så hurtigt, vælges denne til implementationen. 13

(a) Any2Any-testnetværk (bilag A.1.2) (b) One2Any-testnetværk (bilag A.1.3) Figur 6: Procesnetværk til afprøvning af Any2Any kontra One2Any kanaler For et system, der ikke understøtter flere samtidige tråde på hardwareniveau, er forskellen ikke lige så markant, men dog betydelig: testen med én Any2Any-kanal tog i gennemsnit 80,8 sekunder mens testen med multiple One2Any-kanaler i gennemsnit tog 52,3 sekunder. Køretiderne for disse tests kan ligeledes findes i bilag A. 4.2 Fra CSP design til implementation Overordnet har vi taget et meget pragmatisk syn på implementationen og har taget udgangspunkt i det samlede CSP-design, som det blev præsenteret i foregående afsnit, se figur 5. Da vi dog ikke længere ønsker at benytte en Any2Any-kanal mellem SocketHandlergruppen og RequestHandler-gruppen, vælger vi at implementere webserveren ud fra et revideret design: hver SocketHandler forbindes til en RequestMultiplexer med en One2Onekanal. Hver RequestMultiplexer har så stadig adgang til Any2One-kanalerne til de enkelte RequestHandler-processer. Det modificerede design er afbildet i figur 7, hvor Loggerprocessen dog igen er udeladt. Figur 7: Implementationsdesign for CSP WebServer Implementationen er baseret på en én-til-én korrespondence med de i figur 7 nævnte processer og kanaler (se bilag B for kildekode) og koden anvender de samme navne. Dette overskueliggør implementationen og letter forståelsen af koden. Brugen af webserveren er beskrevet i afsnit 4.5 14

4.3 Afvigelser fra CSP En af grundtankerne ved CSP er at undgå deling af data. Dette er overordnet set efterlevet i implementationen med enkelte undtagelser, som dog i praksis er uproblematiske: Den primære undtagelse er delingen af Socket-objektet mellem hhv. RequestReaderog ResponseSender-processerne. Førstnævnte vil læse fra soklen, mens sidstnævnte vil skrive til den. I praksis har denne deling vist sig at være uproblematisk. I forbindelse med caching sendes det samme filindhold fra en FileFetcher til både ResponseSender og CachedFileSystem, for at undgå unødig overhead når indhold skal forbi CachedFileSystem. Denne deling af data er uproblematisk, da dataen kun læses og aldrig modificeres. 4.4 CSP WebServer procesbeskrivelser Med udgangspunkt i implementationsdesignet fra figur 7 gennemgås i dette afsnit de enkelte processer, deres tilstande og protokoller. Der ses bort fra logbeskeder. Hver proces beskrives kort med funktionalitet, ind- og udgående kanaler samt et tilstandsdiagram. For hver begivenhed er der en pil til den tilstand, som begivenheden resulterer i. Ved hver pil er begivenheden angivet over linien og handlingen under linien. 4.4.1 Logger Denne proces skriver logbeskeder til filsystemet. Indgående kanaler: LogChannel. Udgående kanaler: ingen. Tilstandsdiagram: Se figur 8(a). 4.4.2 Connector Denne proces er en TCP-sokkelgenerator. Indgående kanaler: ingen. Udgående kanaler: SocketChannel. Tilstandsdiagram: Se figur 8(b). 4.4.3 ResponseSender Denne proces sender svar tilbage over en sokkel. Indgående kanaler: SocketChannel, ResponseChannel og CountChannel. Udgående kanaler: InputStreamChannel. Tilstandsdiagram: Se figur 9. 15

(a) Tilstandsdiagram for Logger (b) Tilstandsdiagram for Connector Figur 8: Tilstandsdiagrammer Figur 9: Tilstandsdiagram for ResponseSender 16

4.4.4 RequestReader Denne proces læser forespørgsler fra en sokkel. Indgående kanaler: InputStreamChannel. Udgående kanaler: RequestChannel, CountChannel og ResponseChannel. Tilstandsdiagram: Se figur 10. Figur 10: Tilstandsdiagram for RequestReader 4.4.5 RequestMultiplexer Denne proces afgør hvilken RequestHandler, der skal behandle en given forespørgsel. Indgående kanaler: RequestChannel. Udgående kanaler: n FileRequestChannel er og m ExecutionRequestChannel er. Tilstandsdiagram: Se figur 11. 4.4.6 FileCache Denne proces cacher ressourcer. Indgående kanaler: FileRequestChannel og FileContentChannel. Udgående kanaler: InternFileRequestChannel og ResponseChannel. Tilstandsdiagram: Se figur 12. 17

Figur 11: Tilstandsdiagram for RequestMultiplexer Figur 12: Tilstandsdiagram for FileCache 18

4.4.7 FileFetcher Denne proces henter ressourcer fra filsystemet. Indgående kanaler: InternFileRequestChannel. Udgående kanaler: FileContentChannel og ResponseChannel. Tilstandsdiagram: Se figur 13. Figur 13: Tilstandsdiagram for FileFetcher 4.4.8 Executer Denne proces afvikler programmer. Indgående kanaler: ExecutionRequestChannel. Udgående kanaler: ResponseChannel. Tilstandsdiagram: Se figur 14. 19

Figur 14: Tilstandsdiagram for Executer 20

Proces Bilag Resultat Logger C.1 Connector C.2 ResponseSender C.3 RequestReader C.4 RequestMultiplexer C.5 FileCache C.6 FileFetcher C.7 Executer C.8 Tabel 1: Opsummering over afprøvning af de enkelte processer i CSP WebServer 4.5 Brugervejledning Dette afsnit er en kort vejledning til anvendelse af CSP WebServeren. Det antages af læseren er bekendt med afvikling af Java-programmer. WebServer startes fra kommandolinien og tager følgende argumenter: WebServer -p <port number> -d <directory> [-c <number>] [-t <number>] [-f <number>] [-l <number>] -p Angiver hvilken port serveren skal lytte på. -d Angiver serverens rod-bibliotek. -c Angiver det maksimale antal af samtidige forbindelser til serveren. -t Angiver hvor mange caches der skal anvendes. -f Angiver hvor mange arbejdere hver cache har til rådighed. -l Bestemmer hvor udførlig loggen skal være. 0 er laveste indstilling (ingen beskeder) mens 5 er højeste (alt logges). 4.6 Afprøvning I dette afsnit afprøves implementationen af de enkelte CSP-processer for at fastslå om de opfører sig som forventet. For hver proces har vi opstillet et CSP-netværk, der tester de mulige begivenheder, handlinger og tilstande, der er angivet i tilstandsdiagrammet for den givne proces, se afsnit 4.4. En beskrivelse af hver test er givet i de følgende afsnit. Hver test er implementeret i et separat program; programmerne er i afsnit C. For hver test udskrives om den er lykkedes eller fejlet. Afprøvningen er opsummeret i tabel 1. Som det kan ses i figuren fungerer implementationen som forventet. I forbindelse med evalueringen af CSP-WebServeren i næste afsnit, bliver hele procesnetværket black-box-testet, hvorfor en sådan ikke udføres separat. 21

4.6.1 Logger test Logger-processen har kun én tilstand og én hændelse med tilhørende handling: at modtage en logbesked, som skrives til en fil. Loggeren testes ved at lade en proces sende to beskeder til den, hvorefter det testes at loggen indeholder beskederne i korrekt rækkefølge. Testen kan findes i bilag C.1. Testen afvikledes korrekt. 4.6.2 Connector test Connector-processen har kun én tilstand og én hændelse med tilhørende handling: at modtage en TCP-forbindelse og sende den tilsvarende socket på en kanal. Connectoren testes ved at forbinde Connector-processen til en overvågningsproces, der udskriver en besked på stdout hver gang den modtager en socket. Dernæst bruges en browser til at oprette to TCP-forbindelser til Connectoren. Når overvågningsprocessen har modtaget to sockets, er testen afviklet korrekt. Testen kan findes i bilag C.2. Testen afvikledes korrekt. 4.6.3 ResponseSender test Alle tilstande og begivenheder for ResponseSender-processen testes ved den sekvens af beskedudvekslinger, der er beskrevet i tabel 2. Tabellen læses nemmest i sammenhæng med tilstandsdiagrammet i figur 9. Testen kan findes i bilag C.3. Testen afvikledes korrekt. 4.6.4 RequestReader test Alle tilstande og begivenheder for RequestReader-processen testes ved den sekvens af beskedudvekslinger, der er beskrevet i tabel 3. Tabellen læses nemmest i sammenhæng med tilstandsdiagrammet i figur 10. Testen kan findes i bilag C.4. Testen afvikledes korrekt. 4.6.5 RequestMultiplexer test RequestMultiplexer-processen testes ved at sende forespørgsler på de tre kendte ressourcetyper samt en ukendt. En overvågningsproces konstaterer om forespørgslerne sendes videre på den korrekte kanal. Testen kan findes i bilag C.5. Testen afvikledes korrekt. 4.6.6 FileCache test Alle tilstande og begivenheder for FileCache-processen testes ved den sekvens af beskedudvekslinger, der er beskrevet i tabel 4. Tabellen læses nemmest i sammenhæng med tilstandsdiagrammet i figur 12. Testen kan findes i bilag C.6. Testen afvikledes korrekt. 22

læses/skrives SocketChannel! Socket InputStreamChannel? InputStream ResponseChannel! Response [Response.getID() == 2] ResponseChannel! Response [Response.getID() == 1] CountChannel! 4 ResponseChannel! Response [Response.getID() == 4] ResponseChannel! Response [Response.getID() == 3] SocketChannel! Socket InputStreamChannel? InputStream ResponseChannel! Response [Response.getID() == 1] CountChannel! -1 SocketChannel! Socket kommentar en ny socket modtages i starttilstanden svaret kan endnu ikke sendes både dette og foregående svar sendes forbindelsen skal lukkes når det fjerde svar er sendt svaret kan endnu ikke sendes både dette og foregående svar sendes og forbindelsen lukkes ny socket svaret sendes forbindelsen er lukket af klienten ny socket tester at processen er tilbage i start-tilstanden Tabel 2: Sekvens af beskeder, der sendes til og modtages fra ResponseSender 4.6.7 FileFetcher test FileFetcher-processen testes ved at sende forespørgsler på henholdvis en ikke-eksisterende fil og en eksisterende fil. Testen kan findes i bilag C.7. Testen afvikledes korrekt. 4.6.8 Executer test Executer-processen testes ved at sende forespørgsler på henholdvis et ikke-eksisterende program og et eksisterende program. Testen kan findes i bilag C.8. Testen afvikledes korrekt. 23

læses/skrives InputStreamChannel! InputStream kommentar input-strømmen lukkes efter at den er afleveret CountChannel? -1 RequestReader signalerer at strømmen er lukket og vender tilbage til den initielle tilstand InputStreamChannel! InputStream ResponseChannel? Response RequestChannel? Request RequestChannel? Request CountChannel? 3 InputStreamChannel! InputStream der skrives en ugyldig HTTP- til input-strømmen efter den er afleveret RequestReaderen sender et svar om at beskeden var ugyldig. der skrives en gyldig HTTPforespørgsel til input-strømmen RequestReaderen sender HTTPforespørgslen videre der skrives en gyldig HTTPforespørgsel til input-strømmen med headeren Connection: close RequestReaderen sender HTTPforespørgslen videre samt signalerer at sidste besked er modtaget og at der var tre i alt en ny input-strøm tester at processen er tilbage i start-tilstanden Tabel 3: Sekvens af beskeder, der sendes til og modtages fra RequestReader 5 Evaluering I dette afsnit foretages en eksperimentel evaluering af CSP WebServeren. Som nævnt i afsnit 2.1 er de primære mål, at håndtere mange samtidige forbindelser og forespørgsler. Det undersøges, hvor lang tid webserveren er om at behandle 10.000 forespørgsler, med maksimalt antal samtidige forbindelser og forskellige indstillinger for caching. Vi tilstræber dermed at udnytte så meget af CSP WebServer procesnetværket som muligt. 5.1 Opstilling Det var intentionen at evaluere CSP WebServer på Ultra SPARC T1 en på MiG. Denne maskine var dog utilgængelig over en længere periode i det tidsrum vi havde planlagt at 24

læses/skrives FileRequestChannel! FileRequest InternFileRequestChannel? FileRequest ContentChannel! Content FileRequestChannel! FileRequest ResponseChannel? Response FileRequestChannel! FileRequest kommentar filen var ikke i cachen og forespørgslen sendes videre filens indhold leveres til cachen der forespørges efter samme fil filen var i cachen en ny forespørgsel tester at processen er tilbage i start-tilstanden Tabel 4: Sekvens af beskeder, der sendes til og modtages fra FileCache afvikle vores evaluering, hvorfor vi i stedet har anvendt to hjemmecomputere forbundet med et krydset netværkskabel. Den ene har afviklet CSP WebServeren og den anden har genereret forbindelser og forespørgsler, med Java-programmet RequestGeneratorMain der kan findes i bilag D.1. Følgende indstillinger for CSP WebServer blev afprøvet: Caching slået fra. 1 cache slået til. 5 caches slået til. 10 caches slået til. Ved omkring 200 samtidige forbindelser, oplevede vi på den benyttede testplatform fejlen "ConnectException: Connection refused", på trods af at CSP WebServeren havde frie SocketHandlers. CSP WebServeren har 622 CSP-processer, hvilket, som tidligere nævnt, er grundet problemer med JCSP jf. [2, p. 36]. Af denne årsag har vi kun evalueret op til 200 samtidige forbindelser. Designet burde efter vores mening dog kunne skalere til langt flere. Figur 15 viser den tid det har taget RequestGeneratorMain at få de 10.000 forespørgsler behandlet af CSP WebServer, ved forskellige antal samtidige forbindelser. Køretiden for de fire CSP WebServere følges ad; desto flere samtidige forbindelser der håndteres, desto længere tid tager det at behandle de 10.000 forespørgsler. CSP WebServerens maksimale gennemløb, falder nærmest lineært med antallet af samtidige forbindelser. Årsagen til dette skal findes i, at der for at håndterer flere forbindelser, skal benyttes flere SocketHandlers (bestående af to CSP-processer) og dertilhørende RequestMultiplexere, hvilket fører til flere kontekstskift. 25

Figur 15: Køretid ved 10.000 forespørgsler Figur 15 viser, ikke overraskende, at CSP WebServeren uden cache er betydeligt langsommere end CSP WebServerene med cache. De tre cachede webservere ligger rimelig tæt, men den hurtigste er den der kun har én cache (CachedFileSystem). Vi har ingen umiddelbar forklaring på denne opførsel, som strider mod vores antagelse af at dette ville kunne føre til en flaskehals. 6 Konklusion Givet projektbeskrivelsen i afsnit 2 har vi analyseret, designet og implementeret en webserver i JCSP, som understøtter en delmængde af HTTP/1.1-standarden. Implementationen er efterfølgende blevet afprøvet og evalueret ud fra metrikerne antal forbindelser og antal forespørgsler. I forbindelse med realiseringen af CSP-designet, har det været relevant at sammenligne ydelsen på flere One2Any-kanaler kontra en enkelt Any2Any-kanal. Det blev her fundet at brugen af One2Any-kanaler gav en faktor 9 bedre ydelse over Any2Any-kanalen på det Ultra SPARC T1 system, der er stillet rådighed ifm. kurset. Evalueringen viser at CSP WebServer skalerer som forventet. Dog opleves et lille overhead, og dermed tab af ydelse, når der tilføjes flere processer (primært SocketHandlers). Det er derudover blevet konstateret, at med det valgte CSP-design bliver JCSP en begrænsende faktor i sig selv ved mere end 200 samtidige forbindelser. På trods af at Java ikke egner sig til en produktionswebserver, har det givet mulighed for at lave et projekt af en vis størrelse. Set i lyset af sikkerhedsproblemer i mange 26

webserverimplementationer, mener vi der er et godt belæg for at bruge CSP som grundlag for mere sikre webservere. Ved valg af et implementationssprog, der ikke i sig selv er begrænsende for ydelsen, vil en CSP webserver give gode muligheder for at skalere dynamisk baseret på belastning. 6.1 Fremtidigt arbejde Overordnet set er det naturligvis påkrævet at webserveren har fuld understøttelse af HTTP/1.1 og CGI. Det er desuden åbenlyst at en kommerciel implementation ikke kan være tjent med de begrænsninger Java og JCSP giver. Vi mener at designet i sig selv er velegnet og åbner op for skalerbarhed, hvorfor en implementation i occam burde medføre en brugbar webserver. At webserveren ved opstart får angivet antal processer til de forskellige opgaver gør det svært at håndtere en skiftende belastning. Dynamisk oprettelse og nedlægning af processer ud fra den aktuelle belastning ville gøre webserveren mindre afhængig af forhåndsviden om indhold og brugsmønstre. I den forbindelse vil overvejelser omkring caching strategier også være nødvendige, herunder understøttelse af opdatering/fjernelse af cache-indgange ved ændringer i filerne på disken. 27

7 Litteratur [1] Fred Barnes. occwserv: An occam web-server. I J.F. Broenink og G.H. Hilderink, redaktører, Communicating Process Architectures 2003, bind 61 af Concurrent Systems Engineering Series, side 251-268, Amsterdam, The Netherlands, September 2003. IOS Press. [2] Neil Brown og Peter Welch. An Introduction to the Kent C++ CSP Library. http: //www.diku.dk/~vinter/xmp/lecture5c++csp.pdf. [3] University of Kent at Canterbury. Communicating Sequential Processes for Java (JCSP). http://www.cs.kent.ac.uk/projects/ofa/jcsp/. [4] R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach og T. Berners-Lee. RFC 2616: Hypertext Transfer Protocol HTTP/1.1. Internet Engineering Task Force, June 1999. http://www.ietf.org/rfc/rfc2616.txt. [5] Brian Vinter. Putting CSP into practice... JCSP. http://www.diku.dk/~vinter/ xmp/lecture4.pdf. [6] World Wide Web Consortium. CGI: Common Gateway Interface, October 1999. http: //www.w3.org/cgi/. 28

A Evaluering af Any2Any kontra multiple One2Any kanaler Dette bilag viser køretiderne for de to tests, som er beskrevet i afsnit 4.1. Testimplementationerne kan ses i de efterfølgende afsnit. De to tests er afviklet på to systemer: Ultra SPARC T1 kan på hardwareniveau afvikle 32 samtidige tråde Tid (sekunder) Afvikling nr. Any2Any Multiple One2Any 1 792,6 93,9 2 762,5 84,3 3 770,6 85,4 4 781,6 92,5 5 806,1 93,7 Gennemsnit: 782,7 90,0 Spredning: 17,4 4,7 AMD Athlon 64 kan på hardwareniveau afvikle én tråd af gangen A.1 Kildekode A.1.1 Any2AnyTest.mRSL Tid (sekunder) Afvikling nr. Any2Any Multiple One2Any 1 81,5 52,2 2 80,7 52,5 3 80,8 52,3 4 80,9 52,3 5 80,3 52,4 Gennemsnit: 80,8 52,3 Spredning: 0,5 0,1 : : EXECUTE: : echo Any2Any Test java cp commons c l i 1.0. j a r : j c s p c l a s s e s. j a r : p h w c l a s s e s. j a r : cspwebserver. j a r dk. diku. csp. webserver. t e s t. Any2AnyTest echo 29

echo M u l t i p l e One2Any Test java cp commons c l i 1.0. j a r : j c s p c l a s s e s. j a r : p h w c l a s s e s. j a r : cspwebserver. j a r dk. diku. csp. webserver. t e s t. MultipleOne2AnyTest : : NOTIFY : : espen@ hojsgaard. dk : : INPUTFILES : : commons c l i 1.0. j a r j c s p c l a s s e s. j a r p h w c l a s s e s. j a r cspwebserver. j a r : : ARCHITECTURE : : SPARC T1 : : CPUTIME : : 701 A.1.2 Any2AnyTest.java package dk. diku. csp. webserver. t e s t ; import j c s p. lang. Any2AnyChannelInt ; import j c s p. lang. CSProcess ; import j c s p. lang. ChannelInputInt ; import j c s p. lang. ChannelOutputInt ; import j c s p. lang. P a r a l l e l ; public class Any2AnyTest { f i n a l s t a t i c int MAX = 1000000; f i n a l s t a t i c int WORKERS = 1 0 0 ; f i n a l s t a t i c int MASTERS = 1 0 ; s t a t i c I n t e g e r m a s t e r s _ f i n i s h e d = 0 ; s t a t i c long time ; public s t a t i c void main ( S t r i n g [ ] a r g s ) { Any2AnyChannelInt master_to_worker_channel = new Any2AnyChannelInt ( ) ; P a r a l l e l p r o c e s s e s = new P a r a l l e l ( ) ; for ( int i = 0 ; i < MASTERS; i ++) { p r o c e s s e s. addprocess (new Master ( master_to_worker_channel ) ) ; for ( int i = 0 ; i < WORKERS; i ++) { p r o c e s s e s. addprocess (new Worker ( master_to_worker_channel ) ) ; time = System. c u r r e n t T i m e M i l l i s ( ) ; p r o c e s s e s. run ( ) ; s t a t i c class Master implements CSProcess { f i n a l ChannelOutputInt channel_out ; public Master ( ChannelOutputInt channel_out ) { this. channel_out = channel_out ; 30

int i = 0 ; while ( i < MAX) { channel_out. w r i t e ( i ++); synchronized ( m a s t e r s _ f i n i s h e d ) { i f (++m a s t e r s _ f i n i s h e d == MASTERS) { time = System. c u r r e n t T i m e M i l l i s ( ) time ; System. out. p r i n t l n ( " M i l l i s e c o n d s e l a p s e d : " + time + " ( " + time / 1000 + " seconds ) " ) ; System. e x i t ( 0 ) ; return ; s t a t i c class Worker implements CSProcess { A.1.3 f i n a l ChannelInputInt channel_in ; public Worker ( ChannelInputInt channel_in ) { this. channel_in = channel_in ; while ( true ) { channel_in. read ( ) ; MultipleOne2AnyTest.java package dk. diku. csp. webserver. t e s t ; import j c s p. lang. CSProcess ; import j c s p. lang. ChannelInputInt ; import j c s p. lang. ChannelOutputInt ; import j c s p. lang. One2AnyChannelInt ; import j c s p. lang. P a r a l l e l ; public class MultipleOne2AnyTest { f i n a l s t a t i c int MAX = 1000000; f i n a l s t a t i c int WORKERS_PER_MASTER = 1 0 ; f i n a l s t a t i c int MASTERS = 1 0 ; s t a t i c I n t e g e r m a s t e r s _ f i n i s h e d = 0 ; s t a t i c long time ; public s t a t i c void main ( S t r i n g [ ] a r g s ) { P a r a l l e l p r o c e s s e s = new P a r a l l e l ( ) ; for ( int i = 0 ; i < MASTERS; i ++) { One2AnyChannelInt master_worker_channel = new One2AnyChannelInt ( ) ; 31

for ( int q = 0 ; q < WORKERS_PER_MASTER; q++) { p r o c e s s e s. addprocess (new Worker ( master_worker_channel ) ) ; p r o c e s s e s. addprocess (new Master ( master_worker_channel ) ) ; time = System. c u r r e n t T i m e M i l l i s ( ) ; p r o c e s s e s. run ( ) ; return ; s t a t i c class Master implements CSProcess { f i n a l ChannelOutputInt channel_out ; public Master ( ChannelOutputInt channel_out ) { this. channel_out = channel_out ; int i = 0 ; while ( i < MAX) { channel_out. w r i t e ( i ++); synchronized ( m a s t e r s _ f i n i s h e d ) { i f (++m a s t e r s _ f i n i s h e d == MASTERS) { time = System. c u r r e n t T i m e M i l l i s ( ) time ; System. out. p r i n t l n ( " M i l l i s e c o n d s e l a p s e d : " + time + " ( " + time / 1000 + " seconds ) " ) ; System. e x i t ( 0 ) ; return ; s t a t i c class Worker implements CSProcess { f i n a l ChannelInputInt channel_in ; public Worker ( ChannelInputInt channel_in ) { this. channel_in = channel_in ; while ( true ) { channel_in. read ( ) ; 32

33 B Kildekode, CSP WebServer B.1 CachedFileSystem.java package dk. diku. csp. w e b s e r v e r ; import j c s p. l a n g. A l t i n g C h a n n e l I n p u t ; import j c sp. lang. Any2OneChannel ; import j c s p. l a n g. CSProcess ; import j c s p. l a n g. ChannelOutput ; import j c sp. lang. One2AnyChannel ; import j c s p. l a n g. P a r a l l e l ; Process network handling f i l e system access and caching. public c l a s s CachedFileSystem implements CSProcess { private f i nal AltingChannelInput file_ request_ channel_ in ; private f i nal ChannelOutput log_channel_out ; private f i nal String root_dir ; private f i nal int file_ fetcher_ count ; private f i nal boolean enable_cache ; @param root_dir The server s root directory ( i. e. where "/" refers to ) @param f i l e _ f e t c h e r _ c o u n t The number of f i l e s that can be fetched from disk s i m u l t a n e u s l y @param enable_cache Whether to cache f i l e s or not @param file_request_channel_in The channel to receive f i l e requests on @param log_channel_out The channel to send l o g events to public CachedFileSystem ( String root_dir, int file_ fetcher_ count, boolean enable_cache, AltingChannelInput file_request_channel_in, ChannelOutput log_channel_out ) { this. root_dir = root_dir ; this. file_ fetcher_ count = file_ fetcher_ count ; this. enable_cache = enable_cache ; this. file_ request_ channel_ in = file_ request_ channel_ in ; this. log_channel_out = log_channel_out ; Any2OneChannel file_ content_ channel = new Any2OneChannel ( ) ; One2AnyChannel i n t e r n _ f i l e _ r e q u e s t _ c h a n n e l = new One2AnyChannel ( ) ; P a r a l l e l p r o c e s s e s = new P a r a l l e l ( ) ; f o r ( int i = 0 ; i < file_ fetcher_ count ; i++) { p r o c e s s e s. a d d P r o c e s s (new F i l e F e t c h e r ( root_dir, intern_ file_ request_ channel, file_content_channel, log_channel_out ) ) ; p r o c e s s e s. a d d P r o c e s s (new F i l e C a c h e ( enable_cache, file_request_channel_in, file_content_channel, intern_ file_ request_ channel, log_channel_out ) ) ; p r o c e s s e s. run ( ) ; B.2 Connector.java package dk. diku. csp. w e b s e r v e r ; import java. i o. IOException ; import java. net. ServerSocket ; import j a v a. net. S o c k e t ; import j c s p. l a n g. CSProcess ; import j c s p. l a n g. ChannelOutput ; A process which accepts connections on a given port and passes the corresponding s o c k e t s on v i a a channel. public c l a s s Connector implements CSProcess { private ChannelOutput socket_channel_out ; private ChannelOutput log_channel_out ; private int listen_ port ; private int timeout ; @param l i s t e n _ p o r t The port to l i s t e n on @param timeout The SO_TIMEOUT on the created s o c k e t s ( see { @link Socket#setSoTimeout ( i n t ) ) @param socket_channel_out The channel to send s o c k e t s on @param log_channel_out The channel to send l o g events to public Connector ( int listen_ port, int timeout, ChannelOutput socket_channel_out, ChannelOutput log_channel_out ) { this. listen_ port = listen_ port ; this. timeout = timeout ; this. socket_channel_out = socket_channel_out ; this. log_channel_out = log_channel_out ; S e r v e r S o c k e t s e r v e r = new S e r v e r S o c k e t ( l i s t e n _ p o r t ) ;