Integre suas aplicações Spring Cloud ao Service Mesh (ASM) para aproveitar recursos nativos da cloud de governança de serviços sem modificar seu código. Este tópico descreve como usar o ASM para gerenciar serviços do Spring Cloud.
Pré-requisitos
Você possui uma instância do ASM Enterprise ou Ultimate Edition. Para mais informações, consulte Create an ASM instance.
Um cluster gerenciado ACK foi criado. Para mais informações, consulte Create an ACK managed cluster.
Um gateway de entrada está implantado. Para mais informações, consulte Create an ingress gateway.
Contexto
O Spring Cloud é um padrão com diversas implementações, como Spring Cloud Netflix, Spring Cloud Alibaba e Spring Cloud Consul. Para o ASM, a principal diferença entre essas implementações é o registro de serviço utilizado. A tabela a seguir lista o suporte à migração do ASM para diferentes versões do Spring Cloud.
|
Versão do Spring Cloud |
Registro de serviço |
Suporte à migração |
|
Spring Cloud Alibaba |
Microservices Engine (MSE) Nacos (um serviço da Alibaba Cloud) |
Suportado |
|
Spring Cloud Alibaba |
Nacos (autogerenciado) |
Suportado |
|
Spring Cloud Netflix |
Eureka |
Suportado. A versão da instância do ASM deve ser 1.13.4.53 ou posterior. |
|
Spring Cloud Consul |
Consul |
Suportado. A versão da instância do ASM deve ser 1.13.4.53 ou posterior. |
|
Spring Cloud Zookeeper |
Zookeeper |
Suportado. A versão da instância do ASM deve ser 1.13.4.53 ou posterior. |
Visão geral da demonstração
Este tópico utiliza como exemplo uma aplicação desenvolvida com Spring Cloud e Nacos. Baixe o código de amostra no repositório nacos-example.
A aplicação consiste em um serviço consumidor e um serviço provedor. O serviço provedor possui duas versões, v1 e v2, ambas registradas em um registro Nacos. O serviço consumidor obtém os endereços do serviço provedor no registro Nacos e balanceia as requisições entre eles. Ao receber uma requisição, o serviço consumidor a encaminha para um provedor e retorna a resposta correspondente. As duas versões do provedor retornam respostas diferentes:
O provedor v1 responde a uma requisição echo com
Hello Nacos Discovery From v1xxx.O provedor v2 responde a uma requisição echo com
Hello Nacos Discovery From v2xxx.
Na resposta, .xxx é um espaço reservado para o parâmetro passado à API echo. Por exemplo, se uma requisição para /echo/world for enviada ao provedor v1, ele retornará Hello Nacos Discovery From v1world.
Se você não ativar os recursos de service mesh para os serviços consumidor e provedor, ou seja, se nenhum sidecar for injetado nos pods da aplicação, as requisições ainda serão processadas, mas não terão os recursos de governança de serviços fornecidos pelo Istio. Os passos a seguir demonstram como usar o ASM para gerenciar os serviços do Spring Cloud.
Passo 1: Ativar o suporte ao Spring Cloud
Método 1: Para todas as versões e registros
A versão da instância do ASM deve ser 1.13.4.32 ou posterior.
Limitações:
É necessário criar um Kubernetes Service para o serviço de destino. A porta do serviço e a porta de destino devem ser definidas como a porta de escuta da aplicação.
Em versões do ASM anteriores a 1.23.6.32, você deve desativar REGISTRY_ONLY ao usar esta solução.
Conecte-se ao cluster do plano de controle usando kubectl. Para mais informações, consulte Access Istio resources on the control plane by using kubectl.
-
Crie um EnvoyFilter no cluster ASM.
-
Crie um arquivo chamado any-spring-cloud-support.yaml com o seguinte conteúdo.
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: labels: provider: "asm" asm-system: "true" name: any-spring-cloud-support namespace: istio-system spec: configPatches: - applyTo: HTTP_FILTER match: proxy: proxyVersion: "^1.*" context: SIDECAR_OUTBOUND listener: portNumber: 8070 filterChain: filter: name: "envoy.filters.network.http_connection_manager" subFilter: name: "envoy.filters.http.router" patch: operation: INSERT_BEFORE value: # reverse_dns filter specification name: com.aliyun.reverse_dns typed_config: "@type": "type.googleapis.com/udpa.type.v1.TypedStruct" type_url: type.googleapis.com/envoy.config.filter.reverse_dns.v3alpha.CommonConfig value: pod_cidrs: - "10.0.128.0/18"Modifique os parâmetros no arquivo YAML conforme suas necessidades de negócio. Os parâmetros são descritos abaixo:
portNumber: A porta do serviço Spring Cloud. Se as portas não forem uniformes, remova este parâmetro. Caso seja possível consolidar as portas, configure vários recursos EnvoyFilter, cada um vinculado a umaportNumberespecífica.pod_cidrs: O CIDR de pod do cluster ACK ou ACK Serverless. Para encontrar esse valor, faça login no Container Service Management Console e acesse a página Cluster Information. Na aba Cluster Resources, localize o bloco CIDR do Pod em VPC e utilize esse valor para o parâmetro.
-
Execute o comando a seguir para aplicar o
EnvoyFilter.kubectl apply -f any-spring-cloud-support.yaml
-
Método 2: Apenas para registros Nacos
Conecte-se ao cluster do plano de controle usando kubectl. Para mais informações, consulte Access Istio resources on the control plane by using kubectl.
-
Crie um ServiceEntry.
-
Crie um arquivo chamado external-nacos-svc.yaml com o seguinte conteúdo.
kind: ServiceEntry metadata: name: external-nacos-svc spec: hosts: - "NACOS_SERVER_HOST" ## Replace this with your Nacos Server HOST, for example, "mse-xxx-p.nacos-ans.mse.aliyuncs.com". location: MESH_EXTERNAL ports: - number: 8848 name: http resolution: DNSNo arquivo YAML anterior,
8848é a porta padrão do Nacos. Se você usa um servidor Nacos autogerenciado e alterou a porta, modifique também o parâmetronumberadequadamente. -
Execute o comando a seguir para criar o ServiceEntry.
kubectl apply -f external-nacos-svc.yaml
-
-
Crie um EnvoyFilter.
-
Crie um arquivo chamado external-envoyfilter.yaml com o seguinte conteúdo.
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: labels: provider: "asm" asm-system: "true" name: nacos-subscribe-lua namespace: istio-system spec: configPatches: # The first patch adds the lua filter to the listener/http connection manager. - applyTo: HTTP_FILTER match: proxy: proxyVersion: "^1.*" context: SIDECAR_OUTBOUND listener: portNumber: 8848 filterChain: filter: name: "envoy.filters.network.http_connection_manager" subFilter: name: "envoy.filters.http.router" patch: operation: INSERT_BEFORE value: # lua filter specification name: envoy.lua typed_config: "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua" inlineCode: | -- copyright: ASM (Alibaba Cloud ServiceMesh) function envoy_on_request(request_handle) local request_headers = request_handle:headers() -- /nacos/v1/ns/instance/list?healthyOnly=false&namespaceId=public&clientIP=10.122.63.81&serviceName=DEFAULT_GROUP%40%40service-provider&udpPort=53174&encoding=UTF-8 local path = request_headers:get(":path") if string.match(path,"^/nacos/v1/ns/instance/list") then local servicename = string.gsub(path,".*&serviceName.*40([%w.\\_\\-]+)&.*","%1") request_handle:streamInfo():dynamicMetadata():set("context", "request.path", path) request_handle:streamInfo():dynamicMetadata():set("context", "request.servicename", servicename) request_handle:logInfo("subscribe for serviceName: " .. servicename) else request_handle:streamInfo():dynamicMetadata():set("context", "request.path", "") end end function envoy_on_response(response_handle) local request_path = response_handle:streamInfo():dynamicMetadata():get("context")["request.path"] if request_path == "" then return end local servicename = response_handle:streamInfo():dynamicMetadata():get("context")["request.servicename"] response_handle:logInfo("modified response ip to serviceName:" .. servicename) local bodyObject = response_handle:body(true) local body= bodyObject:getBytes(0,bodyObject:length()) body = string.gsub(body,"%s+","") body = string.gsub(body,"(ip\":\")(%d+.%d+.%d+.%d+)","%1"..servicename) response_handle:body():setBytes(body) end -
Execute o comando a seguir para criar o EnvoyFilter.
kubectl apply -f external-envoyfilter.yaml
-
Passo 2: Implantar serviços do Spring Cloud
Para interceptar o processo de registro, crie o EnvoyFilter antes de criar as cargas de trabalho. Se uma carga de trabalho for criada antes do EnvoyFilter, execute uma atualização contínua (rolling update) nessa carga.
Crie um Kubernetes Service do tipo ClusterIP para cada serviço.
Conecte-se ao cluster do plano de dados usando kubectl. Para mais informações, consulte Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.
-
Execute os comandos a seguir para implantar os serviços do Spring Cloud.
export NACOS_ADDRESS=xxxx # Replace xxxx with the address of your MSE or self-managed Nacos. We recommend using an internal VPC address. wget https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-labs/springcloud/demo.yaml -O demo.yaml sed -e "s/NACOS_SERVER_CLUSTERIP/$NACOS_ADDRESS/g" demo.yaml |kubectl apply -f - -
Execute o comando a seguir para verificar os serviços do Spring Cloud.
kubectl get podsSaída esperada:
consumer-bdd464654-jn8q7 2/2 Running 0 25h provider-v1-66bc67fb6d-46pgl 2/2 Running 0 25h provider-v2-76568c45f6-85z87 2/2 Running 0 25h
Passo 3: Criar um gateway e um serviço virtual
-
Crie um gateway Istio.
-
Crie um arquivo chamado test-gateway.yaml com o seguinte conteúdo.
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: test-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" -
Use o arquivo kubeconfig da instância ASM e execute o comando a seguir para criar o gateway Istio.
kubectl apply -f test-gateway.yaml
-
-
Crie um serviço virtual.
-
Crie um arquivo chamado consumer.yaml com o seguinte conteúdo.
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: consumer spec: hosts: - "*" gateways: - test-gateway http: - match: - uri: prefix: / route: - destination: host: consumer.default.svc.cluster.local port: number: 8080 -
Execute o comando a seguir para criar o serviço virtual.
kubectl apply -f consumer.yaml
-
Passo 4: Verificar o gerenciamento de serviços
-
Obtenha o endereço IP do gateway de entrada.
Faça login no console do ASM. No painel de navegação à esquerda, escolha .
Na página Mesh Management, clique no nome da instância ASM. No painel de navegação à esquerda, escolha .
Na página Ingress Gateway, visualize o Service address do gateway de entrada.
-
Execute o comando a seguir para enviar uma requisição ao serviço consumidor do Spring Cloud através do gateway de entrada.
curl <IP address of the ingress gateway>/echo/worldSaída esperada:
Hello Nacos Discovery From v1world Hello Nacos Discovery From v2world Hello Nacos Discovery From v1world Hello Nacos Discovery From v2worldA saída mostra que as requisições são roteadas para os provedores v1 e v2 em round-robin por padrão.
-
Crie uma regra de destino e um serviço virtual.
-
Crie um arquivo chamado service-provider.yaml com o seguinte conteúdo.
--- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: service-provider spec: host: service-provider subsets: - name: v1 labels: label: v1 - name: v2 labels: label: v2 -
Execute o comando a seguir para criar a regra de destino.
kubectl apply -f service-provider.yaml -
Crie um arquivo chamado service-provider1.yaml com o seguinte conteúdo.
O serviço virtual a seguir roteia requisições para /echo/hello ao provedor v1 e direciona todas as outras requisições ao provedor v2.
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: service-provider spec: hosts: - service-provider http: - name: "hello-v1" match: - uri: prefix: "/echo/hello" route: - destination: host: service-provider subset: v1 - name: "default" route: - destination: host: service-provider subset: v2 -
Execute o comando a seguir para criar o serviço virtual.
kubectl apply -f service-provider1.yaml
-
-
Execute o comando a seguir para enviar uma requisição ao serviço consumidor do Spring Cloud.
curl <IP address of the ingress gateway>/echo/helloSaída esperada:
Hello Nacos Discovery From v1hello Hello Nacos Discovery From v1helloA saída indica que todas as requisições para
/echo/hellosão roteadas para o provedor v1, enquanto as demais vão para o provedor v2. Isso confirma que o Istio agora controla o tráfego do Spring Cloud, permitindo que você gerencie os serviços usando regras de roteamento do Istio.
Perguntas frequentes
Solução de problemas de serviços do Spring Cloud
-
Verifique se a interceptação de tráfego está ativada para a porta ou endereço IP do Nacos.
Ao utilizar o método reverse_dns, é obrigatório interceptar os endereços IP dos pods.
Caso utilize o método de script Lua, intercepte o endereço IP do Servidor Nacos e o endereço IP do cluster.
Para interceptar o processo de registro, crie o EnvoyFilter antes das cargas de trabalho. Se uma carga de trabalho foi criada primeiro, realize uma atualização contínua nela.
Confirme se existe um Kubernetes Service do tipo ClusterIP para cada serviço.
-
Identifique qual método você usou para ativar o suporte ao Spring Cloud no plano de controle do ASM.
Verifique a versão do sidecar dos serviços. Se a versão da imagem do sidecar for anterior a 1.13.4.32, apenas o plano de controle da instância ASM foi atualizado, mas não o plano de dados. Execute uma atualização contínua nas implantações de serviço afetadas.