Szukałem w Internecie programu do tworzenia diagramów (ładnych i prosto, a nie takich jak np. w Impress) - znalazłem ciekawą aplikację internetową: http://yuml.me

W międzyczasie myślałem o obsłudze sesji i zmianie jej ID - w sytujacji, gdy wykonujemy asynchroniczne (a szczególnie liczne) zapytania do serwera HTTP nie jest to dobry pomysł. Dlaczego? Ogólnie o tym na poniższych diagramach. Szczegółowo może w przyszłym artykule.

Przykłady diagramów

Standardowe żądanie i przepływ danych w skrypcie PHP

Standardowo wszystko wykonuje się szeregowo. Nie ma więc miejsca na jakiś brak synchronizacji.

Kod:

(start)->(user clicks)
(user clicks)->(request)
(request)->(send sess id)
(send sess id)->(start session)
(start session)->(regenerate id)
(regenerate id)->(send back new sess id)
(send back new sess id)->(continue app)
(continue app)->(respond)
(respond)->(end)

Diagram:

http://yuml.me/4f2106d4
http://yuml.me/4f2106d4

Problem przy zapytaniach asynchronicznych

W przypadku zapytań asynchronicznych możemy natrafić na sytuację, gdy SESSION ID zmieni się na serwerze, ale nie zdąży się zaktualizować na kliencie - czego wynikiem będzie wysłanie żądania w ramach nieistniejącej sesji.

Kod:

(start)->(user clicks)
(user clicks)->|z|
|z|->(request A)
(request A)->(send sess id A - 1)
(send sess id A - 1)->(start session with A - 1)
(start session with A - 1)->(regenerate id)
(regenerate id)->|a|
|a|->|b|
|b|->(send back new sess id B)
(send back new sess id B)->(end)
|z|->(user reads page)
(user reads page)->(user clicks again)
(user clicks again)->(request B)
(request B)->(send sess id A - 2)
(send sess id A - 2)->|a|
|a|->(start session with A - 2 - no session!)
(start session with A - 2 - no session!)->|b|
|b|->(regenerate id again)
(regenerate id again)->(send back new sess id C)
(send back new sess id C)->(end)

Diagram:

http://yuml.me/213615ad
http://yuml.me/213615ad

Inny przykład na desynchronizację

Oto co może dziać się po stronie serwera i klienta.

Kod:

(start)->(1:request, id=A)
(1:request, id=A)->(2:request, id=A)
(2:request, id=A)->(1:start session, id=A)
(1:start session, id=A)->(1:regenrate id, new id=B)
1:regenrate id, new id=B)->(2:start session, id=A)
(2:start session, id=A)->(1:do sthing)
(1:do sthing)->(2:regenrate id, new id=B)
2:regenrate id, new id=C)->(2:send id back, id=C)
(2:send id back, id=C)->(client: gets new id=C)
(client: gets new id=C)->(1:send id back, id=B)
(1:send id back, id=B)->(client: gets new id=B)
(client: gets new id=B)->(2:do sthing with no session)
(2:do sthing with no session)->(client: do sth with bad id, id=B, id on server=C)
(client: do sth with bad id, id=B, id on server=C)->(end)