IPv6 – Happy Eyeballs

Definida na rfc6555, Happy Eyeballs é uma forma de tentar corrigir o problema de decisão sobre qual conexão preferir, caso as duas pontas possuam IPv4 e IPv6. Seu funcionamento consiste em tentar se conectar às duas conexões simultaneamente e utilizar aquela que é estabelecida mais rapidamente, dando uma leve preferência para a conexões IPv6. Browsers como Google Chrome e Mozilla Firefox em suas versões atuais já implementam o Happy Eyeballs e o utilizam por padrão.

Em sua definição mais básica, na hora de acessar um domínio, são verificados seus IPv4 e IPv6 disponíveis para se conectar. O funcionamento padrão da maioria dos sistemas operacionais faz com que primeiro seja tentado a conexão via IPv6 e em caso de falha (timeout) é tentado a conexão via IPv4. Essa implementação apresenta um problema grave, pois caso a conexão IPv6 apresente problemas, o usuário com IPv6 sofrerá um grande delay para acessar o site, enquanto um usuário comum que apresente apenas IPv4 não sofrerá disso. Esse problema é uma das principais barreiras para os provedores de conteúdos, pois o simples fato de se implementar o IPv6 pode acarretar em um prejuízo para o provedor.

Uma solução proposta para isso foi a de tentar se conectar tanto via IPv6 como via IPv4 simultaneamente. Assim o primeiro a responder seria aceito e a outra conexão seria descartada. No entanto essa solução possui 2 problemas:

  1. Seriam desperdiçados muitos sockets para as tentativas de conexões, pois independente da qualidade do serviço sempre seriam feitas pelo menos 2 tentativas de conexão simultaneas. Além disso o excesso de tentativas poderia fazer com que regras mais rígidas de controle de acesso bloqueassem o usuário por excesso de conexões;
  2. Mesmo que o IPv6 possuísse uma qualidade aceitável, o simples fato dele ser um pouco mais lento que o IPv4 faria com que ele nunca fosse utilizado. A princípio isso não é um problema, porém acabaria gerando uma grande barreira para o avanço do IPv6, pois na situação atual é comum que as implementações de IPv6 não sejam tão eficientes quanto as IPv4 já existentes, o que faria com que tais conexões nunca fossem utilizadas, desestimulando assim seu uso.

Diante de tal problema, o algoritmo do Happy Eyeballs procura incentivar o uso do IPv6, porém sem prejudicar a experiência de uso do usuário. Isso é feito partindo do princípio de que a conexão IPv6 está OK, e caso a conexão não seja realizada após um intervalo de tempo (estimado suficiente para se estabelecer a conexão via IPv6) é tentando a conexão via IPv4. Assim mesmo que a conexão IPv6 falhe, o intervalo de tempo perdido para se estabelecer a conexão via IPv4 (da ordem de milisegundos) é praticamente imperceptível ao usuário, ao mesmo tempo em que se evita o excesso de conexões sofrido na solução anterior.

Além disso, o algoritmo do Happy Eyeballs deve guardar em um cache a decisão sobre qual conexão foi preferida (IPv4 ou IPv6). Isso ajuda a evitar tráfego desnecessário na rede, pois caso o IPv6 esteja com problemas, toda conexão feita seria feita primeiramente em IPv6 (que irá falhar) e depois em IPv4. Com o cache esse processo seria feito apenas uma vez e as demais conexões seriam feitas diretamente via IPv4. A rfc6555 especifica que o cache não deve ser guardado por mais de 10 minutos para evitar vícios na rede.

Outro ponto a ser notado é no caso do host possuir mais de um IPv6 ou mais de um IPv4. Neste caso continua se utilizando o procedimento recomendado pelo Happy Eyeballs: tentar se conectar primeiro a um (único) IPv6 e após um pequeno intervalo de tempo t (da ordem de 100 – 300ms) tentar se conectar a um (único) IPv4. Se passar outro intervalo de tempo t após tentar se conectar via IPv4, isso significa que provavelmente o problema não se deve ao protocolo em si, mas sim a outro problema (específico do IP em questão). Assim a rfc6555 recomenda que tente se conectar com os demais IPs, independente se for IPv6 ou IPv4, sempre esperando um intervalo de tempo t entre as tentativas.

Abaixo segue o exemplo do algoritmo básico do Happy Eyeballs (sem cache e admitindo um único IPv6 e um único IPv4):

        conectar (endereço) {
                encontra IPs do endereço
                tenta se conectar a o endereço IPv6
                enquanto nenhuma conexão se estabelece e timeout não estoura {
                        se passou tempo de vantagem dado ao IPv6 {
                                tenta se conectar a um endereço IPv4 (uma única vez)
                        }
                }
                se conseguiu conectar {
                        mantém a conexão conectada
                        fecha as demais conexões (sockets abertos)
                } caso não conseguiu conectar (timeout) {
                        fecha todas as conexões (sockets abertos)
                }
        }

Este é apenas o algortimo básico, portanto não deve ser utilizado, pois faltam recursos importantes como o cache e o tratamento caso existam mais IPs. Porém ele serve para mostrar alguns pontos importantes:

  1. Ao encontrar os IPs do endereço deve-se tomar certo cuidado, pois alguns métodos de se encontrar os IPs (como gethostbyname) retornan apenas IPv4;
  2. Sempre lembrar de fechar as conexões que não foram estabelecidas (e limpar a memória em linguagens sem garbage collector).

Abaixo o algoritmo completo do Happy Eyeballs:

        conectar (endereço) {
                encontra IPs do endereço
                verifica cache (endereço)
                se não existir cache {
                        tenta se conectar a um endereço IPv6
                        enquanto nenhuma conexão se estabelece e timeout não estoura {
                                se passou tempo de vantagem dado ao IPv6 {
                                        tenta se conectar a um endereço IPv4 (uma única vez)
                                }
                                se passou tempo de vantagem e não se conectou nem via IPv6 nem via IPv4 {
                                        tenta se conectar a qualquer outro endereço disponível
                                }
                        }
                } se estiver no cache {
                        tenta se conectar a um endereço com a versão definida no cache
                }
                se conseguiu conectar {
                        mantém a conexão conectada
                        fecha as demais conexões (sockets abertos)
                } caso não conseguiu conectar (timeout) {
                        fecha todas as conexões (sockets abertos)
                }
        }

        verifica cache (endereço) {
                verifica se existe o cache para endereço
                se cache existe {
                        se o cache está ativo há mais de 10 minutos {
                                limpa o cache
                        } caso contrario {
                                retorna o cache
        }
                }
        }

Fonte: http://ipv6.br/entenda/happy-eyeballs/

Deixe um comentário