Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

PHP en Websocket implementatie

Pagina: 1
Acties:

  • Fraekje
  • Registratie: April 2004
  • Laatst online: 19-08-2024
Beste Tweakers,

Ik ben werkzaam als developer en tevens student informatica. Ik heb een vraag over de beste implementatie voor een use-case. Ikzelf heb daarbij al enkele dingen geprobeerd maar ik vraag me af of dit daadwerkelijk the-way-to-go is.

UseCase:
Het bestaande programma is volledig geschreven in PHP met het framework Yii. Het programma verzamelt gegevens m.b.v. een API en schrijft deze weg in zijn database. Het idee is om het schaalbaar te maken door meerdere servers bij te kunnen plaatsen om het verzamelen van gegevens op te splitsen. Vervolgens wordt deze opgeslagen data weggeschreven naar een zogenaamde master-server omgeving. Via een simple round-robin wordt een server ip/adres gegeven van waaruit de API moet worden benaderd. Deze moet de gegevens dan afhandelen waarna later de gegevens worden weggeschreven naar de master omgeving. Het idee is dus dat de master server alleen gegevens gaat verwerken en opslaan en de ''tussen''-servers de gegevens verzamelen en alles wat daarbij komt kijken. De moeilijkheid zit hem in dat er ook gegevens moeten worden gecontroleerd bij de master server om te voorkomen dat er duplicaten ontstaan; Data verstrekt door de API moet altijd per tijdsperiode uniek zijn en niet uitgegeven aan een ander via een andere tussen-server.

Situatieschets:
Browser <--> n-Aantal Tussen-servers <--> Master-Server

Mijn gedachten:... :?
Omdat het huidige systeem volledig in PHP is geschreven ben ik eerst naar REST/SOAP gaan kijken en/of directe database verbindingen. Mijn (weinige) ervaring is echter dat REST niet de meest snelle manier is om servers met elkaar te laten praten. Het mag absoluut NIET voorkomen dat 2 verschillende tussen servers eenzelfde gegevens uitdelen d.m.v. de API. Dit zou met controles verholpen kunnen worden maar idealiter worden er zo min mogelijk controles gedaan en moeten servers zelf al kunnen bepalen of iets kan of niet.
Ik ben daarom gaan kijken naar websockets omdat deze ''instant'' zijn (niets is instant maar als iets in de buurt komt?)

Websockets
PHP en websockets, het kan 8)7 maar in plaats van PHP ben ik voor Java gegaan (simpelweg omdat deze taal mij het meest bekend is en er zo snel een proof of concept kon worden gemaakt). Het punt is dat wanneer je de communicatie volledig over websockets wilt laten gaan, je tussen-server voor zowel Client als Server moet laten spelen. Client: om met de Master-Websocket server te connecten en Server om het PHP gedeelte ermee te laten connecten. Vervolgens heb ik een soort 'facade/queue'-thread gebouwd die wordt geïnterrupt van een sleep wanneer er een nieuwe opdracht door de server vanuit het PHP gedeelte doorkomt. Deze voert hij uit / sync hij met master. Zodra er data door de tussen-server is uitgedeeld wordt direct naar alle andere online tussen-servers gestuurd dat deze data tot tijdsbestek X bezet is en er wat anders moet worden verstuurd.

Lang verhaal kort;
Wat is een algemeen aanvaarde techniek om een programma op te splitsen voor loadbalancing (want dat is het eigenlijk) maar data wel correct te houden. Mijn vraag is eigenlijk; zijn websockets hier wel voor bedoeld? Of ben ik nu iets leuks aan het maken wat wel werkt maar eigenlijk niet werkbaar is / om aan te zien. Is REST voor dit scenario wel de way-to-go? Of is er iets wat ik over het hoofd heb gezien?

Bedankt voor het lezen van deze muur van tekst, vraag gerust als er iets niet duidelijk is.

Verwijderd

Ik begrijp niet echt helemaal wat je dus probeert te zeggen. Maar als ik het goed begrijp wil je dus ook je aparte server om mee via websockets te connecten mee kunnen scalen?

Ik ben toevallig ook op dit moment bezig met een soort gelijke case. Maar dan met .NET SignalR. Wat dan vanuit Microsoft een geadviseerde manier is is om je connecties via een service bus te laten connecten. Op die manier heb je alle connecties via een centrale service en kun je via meerdere servers deze connecties aanspreken. Overigens hebben we geen aparte server voor SignalR, dit gaat gewoon via de frontendservers.

Verwijderd

Ik zou hiervoor gewoon een bestaande loadbalancer oplossing voor gebruiken, en in je frontend een sessie opzetten met een backend server. De loadbalancers configureer je vervolgens zo dat die iets snappen van die sessies (sticky sessions) zodat requests bij voorkeur op dezelfde backend uitkomen.

  • Douweegbertje
  • Registratie: Mei 2008
  • Laatst online: 30-10 12:53

Douweegbertje

Wat kinderachtig.. godverdomme

Om heel eerlijk te zijn snap ik je verhaal maar half. In ieder geval snap ik je redenatie over websockets niet helemaal. Het 'enige' voordeel van websockets t.o.v. wat andere dingen is dat je data ook visa-versa kan versturen. client <- -> server verhaal dus.

Als ik je verhaal probeer te snappen, ga ik er eigenlijk vanuit dat je situatieschets dan dit is:

Browser <--> Master-Server <--> n-Aantal Tussen-servers


Mja wat je in elk geval niet moet doen is zelf het wiel opnieuw uitvinden. Er zijn talloze opties om loadbalacing te implementeren. Wat je niet moet gaan doen is één of andere select uitvoeren en deze weer inserten in één van je andere servers.

Om goed antwoord te geven is er eerder de vraag; wat wil je 'loadbalancen'. De requests door eventuele gebruikers of de snelheid van het verkrijgen van informatie van je API?

In het eerste geval zorg je er gewoon voor dat je een master hebt waar je alleen writes op uitvoert, en deze naar de slaves uitrolt. De users doen dan gewoon round robin of w/e reads op de slaves.

In het tweede geval moet je iets gaan vinden zodat je data wel eens uniek is. Dit kan op zich prima met elke vorm van een API (rest of w/e). Dump je data van de slave servers naar de master. Bij binnenkomst checked de master 'gewoon' de data en zet deze erin. Even terug sturen dat hij het ontvangen heeft en geef een nieuwe opdracht als response oid.

In elk geval moet je proberen om bestaande oplossingen te gebruiken en niet door een soort van 'frontend' oplossing een loadbalancer te gaan maken. Er zijn zat manieren om te balancen, of dit nu voor MySQL, MSSQL of PHP is.

  • johnkeates
  • Registratie: Februari 2008
  • Laatst online: 04-07 16:30
Volgens mij snap je niet wat distributie is... load balancers zijn eigenlijk 'statische' ADC's, die hebben vrij weinig met deze case te maken. WebSockets hebben ook niks met dit verhaal te maken.

Wat je wil hebben is een service bus of op z'n minst een queue. Als je gaat schalen en je hebt een PHP applicatie is het eerste wat je gaat doen het moeilijke denkwerk uit je PHP frontend slopen. Dus zo'n beetje alle requests 1-op-1 in een queue dumpen. Bijvoorbeeld ActiveMQ of RabbitMQ of als je een worker queue wil iets als Gearman of Beanstalkd. Hell, je zou zelfs Redis kunnen gebruiken.

Daarna ga je kijken welke dingen synchroon moeten en welke asynchroon mogen. Dingen die synchroon moeten gaan connecties vreten, dus die dump je het liefste op een bak die veel connecties en weinig transfers doet. Dingen die asynchroon mogen kan je gewoon op je frontend laten staan, die krijgt dan allen nog maar met hele korte sessies te maken. Dan kan je polling gebruiken als je wil weten of je je antwoord voor de web client al hebt, of als je een API gebruikt, dan kan je zelfs gewoon wachten tot de consumer zin heeft om wat op te halen.

Voor dat je verder gaat is het natuurlijk relevant om te weten wat je setup nu is. Een stuk software voor internet maken is heel wat meer dan wat scripties in een mapje dumpen en hopen dat je code op internet hetzelfde werkt als je eigen omgeving. Je hebt waarschijnlijk al een reverse proxy zodat je frontend farms kan maken en asynchrone en synchrone requests naar verschillende servers kan doorsluizen, en als je echt hele drukke services hebt round-robin DNS en misschien wel DNS die geolocated DC's aanwijst.

Verder kan je natuurlijk ook altijd nog een gateway server gebruiken die een API moet gebruiken om z'n doelserver te vinden. Dan maakt ie eerst een request naar de gateway om te vragen of ie mag verbinden en zo ja met welke server, en daarna een nieuwe verbinding naar de juiste processing frontend.

Het kernwoord waar je naar opzoek bent is horizontaal schalen.

Edit: en niks van dit geheel gaat wat uitmaken als je applicatie niet ACID of op z'n minst atomic met z'n data manipulatie om kan gaan. Misschien handig om eerst te kijken of wat je wil überhaupt mogelijk is.

[ Voor 4% gewijzigd door johnkeates op 27-10-2014 01:28 ]


  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Is het niet handiger om dit op DB level te doen met een MySQL cluster zoals: Fabric of Galera?

[ Voor 14% gewijzigd door DJMaze op 27-10-2014 10:36 ]

Maak je niet druk, dat doet de compressor maar


  • Fraekje
  • Registratie: April 2004
  • Laatst online: 19-08-2024
Bedankt voor alle reacties,

mijn hele verhaal blijkt niet duidelijk dus een nieuwe poging.

Momenteel is er sprake van één webserver waarop de PHP applicatie draait met nog één database server. Omdat de requests naar de applicatie zoveel zijn willen we de applicatie in stukken hakken. Ook de werkbaarheid van de applicatie moet dit verbeteren. Daar waar nu zowel de API, Rekenwerk en Backend met statistieken samen zijn wordt opgedeeld. Het gaat voornamelijk over het gedeelte wat de API en het 'rekenwerk´ bevat.

Met een round-robin wordt een willekeurig IP gegeven waarvandaan de API moet worden geladen. Deze server bevat net als de andere servers de mogelijkheid om het rekenwerk te doen.
We kiezen ervoor om met een loadbalancer vanuit de browser te werken en geen echte loadbalancer omdat we geen single point of failure willen. Data wordt daarom door de tussenservers en master server(s) gesynced wanneer deze up zijn. Als een tussenserver plat is kan hij een andere tussenserver aanspreken. En als een master-server plat is dan houdt de tussenserver zijn gegevens langer vast.
Verwijderd schreef op zondag 26 oktober 2014 @ 12:15:
Ik begrijp niet echt helemaal wat je dus probeert te zeggen. Maar als ik het goed begrijp wil je dus ook je aparte server om mee via websockets te connecten mee kunnen scalen?
Omdat de API geschreven is met PHP kan je niet fatsoenlijk werken met bijvoorbeeld een websocket. Waarom wil ik persee een websocket? Omdat ik bij verandering direct alle andere servers op de hoogte wil brengen dat dit stuk data nu in gebruik is. Servers zijn dus onderling met elkaar verbonden met websockets zodat ze van elkaars bestaan weten. I.p.v. een groot spinnenweb wil ik dit gaan doen via de master-server die in contact staat met alle bestaande tussen-servers.

Daarom wil op op de tussenserver buiten het stuk PHP applicatie wat de API etc doet ook een Java webservice hebben. Deze Java webservice maakt het mogelijk om fatsoenlijk een websocket server & client te maken waarmee de Master-Server en de API (php) kunnen praten. Zo kan de API een aanvraag voor data doen aan de websocket, deze geeft asynchroon antwoord waardoor er veel requests doorheen kunnen worden gepompt was mijn idee.
Douweegbertje schreef op maandag 27 oktober 2014 @ 01:15:
Om goed antwoord te geven is er eerder de vraag; wat wil je 'loadbalancen'. De requests door eventuele gebruikers of de snelheid van het verkrijgen van informatie van je API?
Ik weet dus niet helemaal of dit over load-balancing gaat of over een juiste manier van het programma opslitsen. We willen in ieder geval dit tussen-stuk zo maken dat tijdens drukke periodes/piek momenten er nieuwe servers met identieke stukken software kunnen worden opgestart waarna ze zich aanmelden bij de master-server (in het 'web'' dus) en ze kunnen meehelpen met de data distributie via de API.

Mocht er ergens een gedeelte uitvallen dan moet de rest van de applicatie kunnen doorgaan/zijn data kunnen bewaren voor later. Een 'echte' loadbalancer geeft een single point of failure? 8)7

  • Joolee
  • Registratie: Juni 2005
  • Niet online
Fraekje schreef op maandag 27 oktober 2014 @ 10:53:
Bedankt voor alle reacties,

mijn hele verhaal blijkt niet duidelijk dus een nieuwe poging.


[...]
Je bent nu vanuit oplossingen je probleem aan het beschrijven. Ik denk dat het handiger is om eerst je probleem eens duidelijk te maken. Die schemert er in je verhaal zo hier en daar wel doorheen maar is niet echt duidelijk.

Je hebt een zooi clients welke data ophalen bij een webservice. Deze data moet veranderd kunnen worden. (Door wie?) Je hebt het ergens over locking bij het veranderen van data en in je TS staat ook nog "Data verstrekt door de API moet altijd per tijdsperiode uniek zijn en niet uitgegeven aan een ander via een andere tussen-server." Volgens mij is dat laatste de kern van je hele verhaal maar ik haal er niet echt uit wat je nou precies probeert te doen.

[ Voor 61% gewijzigd door Joolee op 27-10-2014 13:43 ]


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Fraekje schreef op maandag 27 oktober 2014 @ 10:53:
Met een round-robin wordt een willekeurig IP gegeven waarvandaan de API moet worden geladen. Deze server bevat net als de andere servers de mogelijkheid om het rekenwerk te doen.
We kiezen ervoor om met een loadbalancer vanuit de browser te werken en geen echte loadbalancer omdat we geen single point of failure willen. Data wordt daarom door de tussenservers en master server(s) gesynced wanneer deze up zijn. Als een tussenserver plat is kan hij een andere tussenserver aanspreken. En als een master-server plat is dan houdt de tussenserver zijn gegevens langer vast.

[...]

Waarom wil ik persee een websocket? Omdat ik bij verandering direct alle andere servers op de hoogte wil brengen dat dit stuk data nu in gebruik is.
Je moet hier goed nadenken over wat je wil:
- wil je een spof eruit werken / redundancy hebben dan moet je bijna wel met latency gaan werken (en oplossingen verzinnen voor wat er moet gebeuren als iets te oude data bevat)
- Wil je direct alle andere servers op de hoogte stellen en is dus elke uitval catastrofaal (want niet alle servers kunnen op de hoogte gesteld worden)

Je kan ze niet combineren.

In principe voor wat jij wil zou ik gewoon een message queue ertussen gooien in de trant van rabbitmq / redis oid en zelf helemaal niet met websockets gaan zitten pielen (laat dat lekker aan rabbitmq / redis over), die hebben een redelijke verdeling over deze 2 onderdelen maar begrijp goed dat het niet 100% allebei is.

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Zo te lezen zit jij vast in het idee dat er maar 1 master is.

Heb jij je wel verdiept in mijn reactie?
Zo niet, dan moet je echt even hier lezen: http://galeracluster.com/

Maak je niet druk, dat doet de compressor maar


  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 21-11 15:31

TheNephilim

Wtfuzzle

Voor zover ik kan opmaken uit je verhaal; ben je op zoek naar een master slave constructie in SQL.

Je master server ontvangt alle schrijfacties en mutaties, de slaves luisteren en fungeren eigenlijk als kopie. Op deze manier kun je lezen vanaf je slaves doen en zo load op de master minimaliseren.

In php kun je heel simpel, zonder loadbalancer oid, al willekeurig één van de slaves aanspreken. Niet zo netjes als round-robin of load-based loadbalancing, maar wel makkelijk.

Tjah, wat je verder met websockets zou willen doen, ik heb geen idee. Misschien zou je dan toch kort(er) moeten omschrijven wat de structuur van je applicatie is. Client vraagt x... server vraagt y om gegevens en geeft client antwoord. Ofzo xd

  • Fraekje
  • Registratie: April 2004
  • Laatst online: 19-08-2024
DJMaze schreef op maandag 27 oktober 2014 @ 16:02:
Zo te lezen zit jij vast in het idee dat er maar 1 master is.

Heb jij je wel verdiept in mijn reactie?
Zo niet, dan moet je echt even hier lezen: http://galeracluster.com/
Het is niet dat het programma moet worden geloadbalanced maar hij moet in stukken gehakt worden zodat dat delen van het programma onafhankelijk van elkaar kunnen worden geupdate/vervangen. Dit is niet alleen een database-ding.
TheNephilim schreef op maandag 27 oktober 2014 @ 16:13:
Tjah, wat je verder met websockets zou willen doen, ik heb geen idee. Misschien zou je dan toch kort(er) moeten omschrijven wat de structuur van je applicatie is. Client vraagt x... server vraagt y om gegevens en geeft client antwoord. Ofzo xd
Soort van sequence diagram:
Iemand bezoekt pagina -> Persoon wordt geregistreerd en genoteerd via de API op de tussenserver -> Tussenserver selecteert data voor de persoon -> Verifeert dit met de master-server -> Master server zegt, ja prima ok is uniek en brengt andere tussenservers op de hoogte (websockets) dat dit stuk data nu is gereserveerd -> Tussenserver heeft een OK gekregen dus stuurt terug naar de pagina -> Data wordt getoond.

Het idee is dus dat tussenservers zelf kunnen nadenken over welke data de bezoeker van de site te zien krijgt en de master server alleen een ja of nee hoeft te geven.

Overigens; de master server is niet één enkele server maar werkt met slaves etc maar het gaat nu puur om het gedeelte ertussen. Is om dit ''tussenserver'' idee met de hier beschreven sequence een websocket een juiste implementatie? Of ben ik gewoon beter af met direct vanuit PHP de databases aanspreken en deze dus te laten loadbalancen m.b.v. slaves en alle andere truukjes op de markt -> Het hele websocket idee weglaten?

  • Joolee
  • Registratie: Juni 2005
  • Niet online
Fraekje schreef op maandag 27 oktober 2014 @ 17:30:
[...]


Het is niet dat het programma moet worden geloadbalanced maar hij moet in stukken gehakt worden zodat dat delen van het programma onafhankelijk van elkaar kunnen worden geupdate/vervangen. Dit is niet alleen een database-ding.


[...]


Soort van sequence diagram:
Iemand bezoekt pagina -> Persoon wordt geregistreerd en genoteerd via de API op de tussenserver -> Tussenserver selecteert data voor de persoon -> Verifeert dit met de master-server -> Master server zegt, ja prima ok is uniek en brengt andere tussenservers op de hoogte (websockets) dat dit stuk data nu is gereserveerd -> Tussenserver heeft een OK gekregen dus stuurt terug naar de pagina -> Data wordt getoond.

Het idee is dus dat tussenservers zelf kunnen nadenken over welke data de bezoeker van de site te zien krijgt en de master server alleen een ja of nee hoeft te geven.

Overigens; de master server is niet één enkele server maar werkt met slaves etc maar het gaat nu puur om het gedeelte ertussen. Is om dit ''tussenserver'' idee met de hier beschreven sequence een websocket een juiste implementatie? Of ben ik gewoon beter af met direct vanuit PHP de databases aanspreken en deze dus te laten loadbalancen m.b.v. slaves en alle andere truukjes op de markt -> Het hele websocket idee weglaten?
Op welke basis bepaalt de master server dat de informatie correct is en op welke basis selecteert de tussenserver welke data er weergegeven kan worden?

  • Fraekje
  • Registratie: April 2004
  • Laatst online: 19-08-2024
Joolee schreef op dinsdag 28 oktober 2014 @ 08:29:
[...]

Op welke basis bepaalt de master server dat de informatie correct is en op welke basis selecteert de tussenserver welke data er weergegeven kan worden?
De master server kijkt alleen naar de tijd van laatste uitgave. De tussen-server doet complexe berekeningen om met een suggestie te komen voor de master server die alleen naar de tijd van uitgave kijkt.
Pagina: 1