This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch k8s/service-registry
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit 19b60d887a56f305bb307dcb12b15e3dcfe5d1c8
Author: kezhenxu94 <kezhenx...@163.com>
AuthorDate: Fri Oct 23 12:06:38 2020 +0800

    Improve K8S ALS analysis
    
    The current implementation of envoy ALS K8S analysis is based on the 
hierarchy, pod -> StatefulSet -> deployment, StatefulSet, or others. It's 
freaky and different from the Istio Kubernetes registry.
    
    The new path is pod -> endpoint -> service, and we should leverage Informer 
API instead of raw Kubernetes API.
---
 .github/workflows/e2e.istio.yaml                   |  13 +-
 docker/oap/log4j2.xml                              |   1 +
 .../receiver/envoy/als/K8SServiceRegistry.java     | 220 +++++++++++++++++
 .../envoy/als/K8sALSServiceMeshHTTPAnalysis.java   | 273 ++++++---------------
 .../server/receiver/envoy/als/ServiceMetaInfo.java |   9 +
 .../receiver/envoy/als/K8sHTTPAnalysisTest.java    |  17 +-
 test/e2e-mesh/e2e-istio/scripts/istio.sh           |   3 +-
 .../skywalking/e2e/retryable/RetryableTest.java    |   4 +-
 .../org/apache/skywalking/e2e/mesh/ALSE2E.java     |   2 +-
 .../src/test/resources/expected/als/services.yml   |  12 +-
 10 files changed, 329 insertions(+), 225 deletions(-)

diff --git a/.github/workflows/e2e.istio.yaml b/.github/workflows/e2e.istio.yaml
index 28db870..4450f70 100644
--- a/.github/workflows/e2e.istio.yaml
+++ b/.github/workflows/e2e.istio.yaml
@@ -21,14 +21,16 @@ on:
   push:
     branches:
       - master
+      - k8s/service-registry
 
 env:
   SKIP_TEST: true
   ES_VERSION: es7
   ISTIO_VERSION: 1.7.1
+  K8S_VER: 1.17.0
   TAG: ${{ github.sha }}
   SCRIPTS_DIR: test/e2e-mesh/e2e-istio/scripts
-  SW_OAP_BASE_IMAGE: openjdk:8-jre-alpine
+  SW_OAP_BASE_IMAGE: openjdk:11-jdk
 
 jobs:
   als:
@@ -62,17 +64,22 @@ jobs:
         run: |
           git clone https://github.com/apache/skywalking-kubernetes.git
           cd skywalking-kubernetes
-          git reset --hard 419cd1aed8bb4ad972208e5a031527a25d2ae690
+          git reset --hard e29fa9c7dc16409af2cfb9c982c9840d8932c86a
           cd chart
           helm dep up skywalking
           helm -n istio-system install skywalking skywalking \
                --set fullnameOverride=skywalking \
                --set elasticsearch.replicas=1 \
+               --set elasticsearch.minimumMasterNodes=1 \
+               --set elasticsearch.imageTag=7.5.1 \
                --set oap.env.SW_ENVOY_METRIC_ALS_HTTP_ANALYSIS=k8s-mesh \
                --set oap.envoy.als.enabled=true \
                --set oap.replicas=1 \
+               --set ui.image.repository=skywalking/ui \
+               --set ui.image.tag=$TAG \
                --set oap.image.tag=$TAG \
-               --set oap.image.repository=skywalking/oap
+               --set oap.image.repository=skywalking/oap \
+               --set oap.storageType=elasticsearch7
           kubectl -n istio-system get pods
 
           sleep 3
diff --git a/docker/oap/log4j2.xml b/docker/oap/log4j2.xml
index eb69a89..fadfaa1 100644
--- a/docker/oap/log4j2.xml
+++ b/docker/oap/log4j2.xml
@@ -29,6 +29,7 @@
         <logger name="org.elasticsearch.common.network.IfConfig" level="INFO"/>
         <logger name="io.grpc.netty" level="INFO"/>
         <logger 
name="org.apache.skywalking.oap.server.receiver.istio.telemetry" level="DEBUG"/>
+        <logger 
name="org.apache.skywalking.oap.server.receiver.envoy.als.K8SServiceRegistry" 
level="DEBUG"/>
         <Root level="INFO">
             <AppenderRef ref="Console"/>
         </Root>
diff --git 
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8SServiceRegistry.java
 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8SServiceRegistry.java
new file mode 100644
index 0000000..afb3d49
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8SServiceRegistry.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.receiver.envoy.als;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.kubernetes.client.informer.ResourceEventHandler;
+import io.kubernetes.client.informer.SharedInformerFactory;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1Endpoints;
+import io.kubernetes.client.openapi.models.V1EndpointsList;
+import io.kubernetes.client.openapi.models.V1ObjectMeta;
+import io.kubernetes.client.openapi.models.V1Pod;
+import io.kubernetes.client.openapi.models.V1PodList;
+import io.kubernetes.client.util.Config;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+
+import static java.util.Objects.isNull;
+import static java.util.Objects.requireNonNull;
+
+@Slf4j
+class K8SServiceRegistry {
+    final Map<String, ServiceMetaInfo> ipServiceMap;
+
+    final ExecutorService executor;
+
+    K8SServiceRegistry() {
+        ipServiceMap = new ConcurrentHashMap<>();
+        executor = Executors.newCachedThreadPool(
+            new ThreadFactoryBuilder()
+                .setNameFormat("K8SServiceRegistry-%d")
+                .setDaemon(true)
+                .build()
+        );
+    }
+
+    void start() throws IOException {
+        final ApiClient apiClient = Config.defaultClient();
+        apiClient.setHttpClient(apiClient.getHttpClient()
+                                         .newBuilder()
+                                         .readTimeout(0, TimeUnit.SECONDS)
+                                         .build());
+
+        final CoreV1Api coreV1Api = new CoreV1Api(apiClient);
+        final SharedInformerFactory factory = new 
SharedInformerFactory(executor);
+
+        listenEndpointsEvents(coreV1Api, factory);
+        listenPodEvents(coreV1Api, factory);
+
+        factory.startAllRegisteredInformers();
+
+        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> 
log.info("ipServiceMap={}", ipServiceMap), 10, 10, TimeUnit.SECONDS);
+    }
+
+    private void listenEndpointsEvents(final CoreV1Api coreV1Api, final 
SharedInformerFactory factory) {
+        factory.sharedIndexInformerFor(
+            params -> coreV1Api.listEndpointsForAllNamespacesCall(
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                params.resourceVersion,
+                params.timeoutSeconds,
+                params.watch,
+                null
+            ),
+            V1Endpoints.class,
+            V1EndpointsList.class
+        ).addEventHandler(new ResourceEventHandler<V1Endpoints>() {
+            @Override
+            public void onAdd(final V1Endpoints endpoints) {
+                addEndpoints(endpoints);
+            }
+
+            @Override
+            public void onUpdate(final V1Endpoints oldEndpoints, final 
V1Endpoints newEndpoints) {
+                addEndpoints(newEndpoints);
+            }
+
+            @Override
+            public void onDelete(final V1Endpoints endpoints, final boolean 
deletedFinalStateUnknown) {
+                removeEndpoints(endpoints);
+            }
+        });
+    }
+
+    private void listenPodEvents(final CoreV1Api coreV1Api, final 
SharedInformerFactory factory) {
+        factory.sharedIndexInformerFor(
+            params -> coreV1Api.listPodForAllNamespacesCall(
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                params.resourceVersion,
+                params.timeoutSeconds,
+                params.watch,
+                null
+            ),
+            V1Pod.class,
+            V1PodList.class
+        ).addEventHandler(new ResourceEventHandler<V1Pod>() {
+            @Override
+            public void onAdd(final V1Pod pod) {
+                addPod(pod);
+            }
+
+            @Override
+            public void onUpdate(final V1Pod oldPod, final V1Pod newPod) {
+                addPod(newPod);
+            }
+
+            @Override
+            public void onDelete(final V1Pod pod, final boolean 
deletedFinalStateUnknown) {
+                removePod(pod);
+            }
+        });
+    }
+
+    private void removePod(final V1Pod pod) {
+        log.debug("Removing pod {}", pod);
+
+        Optional.ofNullable(pod.getStatus()).ifPresent(
+            status -> ipServiceMap.remove(status.getPodIP())
+        );
+    }
+
+    private void addPod(final V1Pod pod) {
+        log.debug("Adding pod {}", pod);
+
+        Optional.ofNullable(pod.getStatus()).ifPresent(
+            status -> {
+                final String ip = status.getPodIP();
+                final ServiceMetaInfo service = 
ipServiceMap.computeIfAbsent(ip, unused -> new ServiceMetaInfo());
+
+                final V1ObjectMeta podMeta = requireNonNull(pod.getMetadata());
+                service.setServiceInstanceName(String.format("%s.%s", 
podMeta.getName(), podMeta.getNamespace()));
+                service.setTags(transformLabelsToTags(podMeta.getLabels()));
+            }
+        );
+    }
+
+    private void addEndpoints(final V1Endpoints endpoints) {
+        log.debug("Adding endpoints {}", endpoints);
+
+        final String serviceName = 
requireNonNull(endpoints.getMetadata()).getName();
+
+        requireNonNull(endpoints.getSubsets()).forEach(subset -> {
+            requireNonNull(subset.getAddresses()).forEach(address -> {
+                final String ip = address.getIp();
+                final ServiceMetaInfo service = 
ipServiceMap.computeIfAbsent(ip, unused -> new ServiceMetaInfo());
+                service.setServiceName(serviceName);
+            });
+        });
+    }
+
+    private void removeEndpoints(final V1Endpoints endpoints) {
+        log.debug("Removing endpoints {}", endpoints);
+
+        requireNonNull(endpoints.getSubsets()).forEach(subset -> {
+            requireNonNull(subset.getAddresses()).forEach(address -> {
+                final String ip = address.getIp();
+                ipServiceMap.remove(ip);
+            });
+        });
+    }
+
+    private List<ServiceMetaInfo.KeyValue> transformLabelsToTags(final 
Map<String, String> labels) {
+        if (isNull(labels)) {
+            return Collections.emptyList();
+        }
+        return labels.entrySet()
+                     .stream()
+                     .map(each -> new ServiceMetaInfo.KeyValue(each.getKey(), 
each.getValue()))
+                     .collect(Collectors.toList());
+    }
+
+    ServiceMetaInfo findService(final String ip) {
+        log.info("Finding ip {}", ip);
+        final ServiceMetaInfo service = ipServiceMap.getOrDefault(ip, 
ServiceMetaInfo.UNKNOWN);
+        if (!service.isComplete()) {
+            log.info("Unknown ip {}, ip -> service is null, service {}", ip, 
service);
+            return ServiceMetaInfo.UNKNOWN;
+        }
+        return service;
+    }
+
+    boolean isEmpty() {
+        return ipServiceMap.isEmpty();
+    }
+}
diff --git 
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sALSServiceMeshHTTPAnalysis.java
 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sALSServiceMeshHTTPAnalysis.java
index 6d1e3dc..807ba06 100644
--- 
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sALSServiceMeshHTTPAnalysis.java
+++ 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sALSServiceMeshHTTPAnalysis.java
@@ -19,7 +19,6 @@
 package org.apache.skywalking.oap.server.receiver.envoy.als;
 
 import com.google.common.base.Strings;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.protobuf.Duration;
 import com.google.protobuf.Timestamp;
 import io.envoyproxy.envoy.api.v2.core.Address;
@@ -31,58 +30,32 @@ import 
io.envoyproxy.envoy.data.accesslog.v2.HTTPRequestProperties;
 import io.envoyproxy.envoy.data.accesslog.v2.HTTPResponseProperties;
 import io.envoyproxy.envoy.data.accesslog.v2.TLSProperties;
 import io.envoyproxy.envoy.service.accesslog.v2.StreamAccessLogsMessage;
-import io.kubernetes.client.openapi.ApiClient;
-import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.apis.ExtensionsV1beta1Api;
-import io.kubernetes.client.openapi.models.V1ObjectMeta;
-import io.kubernetes.client.openapi.models.V1OwnerReference;
-import io.kubernetes.client.openapi.models.V1Pod;
-import io.kubernetes.client.openapi.models.V1PodList;
-import io.kubernetes.client.util.Config;
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-import lombok.AccessLevel;
-import lombok.Getter;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.aop.server.receiver.mesh.TelemetryDataDispatcher;
 import org.apache.skywalking.apm.network.common.v3.DetectPoint;
 import org.apache.skywalking.apm.network.servicemesh.v3.Protocol;
 import org.apache.skywalking.apm.network.servicemesh.v3.ServiceMeshMetric;
 import org.apache.skywalking.oap.server.core.source.Source;
 import 
org.apache.skywalking.oap.server.receiver.envoy.EnvoyMetricReceiverConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Analysis log based on ingress and mesh scenarios.
  */
+@Slf4j
 public class K8sALSServiceMeshHTTPAnalysis implements ALSHTTPAnalysis {
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(K8sALSServiceMeshHTTPAnalysis.class);
-
-    private static final String VALID_PHASE = "Running";
-
     private static final String NON_TLS = "NONE";
 
     private static final String M_TLS = "mTLS";
 
     private static final String TLS = "TLS";
 
-    @Getter(AccessLevel.PROTECTED)
-    private final AtomicReference<Map<String, ServiceMetaInfo>> ipServiceMap = 
new AtomicReference<>();
-
-    private final ScheduledExecutorService executorService = 
Executors.newScheduledThreadPool(
-        1, new ThreadFactoryBuilder()
-            .setNameFormat("load-pod-%d")
-            .setDaemon(true)
-            .build());
+    protected K8SServiceRegistry serviceRegistry;
 
     @Override
     public String name() {
@@ -90,83 +63,15 @@ public class K8sALSServiceMeshHTTPAnalysis implements 
ALSHTTPAnalysis {
     }
 
     @Override
+    @SneakyThrows
     public void init(EnvoyMetricReceiverConfig config) {
-        executorService.scheduleAtFixedRate(this::loadPodInfo, 0, 15, 
TimeUnit.SECONDS);
-    }
-
-    private boolean invalidPodList() {
-        Map<String, ServiceMetaInfo> map = ipServiceMap.get();
-        return map == null || map.isEmpty();
-    }
-
-    private void loadPodInfo() {
-        try {
-            ApiClient client = Config.defaultClient();
-            CoreV1Api api = new CoreV1Api(client);
-
-            V1PodList list = api.listPodForAllNamespaces(null, null, null, 
null, null, null, null, null, null);
-            Map<String, ServiceMetaInfo> ipMap = new 
HashMap<>(list.getItems().size());
-            long startTime = System.nanoTime();
-            for (V1Pod item : list.getItems()) {
-                if (!item.getStatus().getPhase().equals(VALID_PHASE)) {
-                    LOGGER.debug("Invalid pod {} is not in a valid phase {}", 
item.getMetadata()
-                                                                               
   .getName(), item.getStatus()
-                                                                               
                   .getPhase());
-                    continue;
-                }
-                if 
(item.getStatus().getPodIP().equals(item.getStatus().getHostIP())) {
-                    LOGGER.debug(
-                        "Pod {}.{} is removed because hostIP and podIP are 
identical ", item.getMetadata()
-                                                                               
             .getName(),
-                        item.getMetadata()
-                            .getNamespace()
-                    );
-                    continue;
-                }
-                ipMap.put(item.getStatus().getPodIP(), 
createServiceMetaInfo(item.getMetadata()));
-            }
-            LOGGER.info("Load {} pods in {}ms", ipMap.size(), 
(System.nanoTime() - startTime) / 1_000_000);
-            ipServiceMap.set(ipMap);
-        } catch (Throwable th) {
-            LOGGER.error("run load pod error", th);
-        }
-    }
-
-    private ServiceMetaInfo createServiceMetaInfo(final V1ObjectMeta podMeta) {
-        ExtensionsV1beta1Api extensionsApi = new ExtensionsV1beta1Api();
-        DependencyResource dr = new DependencyResource(podMeta);
-        DependencyResource meta = dr.getOwnerResource(
-            "ReplicaSet", ownerReference -> 
extensionsApi.readNamespacedReplicaSet(
-                ownerReference
-                    .getName(), podMeta.getNamespace(), "", true, true)
-                                                         .getMetadata());
-        ServiceMetaInfo result = new ServiceMetaInfo();
-        if (meta.getMetadata().getOwnerReferences() != null && 
meta.getMetadata().getOwnerReferences().size() > 0) {
-            V1OwnerReference owner = 
meta.getMetadata().getOwnerReferences().get(0);
-            result.setServiceName(String.format("%s.%s", owner.getName(), 
meta.getMetadata().getNamespace()));
-        } else {
-            result.setServiceName(String.format("%s.%s", 
meta.getMetadata().getName(), meta.getMetadata()
-                                                                               
            .getNamespace()));
-        }
-        result.setServiceInstanceName(String.format("%s.%s", 
podMeta.getName(), podMeta.getNamespace()));
-        result.setTags(transformLabelsToTags(podMeta.getLabels()));
-        return result;
-    }
-
-    private List<ServiceMetaInfo.KeyValue> transformLabelsToTags(final 
Map<String, String> labels) {
-        if (labels == null || labels.size() < 1) {
-            return Collections.emptyList();
-        }
-        List<ServiceMetaInfo.KeyValue> result = new ArrayList<>(labels.size());
-        for (Map.Entry<String, String> each : labels.entrySet()) {
-            result.add(new ServiceMetaInfo.KeyValue(each.getKey(), 
each.getValue()));
-        }
-        return result;
+        serviceRegistry = new K8SServiceRegistry();
+        serviceRegistry.start();
     }
 
     @Override
     public List<Source> analysis(StreamAccessLogsMessage.Identifier 
identifier, HTTPAccessLogEntry entry, Role role) {
-        if (invalidPodList()) {
+        if (serviceRegistry.isEmpty()) {
             return Collections.emptyList();
         }
         switch (role) {
@@ -209,95 +114,74 @@ public class K8sALSServiceMeshHTTPAnalysis implements 
ALSHTTPAnalysis {
                 boolean status = responseCode >= 200 && responseCode < 400;
 
                 Address downstreamRemoteAddress = 
properties.getDownstreamRemoteAddress();
-                ServiceMetaInfo downstreamService = find(
-                    downstreamRemoteAddress.getSocketAddress()
-                                           .getAddress(), 
downstreamRemoteAddress.getSocketAddress()
-                                                                               
  .getPortValue());
+                ServiceMetaInfo downstreamService = 
find(downstreamRemoteAddress.getSocketAddress().getAddress());
                 Address downstreamLocalAddress = 
properties.getDownstreamLocalAddress();
-                ServiceMetaInfo localService = find(
-                    downstreamLocalAddress.getSocketAddress()
-                                          .getAddress(), 
downstreamLocalAddress.getSocketAddress()
-                                                                               
.getPortValue());
+                ServiceMetaInfo localService = 
find(downstreamLocalAddress.getSocketAddress().getAddress());
                 String tlsMode = parseTLS(properties.getTlsProperties());
+
+                ServiceMeshMetric.Builder metric = null;
                 if (cluster.startsWith("inbound|")) {
                     // Server side
                     if (downstreamService.equals(ServiceMetaInfo.UNKNOWN)) {
                         // Ingress -> sidecar(server side)
                         // Mesh telemetry without source, the relation would 
be generated.
-                        ServiceMeshMetric.Builder metric = 
ServiceMeshMetric.newBuilder()
-                                                                            
.setStartTime(startTime)
-                                                                            
.setEndTime(startTime + duration)
-                                                                            
.setDestServiceName(
-                                                                               
 localService.getServiceName())
-                                                                            
.setDestServiceInstance(
-                                                                               
 localService.getServiceInstanceName())
-                                                                            
.setEndpoint(endpoint)
-                                                                            
.setLatency((int) duration)
-                                                                            
.setResponseCode(
-                                                                               
 Math.toIntExact(responseCode))
-                                                                            
.setStatus(status)
-                                                                            
.setProtocol(protocol)
-                                                                            
.setTlsMode(tlsMode)
-                                                                            
.setDetectPoint(DetectPoint.server);
-
-                        LOGGER.debug("Transformed ingress->sidecar inbound 
mesh metric {}", metric);
-                        forward(metric);
+                        metric = ServiceMeshMetric.newBuilder()
+                                                  .setStartTime(startTime)
+                                                  .setEndTime(startTime + 
duration)
+                                                  
.setDestServiceName(localService.getServiceName())
+                                                  
.setDestServiceInstance(localService.getServiceInstanceName())
+                                                  .setEndpoint(endpoint)
+                                                  .setLatency((int) duration)
+                                                  
.setResponseCode(Math.toIntExact(responseCode))
+                                                  .setStatus(status)
+                                                  .setProtocol(protocol)
+                                                  .setTlsMode(tlsMode)
+                                                  
.setDetectPoint(DetectPoint.server);
+
+                        log.debug("Transformed ingress->sidecar inbound mesh 
metric {}", metric);
                     } else {
                         // sidecar -> sidecar(server side)
-                        ServiceMeshMetric.Builder metric = 
ServiceMeshMetric.newBuilder()
-                                                                            
.setStartTime(startTime)
-                                                                            
.setEndTime(startTime + duration)
-                                                                            
.setSourceServiceName(
-                                                                               
 downstreamService.getServiceName())
-                                                                            
.setSourceServiceInstance(
-                                                                               
 downstreamService.getServiceInstanceName())
-                                                                            
.setDestServiceName(
-                                                                               
 localService.getServiceName())
-                                                                            
.setDestServiceInstance(
-                                                                               
 localService.getServiceInstanceName())
-                                                                            
.setEndpoint(endpoint)
-                                                                            
.setLatency((int) duration)
-                                                                            
.setResponseCode(
-                                                                               
 Math.toIntExact(responseCode))
-                                                                            
.setStatus(status)
-                                                                            
.setProtocol(protocol)
-                                                                            
.setTlsMode(tlsMode)
-                                                                            
.setDetectPoint(DetectPoint.server);
-
-                        LOGGER.debug("Transformed sidecar->sidecar(server 
side) inbound mesh metric {}", metric);
-                        forward(metric);
+                        metric = ServiceMeshMetric.newBuilder()
+                                                  .setStartTime(startTime)
+                                                  .setEndTime(startTime + 
duration)
+                                                  
.setSourceServiceName(downstreamService.getServiceName())
+                                                  
.setSourceServiceInstance(downstreamService.getServiceInstanceName())
+                                                  
.setDestServiceName(localService.getServiceName())
+                                                  
.setDestServiceInstance(localService.getServiceInstanceName())
+                                                  .setEndpoint(endpoint)
+                                                  .setLatency((int) duration)
+                                                  
.setResponseCode(Math.toIntExact(responseCode))
+                                                  .setStatus(status)
+                                                  .setProtocol(protocol)
+                                                  .setTlsMode(tlsMode)
+                                                  
.setDetectPoint(DetectPoint.server);
+
+                        log.debug("Transformed sidecar->sidecar(server side) 
inbound mesh metric {}", metric);
                     }
                 } else if (cluster.startsWith("outbound|")) {
                     // sidecar(client side) -> sidecar
                     Address upstreamRemoteAddress = 
properties.getUpstreamRemoteAddress();
-                    ServiceMetaInfo destService = find(
-                        upstreamRemoteAddress.getSocketAddress()
-                                             .getAddress(), 
upstreamRemoteAddress.getSocketAddress()
-                                                                               
  .getPortValue());
-
-                    ServiceMeshMetric.Builder metric = 
ServiceMeshMetric.newBuilder()
-                                                                        
.setStartTime(startTime)
-                                                                        
.setEndTime(startTime + duration)
-                                                                        
.setSourceServiceName(
-                                                                            
downstreamService.getServiceName())
-                                                                        
.setSourceServiceInstance(
-                                                                            
downstreamService.getServiceInstanceName())
-                                                                        
.setDestServiceName(
-                                                                            
destService.getServiceName())
-                                                                        
.setDestServiceInstance(
-                                                                            
destService.getServiceInstanceName())
-                                                                        
.setEndpoint(endpoint)
-                                                                        
.setLatency((int) duration)
-                                                                        
.setResponseCode(Math.toIntExact(responseCode))
-                                                                        
.setStatus(status)
-                                                                        
.setProtocol(protocol)
-                                                                        
.setTlsMode(tlsMode)
-                                                                        
.setDetectPoint(DetectPoint.client);
-
-                    LOGGER.debug("Transformed sidecar->sidecar(server side) 
inbound mesh metric {}", metric);
-                    forward(metric);
-
+                    ServiceMetaInfo destService = 
find(upstreamRemoteAddress.getSocketAddress().getAddress());
+
+                    metric = ServiceMeshMetric.newBuilder()
+                                              .setStartTime(startTime)
+                                              .setEndTime(startTime + duration)
+                                              
.setSourceServiceName(downstreamService.getServiceName())
+                                              
.setSourceServiceInstance(downstreamService.getServiceInstanceName())
+                                              
.setDestServiceName(destService.getServiceName())
+                                              
.setDestServiceInstance(destService.getServiceInstanceName())
+                                              .setEndpoint(endpoint)
+                                              .setLatency((int) duration)
+                                              
.setResponseCode(Math.toIntExact(responseCode))
+                                              .setStatus(status)
+                                              .setProtocol(protocol)
+                                              .setTlsMode(tlsMode)
+                                              
.setDetectPoint(DetectPoint.client);
+
+                    log.debug("Transformed sidecar->sidecar(server side) 
inbound mesh metric {}", metric);
                 }
+
+                Optional.ofNullable(metric).ifPresent(this::forward);
             }
         }
         return sources;
@@ -308,11 +192,11 @@ public class K8sALSServiceMeshHTTPAnalysis implements 
ALSHTTPAnalysis {
             return NON_TLS;
         }
         if 
(Strings.isNullOrEmpty(Optional.ofNullable(properties.getLocalCertificateProperties())
-            
.orElse(TLSProperties.CertificateProperties.newBuilder().build()).getSubject()))
 {
+                                          
.orElse(TLSProperties.CertificateProperties.newBuilder().build()).getSubject()))
 {
             return NON_TLS;
         }
         if 
(Strings.isNullOrEmpty(Optional.ofNullable(properties.getPeerCertificateProperties())
-            
.orElse(TLSProperties.CertificateProperties.newBuilder().build()).getSubject()))
 {
+                                          
.orElse(TLSProperties.CertificateProperties.newBuilder().build()).getSubject()))
 {
             return TLS;
         }
         return M_TLS;
@@ -326,14 +210,10 @@ public class K8sALSServiceMeshHTTPAnalysis implements 
ALSHTTPAnalysis {
             Address upstreamRemoteAddress = 
properties.getUpstreamRemoteAddress();
             if (downstreamLocalAddress != null && downstreamRemoteAddress != 
null && upstreamRemoteAddress != null) {
                 SocketAddress downstreamRemoteAddressSocketAddress = 
downstreamRemoteAddress.getSocketAddress();
-                ServiceMetaInfo outside = find(
-                    downstreamRemoteAddressSocketAddress.getAddress(), 
downstreamRemoteAddressSocketAddress
-                        .getPortValue());
+                ServiceMetaInfo outside = 
find(downstreamRemoteAddressSocketAddress.getAddress());
 
                 SocketAddress downstreamLocalAddressSocketAddress = 
downstreamLocalAddress.getSocketAddress();
-                ServiceMetaInfo ingress = find(
-                    downstreamLocalAddressSocketAddress.getAddress(), 
downstreamLocalAddressSocketAddress
-                        .getPortValue());
+                ServiceMetaInfo ingress = 
find(downstreamLocalAddressSocketAddress.getAddress());
 
                 long startTime = formatAsLong(properties.getStartTime());
                 long duration = 
formatAsLong(properties.getTimeToLastDownstreamTxByte());
@@ -375,13 +255,11 @@ public class K8sALSServiceMeshHTTPAnalysis implements 
ALSHTTPAnalysis {
                                                                     
.setTlsMode(tlsMode)
                                                                     
.setDetectPoint(DetectPoint.server);
 
-                LOGGER.debug("Transformed ingress inbound mesh metric {}", 
metric);
+                log.debug("Transformed ingress inbound mesh metric {}", 
metric);
                 forward(metric);
 
                 SocketAddress upstreamRemoteAddressSocketAddress = 
upstreamRemoteAddress.getSocketAddress();
-                ServiceMetaInfo targetService = find(
-                    upstreamRemoteAddressSocketAddress.getAddress(), 
upstreamRemoteAddressSocketAddress
-                        .getPortValue());
+                ServiceMetaInfo targetService = 
find(upstreamRemoteAddressSocketAddress.getAddress());
 
                 long outboundStartTime = startTime + 
formatAsLong(properties.getTimeToFirstUpstreamTxByte());
                 long outboundEndTime = startTime + 
formatAsLong(properties.getTimeToLastUpstreamRxByte());
@@ -409,7 +287,7 @@ public class K8sALSServiceMeshHTTPAnalysis implements 
ALSHTTPAnalysis {
                                                                             
.setTlsMode(NON_TLS)
                                                                             
.setDetectPoint(DetectPoint.client);
 
-                LOGGER.debug("Transformed ingress outbound mesh metric {}", 
outboundMetric);
+                log.debug("Transformed ingress outbound mesh metric {}", 
outboundMetric);
                 forward(outboundMetric);
             }
         }
@@ -435,17 +313,8 @@ public class K8sALSServiceMeshHTTPAnalysis implements 
ALSHTTPAnalysis {
     /**
      * @return found service info, or {@link ServiceMetaInfo#UNKNOWN} to 
represent not found.
      */
-    protected ServiceMetaInfo find(String ip, int port) {
-        Map<String, ServiceMetaInfo> map = ipServiceMap.get();
-        if (map == null) {
-            LOGGER.debug("Unknown ip {}, ip -> service is null", ip);
-            return ServiceMetaInfo.UNKNOWN;
-        }
-        if (map.containsKey(ip)) {
-            return map.get(ip);
-        }
-        LOGGER.debug("Unknown ip {}, ip -> service is {}", ip, map);
-        return ServiceMetaInfo.UNKNOWN;
+    protected ServiceMetaInfo find(String ip) {
+        return serviceRegistry.findService(ip);
     }
 
     protected void forward(ServiceMeshMetric.Builder metric) {
diff --git 
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ServiceMetaInfo.java
 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ServiceMetaInfo.java
index 41ba0e5..c449c2f 100644
--- 
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ServiceMetaInfo.java
+++ 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/als/ServiceMetaInfo.java
@@ -25,6 +25,8 @@ import lombok.RequiredArgsConstructor;
 import lombok.Setter;
 import lombok.ToString;
 
+import static java.util.Objects.nonNull;
+
 @Getter
 @Setter
 @ToString
@@ -41,6 +43,13 @@ public class ServiceMetaInfo {
         this.serviceInstanceName = serviceInstanceName;
     }
 
+    /**
+     * @return {@code true} if this object is completely constructed, 
otherwise {@code false}.
+     */
+    public boolean isComplete() {
+        return nonNull(serviceName) && nonNull(serviceInstanceName);
+    }
+
     @Setter
     @Getter
     @RequiredArgsConstructor
diff --git 
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sHTTPAnalysisTest.java
 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sHTTPAnalysisTest.java
index e6c797f..dea5f70 100644
--- 
a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sHTTPAnalysisTest.java
+++ 
b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/envoy/als/K8sHTTPAnalysisTest.java
@@ -18,7 +18,6 @@
 
 package org.apache.skywalking.oap.server.receiver.envoy.als;
 
-import com.google.common.collect.ImmutableMap;
 import com.google.protobuf.util.JsonFormat;
 import io.envoyproxy.envoy.service.accesslog.v2.StreamAccessLogsMessage;
 import java.io.IOException;
@@ -34,6 +33,10 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 public class K8sHTTPAnalysisTest {
 
     private MockK8sAnalysis analysis;
@@ -147,12 +150,12 @@ public class K8sHTTPAnalysisTest {
 
         @Override
         public void init(EnvoyMetricReceiverConfig config) {
-            getIpServiceMap().set(
-                ImmutableMap.of("10.44.2.56", new ServiceMetaInfo("ingress", 
"ingress-Inst"), "10.44.2.54",
-                                new ServiceMetaInfo("productpage", 
"productpage-Inst"), "10.44.6.66",
-                                new ServiceMetaInfo("detail", "detail-Inst"), 
"10.44.2.55",
-                                new ServiceMetaInfo("review", "detail-Inst")
-                ));
+            serviceRegistry = mock(K8SServiceRegistry.class);
+            
when(serviceRegistry.findService(anyString())).thenReturn(ServiceMetaInfo.UNKNOWN);
+            when(serviceRegistry.findService("10.44.2.56")).thenReturn(new 
ServiceMetaInfo("ingress", "ingress-Inst"));
+            when(serviceRegistry.findService("10.44.2.54")).thenReturn(new 
ServiceMetaInfo("productpage", "productpage-Inst"));
+            when(serviceRegistry.findService("10.44.6.66")).thenReturn(new 
ServiceMetaInfo("detail", "detail-Inst"));
+            when(serviceRegistry.findService("10.44.2.55")).thenReturn(new 
ServiceMetaInfo("review", "detail-Inst"));
         }
 
         @Override
diff --git a/test/e2e-mesh/e2e-istio/scripts/istio.sh 
b/test/e2e-mesh/e2e-istio/scripts/istio.sh
index ffd432c..2578818 100644
--- a/test/e2e-mesh/e2e-istio/scripts/istio.sh
+++ b/test/e2e-mesh/e2e-istio/scripts/istio.sh
@@ -21,7 +21,6 @@
 
 set -ex
 
-curl -L https://istio.io/downloadIstio | sh -
-sudo mv $PWD/istio-$ISTIO_VERSION/bin/istioctl /usr/local/bin/
+istioctl version || (curl -L https://istio.io/downloadIstio | sh - && sudo mv 
$PWD/istio-$ISTIO_VERSION/bin/istioctl /usr/local/bin/)
 istioctl install $@
 kubectl label namespace default istio-injection=enabled
diff --git 
a/test/e2e/e2e-common/src/main/java/org/apache/skywalking/e2e/retryable/RetryableTest.java
 
b/test/e2e/e2e-common/src/main/java/org/apache/skywalking/e2e/retryable/RetryableTest.java
index 0dc440a..f6218c8 100644
--- 
a/test/e2e/e2e-common/src/main/java/org/apache/skywalking/e2e/retryable/RetryableTest.java
+++ 
b/test/e2e/e2e-common/src/main/java/org/apache/skywalking/e2e/retryable/RetryableTest.java
@@ -49,10 +49,10 @@ public @interface RetryableTest {
     /**
      * @return maximum times to retry, or -1 for infinite retries. {@code -1} 
by default.
      */
-    int value() default 300;
+    int value() default 120;
 
     /**
      * @return the interval between any two retries, in millisecond. {@code 
1000} by default.
      */
-    long interval() default 1000;
+    long interval() default 10000;
 }
diff --git 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/mesh/ALSE2E.java 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/mesh/ALSE2E.java
index 3442ee1..eee567a 100644
--- a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/mesh/ALSE2E.java
+++ b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/mesh/ALSE2E.java
@@ -66,7 +66,7 @@ import static org.apache.skywalking.e2e.utils.Yamls.load;
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public class ALSE2E extends SkyWalkingTestAdapter {
     private final String swWebappHost = 
Optional.ofNullable(Strings.emptyToNull(System.getenv("WEBAPP_HOST"))).orElse("127.0.0.1");
-    private final String swWebappPort = 
Optional.ofNullable(Strings.emptyToNull(System.getenv("WEBAPP_PORT"))).orElse("8080");
+    private final String swWebappPort = 
Optional.ofNullable(Strings.emptyToNull(System.getenv("WEBAPP_PORT"))).orElse("12800");
     protected HostAndPort swWebappHostPort = HostAndPort.builder()
                                                         .host(swWebappHost)
                                                         
.port(Integer.parseInt(swWebappPort))
diff --git a/test/e2e/e2e-test/src/test/resources/expected/als/services.yml 
b/test/e2e/e2e-test/src/test/resources/expected/als/services.yml
index bd79611..006a060 100644
--- a/test/e2e/e2e-test/src/test/resources/expected/als/services.yml
+++ b/test/e2e/e2e-test/src/test/resources/expected/als/services.yml
@@ -15,16 +15,12 @@
 
 services:
   - key: not null
-    label: re(ratings-v1.*)
+    label: re(ratings.*)
   - key: not null
-    label: re(reviews-v1.*)
+    label: re(reviews.*)
   - key: not null
-    label: re(reviews-v2.*)
+    label: re(productpage.*)
   - key: not null
-    label: re(reviews-v3.*)
-  - key: not null
-    label: re(productpage-v1.*)
-  - key: not null
-    label: re(details-v1.*)
+    label: re(details.*)
   - key: not null
     label: re(istio-ingressgateway.*)

Reply via email to