Stateless e sessão para ambiente distribuído, como fica essa arquitetura?

Saudações amigos!!!

Referente a ambientes distribuídos e quanto a questão de programação, muito se fala sobre a utilização de stateless e stateful em ambiente corporativo tem-se adotado muito a utilização do stateful através de frameworks como jsf, gwt, wicket e outros… já na outra ponta estão as “startups” que tem aderido mais ao modelo stateless com frameworks como spring mvc, struts e outras linguagens hipistas que trazem esse conceito embutido em si.
Não querendo aqui discutir qual framework/linguagem é ou não, se jsf também pode ou não ser stateless, mas gostaria de tirar dúvida e discutir 2 itens:

1) O modelo stateless é realmente o mais indicado para distribuir o sistema entre “shards”,“cluster”,“grid”,“servidores”? e porque?
2) Se a utilização de sessão para salvar o estado do usuário destruir a possibilidade de distribuir o sistema entre servidores, então eu não deveria utilizar mais sessão? ou poderia serializar a sessão no banco para auxiliar no retorno do usuário ao site para momentos críticos como no caso de um “carrinho de compras”?

Resumindo, minha dúvida está em torno do uso da sessão em um ambiente stateless/distribuído…

Abraços!

[quote=tiagomac]Saudações amigos!!!

Referente a ambientes distribuídos e quanto a questão de programação, muito se fala sobre a utilização de stateless e stateful em ambiente corporativo tem-se adotado muito a utilização do stateful através de frameworks como jsf, gwt, wicket e outros… já na outra ponta estão as “startups” que tem aderido mais ao modelo stateless com frameworks como spring mvc, struts e outras linguagens hipistas que trazem esse conceito embutido em si.
Não querendo aqui discutir qual framework/linguagem é ou não, se jsf também pode ou não ser stateless, mas gostaria de tirar dúvida e discutir 2 itens:

1) O modelo stateless é realmente o mais indicado para distribuir o sistema entre “shards”,“cluster”,“grid”,“servidores”? e porque?
2) Se a utilização de sessão para salvar o estado do usuário destruir a possibilidade de distribuir o sistema entre servidores, então eu não deveria utilizar mais sessão? ou poderia serializar a sessão no banco para auxiliar no retorno do usuário ao site para momentos críticos como no caso de um “carrinho de compras”?

Resumindo, minha dúvida está em torno do uso da sessão em um ambiente stateless/distribuído…

Abraços![/quote]

Faça um exercício mental:

  1. Primeiro imagine um servidor com beans stateful (não interessa se são EJB’s, POJO’s gerenciados por JSF, whatever). Não há problema algum nesse ambiente.
  2. Visualize um ambiente com duas máquinas. Sticky sessions precisam ser configuradas para que as duas máquinas enxerguem a mesma sessão. A sessão precisa ser passada entre as máquinas para que não haja problemas (alguns sistemas também poderiam forçar o cliente a sempre enxergar a mesma máquina, mas isso seria um tiro no pé, já que perderia toda a noção de alta disponibilidade).
  3. Visualize um ambiente com mil máquinas. Estratégias mais avançadas precisam ser utilizadas para guardar a sessão num ambiente externo (por exemplo, um cluster memcached). A rede passa a ser muito onerada com o tráfego de dados.
  4. Visualize dois ou três datacenters, com mil máquinas cada… E ter sessões passa a ser impraticável.

Num ambiente stateless, não existe esse problema. Se você tem um carrinho de compras, por exemplo, esse carrinho pode ser passado sempre na requisição para o servidor. Claro, o tráfego de rede cliente/servidor ficaria um tanto pior, mas esse problema seria distribuído entre os clientes, de modo que os servidores não “abraçariam” a carga toda sozinhos. Só que, nesse ambiente, a escalabilidade dependeria apenas de colocar mais máquinas no cluster, tendendo a uma arquitetura conhecida como shared-nothing (na minha opinião, a melhor que existe).

Pra concluir… como você deve ter reparado pelo exercício mental, depende bastante do número de usuários que você possuir, mas em linhas gerais, sem estado é melhor do que com estado.

[]'s

P.S: Um adendo: cluster é uma coisa, grid é outra (parecida, mas diferente). Cluster é um conceito genérico, grid é mais específico e, em geral, é bom evitar grids e ter clusters.

O que o asaudate falou faz sentido, mas ter um ambiente totalmente stateless requer https para autenticação.

Se o ambiente é stateless, o cara tem que enviar username e senha em CADA requisição e a autenticação tem que ser feita em CADA requisição. Já que vc está enviando o username e senha TODAS as requisições então TODAS as requisições terão que ser HTTPS. Talvez isso hoje em dia já seja algo aceitável, alguém com experiência REAL com web services pode opinar.

Agora se vc utilizar um MEMCACHE da vida, vc pode autenticar o cara só uma única vez, criar um HASH (session id) e enviar essa session ID pra ele. Daí vc guarda essa session id no memcache e o cara pode apenas enviar essa session id a cada requisição. Feito isso vc basicamente implementou o esquema de sessão de um web container no seu web service.

Só que a session id tem vários problemas de segurança (session hijack) então enviando o username e a senha sempre via https é a opção mais segura.

Uma dúvida: Já que o cliente do web service vai ter que enviar o username e a senha SEMPRE ele vai ter que armazenar isso em algum lugar do seu lado. Não teríamos aí um problema de segurança no lado do cliente?

O pessoal do OWASP tem umas estratégias pra combater isso (não me pergunte como porque eu não sei dos detalhes).

[quote=asaudate][quote=saoj]
Só que a session id tem vários problemas de segurança (session hijack) então enviando o username e a senha sempre via https é a opção mais segura.

Uma dúvida: Já que o cliente do web service vai ter que enviar o username e a senha SEMPRE ele vai ter que armazenar isso em algum lugar do seu lado. Não teríamos aí um problema de segurança no lado do cliente?
[/quote]

O pessoal do OWASP tem umas estratégias pra combater isso (não me pergunte como porque eu não sei dos detalhes).[/quote]

Acho que o cliente pode guardar o username e a senha em memória mesmo e enviá-la com cada requisição via https.

Esse link que vc me passou é muito burocrático. :slight_smile:

[quote=saoj][quote=asaudate][quote=saoj]
Só que a session id tem vários problemas de segurança (session hijack) então enviando o username e a senha sempre via https é a opção mais segura.

Uma dúvida: Já que o cliente do web service vai ter que enviar o username e a senha SEMPRE ele vai ter que armazenar isso em algum lugar do seu lado. Não teríamos aí um problema de segurança no lado do cliente?
[/quote]

O pessoal do OWASP tem umas estratégias pra combater isso (não me pergunte como porque eu não sei dos detalhes).[/quote]

Acho que o cliente pode guardar o username e a senha em memória mesmo e enviá-la com cada requisição via https.

Esse link que vc me passou é muito burocrático. :)[/quote]

Demaaaaaaais!!! É justamente por isso que eu não sei dos detalhes =D

Com a questão do usuário e senha é justamente uma questão muito interessante, estou dando uma caçada nos papers do Michael Stonebraker (“pai” da idéia do shared-nothing e derivados) pra ver qual é a idéia :wink:

No ambiente onde o usuário precisa receber/enviar todos os dados para não salvar o estado no lado do servidor criaria um tráfego realmente intenso na rede… Eu imaginei um cenário que até criou essa dúvida em mim, imagine o seguinte:

  • Um usuário logado no sistema começa a preencher 5 formulários, um após o outro… se no terceiro formulário o usuário resolver parar o preenchimento e abrir outro navegador ele teria que logar novamente, correto? então o sistema precisaria resgatar o estado dele anterior, existe uma restrição ai: todos esses dados só podem ser persistidos no SGBD quando os 5 formulários estiverem completamente preenchidos, agora surge a questão, onde armazenar e como resgatar?

Para buscar os dados que pertencem a esse usuário o login pode ser utilizado, mas supondo que existem 5 containers em cluster e o usuário fez o primeiro acesso em S1 (servidor 01), já no segundo acesso ele entrou em S2, se esses dados estiverem na memória de S1, como S2 vai descobrir e resgatar? existe algum container que faça esse gerenciamento automaticamente tomando como identificador um dado que agente provê (nesse caso um login por exemplo)?.

Temos um caso real dessa situação no trabalho que se repete muito… basta o usuário mudar um IP para o servidor OC4J jogá-lo em outro servidor que não tem o estado anterior dele…

[quote=saoj]O que o asaudate falou faz sentido, mas ter um ambiente totalmente stateless requer https para autenticação.

Se o ambiente é stateless, o cara tem que enviar username e senha em CADA requisição e a autenticação tem que ser feita em CADA requisição. Já que vc está enviando o username e senha TODAS as requisições então TODAS as requisições terão que ser HTTPS. Talvez isso hoje em dia já seja algo aceitável, alguém com experiência REAL com web services pode opinar.

Agora se vc utilizar um MEMCACHE da vida, vc pode autenticar o cara só uma única vez, criar um HASH (session id) e enviar essa session ID pra ele. Daí vc guarda essa session id no memcache e o cara pode apenas enviar essa session id a cada requisição. Feito isso vc basicamente implementou o esquema de sessão de um web container no seu web service.

Só que a session id tem vários problemas de segurança (session hijack) então enviando o username e a senha sempre via https é a opção mais segura.

Uma dúvida: Já que o cliente do web service vai ter que enviar o username e a senha SEMPRE ele vai ter que armazenar isso em algum lugar do seu lado. Não teríamos aí um problema de segurança no lado do cliente?
[/quote]

Autenticação e arquitetura stateless não são casos de uso opostos?

Autenticação = Restringir acesso à informação
Arquitetura Stateless = Escalabilidade (ou seja, publicar informação para o máximo número de pessoas com o mínimo de esforço)

[quote=tionil][quote=saoj]O que o asaudate falou faz sentido, mas ter um ambiente totalmente stateless requer https para autenticação.

Se o ambiente é stateless, o cara tem que enviar username e senha em CADA requisição e a autenticação tem que ser feita em CADA requisição. Já que vc está enviando o username e senha TODAS as requisições então TODAS as requisições terão que ser HTTPS. Talvez isso hoje em dia já seja algo aceitável, alguém com experiência REAL com web services pode opinar.

Agora se vc utilizar um MEMCACHE da vida, vc pode autenticar o cara só uma única vez, criar um HASH (session id) e enviar essa session ID pra ele. Daí vc guarda essa session id no memcache e o cara pode apenas enviar essa session id a cada requisição. Feito isso vc basicamente implementou o esquema de sessão de um web container no seu web service.

Só que a session id tem vários problemas de segurança (session hijack) então enviando o username e a senha sempre via https é a opção mais segura.

Uma dúvida: Já que o cliente do web service vai ter que enviar o username e a senha SEMPRE ele vai ter que armazenar isso em algum lugar do seu lado. Não teríamos aí um problema de segurança no lado do cliente?
[/quote]

Autenticação e arquitetura stateless não são casos de uso opostos?

Autenticação = Restringir acesso à informação
Arquitetura Stateless = Escalabilidade (ou seja, publicar informação para o máximo número de pessoas com o mínimo de esforço)[/quote]

Não são opostas. Vc precisa de atuenticação num ambiente stateless. E para ter segurança vai ter que usar https em tudo pois a senha estará clear-text em todas as requisicões. Se bem que mesmo usando session id o recomendável é ter https, então acho que no final vai dar na mesma.

[quote=tiagomac]No ambiente onde o usuário precisa receber/enviar todos os dados para não salvar o estado no lado do servidor criaria um tráfego realmente intenso na rede… Eu imaginei um cenário que até criou essa dúvida em mim, imagine o seguinte:

  • Um usuário logado no sistema começa a preencher 5 formulários, um após o outro… se no terceiro formulário o usuário resolver parar o preenchimento e abrir outro navegador ele teria que logar novamente, correto? então o sistema precisaria resgatar o estado dele anterior, existe uma restrição ai: todos esses dados só podem ser persistidos no SGBD quando os 5 formulários estiverem completamente preenchidos, agora surge a questão, onde armazenar e como resgatar?

Para buscar os dados que pertencem a esse usuário o login pode ser utilizado, mas supondo que existem 5 containers em cluster e o usuário fez o primeiro acesso em S1 (servidor 01), já no segundo acesso ele entrou em S2, se esses dados estiverem na memória de S1, como S2 vai descobrir e resgatar? existe algum container que faça esse gerenciamento automaticamente tomando como identificador um dado que agente provê (nesse caso um login por exemplo)?.

Temos um caso real dessa situação no trabalho que se repete muito… basta o usuário mudar um IP para o servidor OC4J jogá-lo em outro servidor que não tem o estado anterior dele…

[/quote]

Justamente. Ao longo de todas as requisições, ele vai apenas enriquencendo os dados para, no final, mandar um pacote só. É a idéia de não se manter o estado no servidor: quando não se faz isso, a tendência é manter o estado no cliente.

No caso do cluster OC4J, a idéia seria que ele fosse um cluster de fato. Em cluster, existe o conceito de sticky sessions, onde os nós do cluster conhecem a sessão de que eles estão falando. Nesse caso, mesmo que a requisição N seja enviada para um servidor diferente da requisição N-1, ainda assim eles sabem do que o cliente está falando. E o problema aí é justamente a escalabilidade.

[]'s

P.S: Quem usa OC4J em 2012?!?!? :shock:

[quote=saoj][quote=tionil][quote=saoj]O que o asaudate falou faz sentido, mas ter um ambiente totalmente stateless requer https para autenticação.

Se o ambiente é stateless, o cara tem que enviar username e senha em CADA requisição e a autenticação tem que ser feita em CADA requisição. Já que vc está enviando o username e senha TODAS as requisições então TODAS as requisições terão que ser HTTPS. Talvez isso hoje em dia já seja algo aceitável, alguém com experiência REAL com web services pode opinar.

Agora se vc utilizar um MEMCACHE da vida, vc pode autenticar o cara só uma única vez, criar um HASH (session id) e enviar essa session ID pra ele. Daí vc guarda essa session id no memcache e o cara pode apenas enviar essa session id a cada requisição. Feito isso vc basicamente implementou o esquema de sessão de um web container no seu web service.

Só que a session id tem vários problemas de segurança (session hijack) então enviando o username e a senha sempre via https é a opção mais segura.

Uma dúvida: Já que o cliente do web service vai ter que enviar o username e a senha SEMPRE ele vai ter que armazenar isso em algum lugar do seu lado. Não teríamos aí um problema de segurança no lado do cliente?
[/quote]

Autenticação e arquitetura stateless não são casos de uso opostos?

Autenticação = Restringir acesso à informação
Arquitetura Stateless = Escalabilidade (ou seja, publicar informação para o máximo número de pessoas com o mínimo de esforço)[/quote]

Não são opostas. Vc precisa de atuenticação num ambiente stateless. E para ter segurança vai ter que usar https em tudo pois a senha estará clear-text em todas as requisicões. Se bem que mesmo usando session id o recomendável é ter https, então acho que no final vai dar na mesma.
[/quote]

Se você precisa de autenticação não terá muitos benefícios em adotar uma arquitetura stateless.

Ainda assim você pode usar mecanismo baseado em tokens e guardar o estado no servidor ou num memcache sem problemas.

O problema de armazenar na sessão é que o estado passa a estar associado com a instancia do servidor.

[quote=tiagomac]Saudações amigos!!!

Referente a ambientes distribuídos e quanto a questão de programação, muito se fala sobre a utilização de stateless e stateful em ambiente corporativo tem-se adotado muito a utilização do stateful através de frameworks como jsf, gwt, wicket e outros… já na outra ponta estão as “startups” que tem aderido mais ao modelo stateless com frameworks como spring mvc, struts e outras linguagens hipistas que trazem esse conceito embutido em si.
Não querendo aqui discutir qual framework/linguagem é ou não, se jsf também pode ou não ser stateless, mas gostaria de tirar dúvida e discutir 2 itens:

1) O modelo stateless é realmente o mais indicado para distribuir o sistema entre “shards”,“cluster”,“grid”,“servidores”? e porque?
2) Se a utilização de sessão para salvar o estado do usuário destruir a possibilidade de distribuir o sistema entre servidores, então eu não deveria utilizar mais sessão? ou poderia serializar a sessão no banco para auxiliar no retorno do usuário ao site para momentos críticos como no caso de um “carrinho de compras”?

Resumindo, minha dúvida está em torno do uso da sessão em um ambiente stateless/distribuído…

[/quote]

Bom, primeiro vc está misturando um pouco as coisas. Discutir usar session ou não usar session no web container, não tem nada que ver com sistema distribuido.
Sistema distribuido é considerar que todas as camadas existem em mais do que um nodo. Não apenas a camada de apresentação.

Como sempre, depende da aplicação. E-comerce é statless. Isto porque a forma de usar o site é mais esparça. Vc quer que todos os URL funcionem corretamente sem autenticação ou informações de dependam o usuário porque nem sempre existe um usuário e temos os robots do google que são muito importantes. Agora, ERPs não tem como não ter session. Auditoria, etc… faz parte. Todos os webcontainers criam session por default mesmo que vc não use e mandam um cookie para o browser. É no browser que está o segredo e não no web container. Se eu não usar session no web container , mas usar cookie estou mantendo o estado na mesma, mas meu sistema é statetless. Neste caso a camada de cliente é stateless (que é o correto) e o resto não precisa. Já que o cliente não precisa ser destribuido ( o usuário só está em um lugar de cada vez).

Outro ponto é , sendo statless e mesmo assim ter que passar informação do usuário. Ai caimos no https que já foi referido, mas principalmente caimos no contextos de segurança EE. Se vc usar JAAS para cria este contexto, vc consegue propagar a informação até ao EJB sem problemas e sem usar estado em nenhum lugar (excepto no cliente. Esta é a tecnica que o google usa : tudo com cookies e https)

[quote=tionil]
Se você precisa de autenticação não terá muitos benefícios em adotar uma arquitetura stateless.

Ainda assim você pode usar mecanismo baseado em tokens e guardar o estado no servidor ou num memcache sem problemas.

O problema de armazenar na sessão é que o estado passa a estar associado com a instancia do servidor.[/quote]

Então… discordo totalmente. Em partes:

  1. O problema da autenticação não invalida uma arquitetura stateless, já que a vantagem da escalabilidade é muito maior do que simplesmente ter que se autenticar por requisição. Você consegue imaginar o tamanho do cluster do Gmail ? Você conseguiria acreditar se alguém te falasse que é uma arquitetura stateful? Nem eu. O ponto aqui é até que simples: quem armazena o estado é o cliente, de maneira que, quando falamos de stateless, estamos nos referindo ao servidor. Ninguém falou sobre problema algum em se armazenar o estado no cliente. (Por falar nisso, já ouviu falar em HATEOAS, um dos conceitos de REST?)

  2. Armazenar a sessão não implica “amarrar” o cliente a uma máquina, já que isso quebraria o conceito de alta disponibilidade. O problema é que as sessões precisam ser configuradas como sticky, o que faz com que os nós do cluster “conversem” entre si, repassando entre eles a sessão. Um imenso gargalo em clusters grandes.

[]'s

[quote=asaudate][quote=tionil]
Se você precisa de autenticação não terá muitos benefícios em adotar uma arquitetura stateless.

Ainda assim você pode usar mecanismo baseado em tokens e guardar o estado no servidor ou num memcache sem problemas.

O problema de armazenar na sessão é que o estado passa a estar associado com a instancia do servidor.[/quote]

Então… discordo totalmente. Em partes:

  1. O problema da autenticação não invalida uma arquitetura stateless, já que a vantagem da escalabilidade é muito maior do que simplesmente ter que se autenticar por requisição. Você consegue imaginar o tamanho do cluster do Gmail ? Você conseguiria acreditar se alguém te falasse que é uma arquitetura stateful? Nem eu. O ponto aqui é até que simples: quem armazena o estado é o cliente, de maneira que, quando falamos de stateless, estamos nos referindo ao servidor. Ninguém falou sobre problema algum em se armazenar o estado no cliente. (Por falar nisso, já ouviu falar em HATEOAS, um dos conceitos de REST?)

  2. Armazenar a sessão não implica “amarrar” o cliente a uma máquina, já que isso quebraria o conceito de alta disponibilidade. O problema é que as sessões precisam ser configuradas como sticky, o que faz com que os nós do cluster “conversem” entre si, repassando entre eles a sessão. Um imenso gargalo em clusters grandes.

[]'s[/quote]

Desculpa mas não entendi.

Afinal, você esta dizendo que o gmail adota uma arquitetura stateless ou não.

Dizem que um memcache distribuído segura bem.

Outra possibilidade é usar o database como um “repositório distribuído”.

Daí o seu ponto de falha fica sendo o database.

Daí faz um cluster de database. Nunca fiz, mas ouvi falar que o mysql faz isso bem.

Aplicações web por padrão oferecem uma implementação simples de session via cookie (ou URL rewrite), que obviamente não é 100% segura a não ser que vc use https para evitar session hijack.

Web services SOAP/REST até onde eu sei não te oferecem NADA para autenticação, isto é, assumem statless e um abraço! Mais um motivo pelo qual eu fujo de SOAP/REST e faço meus web services dentro do meu container web, como se fosse uma aplicação web qualquer, sem wsdl mesmo. Eu publico um documento com as especficações dos meus web services. Uma coisa que SEMPRE QUIZ é um javadoc para especifica web services. Não sei como alguém não fez isso ainda.

A verdade é que para certas aplicações, a session é uma mão na roda, e ficar guardando informação no cliente é tedioso. Sem contar que não persiste. O caso clássico é o carrinho de compras. Nesse caso acho que o bom e velho database se torna o seu cluster de session, ou sja, vc guarda o estado no database.