apache / dubbo-admin

@@ -0,0 +1,170 @@
Loading
1 +
/*
2 +
 * Licensed to the Apache Software Foundation (ASF) under one or more
3 +
 * contributor license agreements.  See the NOTICE file distributed with
4 +
 * this work for additional information regarding copyright ownership.
5 +
 * The ASF licenses this file to You under the Apache License, Version 2.0
6 +
 * (the "License"); you may not use this file except in compliance with
7 +
 * the License.  You may obtain a copy of the License at
8 +
 *
9 +
 *     http://www.apache.org/licenses/LICENSE-2.0
10 +
 *
11 +
 * Unless required by applicable law or agreed to in writing, software
12 +
 * distributed under the License is distributed on an "AS IS" BASIS,
13 +
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 +
 * See the License for the specific language governing permissions and
15 +
 * limitations under the License.
16 +
 */
17 +
18 +
package org.apache.dubbo.admin.registry.mapping.impl;
19 +
20 +
import org.apache.dubbo.admin.registry.mapping.ServiceMapping;
21 +
import org.apache.dubbo.common.URL;
22 +
import org.apache.dubbo.common.logger.Logger;
23 +
import org.apache.dubbo.common.logger.LoggerFactory;
24 +
import org.apache.dubbo.common.utils.ConcurrentHashSet;
25 +
import org.apache.dubbo.common.utils.StringUtils;
26 +
import org.apache.dubbo.metadata.MappingChangedEvent;
27 +
import org.apache.dubbo.metadata.MappingListener;
28 +
import org.apache.dubbo.registry.nacos.NacosNamingServiceWrapper;
29 +
import org.apache.dubbo.registry.nacos.util.NacosNamingServiceUtils;
30 +
31 +
import com.alibaba.nacos.api.common.Constants;
32 +
import com.alibaba.nacos.api.exception.NacosException;
33 +
import com.alibaba.nacos.api.naming.pojo.ListView;
34 +
import com.google.common.collect.Sets;
35 +
36 +
import java.util.Arrays;
37 +
import java.util.HashSet;
38 +
import java.util.List;
39 +
import java.util.Set;
40 +
import java.util.concurrent.Executors;
41 +
import java.util.concurrent.ScheduledExecutorService;
42 +
import java.util.concurrent.TimeUnit;
43 +
44 +
import static com.alibaba.nacos.api.PropertyKeyConst.NAMING_LOAD_CACHE_AT_START;
45 +
import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY;
46 +
import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY;
47 +
import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY;
48 +
import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY;
49 +
50 +
/**
51 +
 * Nacos not support batch listen config feature. Therefore, regularly query the service list instead of notification
52 +
 */
53 +
public class NacosServiceMapping implements ServiceMapping {
54 +
55 +
    /**
56 +
     * All 2.x supported categories
57 +
     */
58 +
    private static final List<String> ALL_SUPPORTED_CATEGORIES = Arrays.asList(
59 +
            PROVIDERS_CATEGORY,
60 +
            CONSUMERS_CATEGORY,
61 +
            ROUTERS_CATEGORY,
62 +
            CONFIGURATORS_CATEGORY
63 +
    );
64 +
65 +
    /**
66 +
     * The separator for service name
67 +
     * Change a constant to be configurable, it's designed for Windows file name that is compatible with old
68 +
     * Nacos binary release(< 0.6.1)
69 +
     */
70 +
    private static final String SERVICE_NAME_SEPARATOR = System.getProperty("nacos.service.name.separator", ":");
71 +
72 +
    private static final long LOOKUP_INTERVAL = Long.getLong("nacos.service.names.lookup.interval", 30);
73 +
74 +
    private ScheduledExecutorService scheduledExecutorService;
75 +
76 +
    private final Set<MappingListener> listeners = new ConcurrentHashSet<>();
77 +
78 +
    private static final int PAGINATION_SIZE = 100;
79 +
80 +
    private NacosNamingServiceWrapper namingService;
81 +
82 +
    private Set<String> anyServices = new HashSet<>();
83 +
84 +
    private static final Logger LOGGER = LoggerFactory.getLogger(NacosServiceMapping.class);
85 +
86 +
    @Override
87 +
    public void init(URL url) {
88 +
        url.addParameter(NAMING_LOAD_CACHE_AT_START, "false");
89 +
        namingService = NacosNamingServiceUtils.createNamingService(url);
90 +
        scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
91 +
        listenerAll();
92 +
    }
93 +
94 +
    @Override
95 +
    public void listenerAll() {
96 +
97 +
        try {
98 +
            anyServices = getAllServiceNames();
99 +
        } catch (Exception e) {
100 +
            LOGGER.error("Get nacos all services fail ", e);
101 +
        }
102 +
        for (String service : anyServices) {
103 +
            notifyMappingChangedEvent(service);
104 +
        }
105 +
        scheduledExecutorService.scheduleAtFixedRate(() -> {
106 +
            try {
107 +
                Set<String> serviceNames = getAllServiceNames();
108 +
                for (String serviceName : serviceNames) {
109 +
                    if (anyServices.add(serviceName)) {
110 +
                        notifyMappingChangedEvent(serviceName);
111 +
                    }
112 +
                }
113 +
            } catch (Exception e) {
114 +
                LOGGER.error("Get nacos all services fail ", e);
115 +
            }
116 +
117 +
        }, LOOKUP_INTERVAL, LOOKUP_INTERVAL, TimeUnit.SECONDS);
118 +
    }
119 +
120 +
    private Set<String> getAllServiceNames() throws NacosException {
121 +
122 +
        Set<String> serviceNames = new HashSet<>();
123 +
        int pageIndex = 1;
124 +
        ListView<String> listView = namingService.getServicesOfServer(pageIndex, PAGINATION_SIZE,
125 +
                Constants.DEFAULT_GROUP);
126 +
        // First page data
127 +
        List<String> firstPageData = listView.getData();
128 +
        // Append first page into list
129 +
        serviceNames.addAll(firstPageData);
130 +
        // the total count
131 +
        int count = listView.getCount();
132 +
        // the number of pages
133 +
        int pageNumbers = count / PAGINATION_SIZE;
134 +
        int remainder = count % PAGINATION_SIZE;
135 +
        // remain
136 +
        if (remainder > 0) {
137 +
            pageNumbers += 1;
138 +
        }
139 +
        // If more than 1 page
140 +
        while (pageIndex < pageNumbers) {
141 +
            listView = namingService.getServicesOfServer(++pageIndex, PAGINATION_SIZE, Constants.DEFAULT_GROUP);
142 +
            serviceNames.addAll(listView.getData());
143 +
        }
144 +
145 +
        return serviceNames;
146 +
    }
147 +
148 +
    private void notifyMappingChangedEvent(String service) {
149 +
        if (StringUtils.isBlank(service)) {
150 +
            return;
151 +
        }
152 +
        for (String category : ALL_SUPPORTED_CATEGORIES) {
153 +
            String prefix = category + SERVICE_NAME_SEPARATOR;
154 +
            if (service.startsWith(prefix)) {
155 +
                return;
156 +
            }
157 +
        }
158 +
        MappingChangedEvent event = new MappingChangedEvent(null, Sets.newHashSet(service));
159 +
        for (MappingListener listener : listeners) {
160 +
            listener.onEvent(event);
161 +
        }
162 +
    }
163 +
164 +
165 +
    @Override
166 +
    public void addMappingListener(MappingListener listener) {
167 +
        listeners.add(listener);
168 +
    }
169 +
170 +
}

@@ -21,6 +21,7 @@
Loading
21 21
import org.apache.dubbo.admin.model.domain.RegistrySource;
22 22
import org.apache.dubbo.common.BaseServiceMetadata;
23 23
import org.apache.dubbo.common.URL;
24 +
import org.apache.dubbo.common.utils.StringUtils;
24 25
25 26
import java.util.ArrayList;
26 27
import java.util.HashMap;
@@ -52,7 +53,7 @@
Loading
52 53
        p.setHash(id);
53 54
        String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
54 55
        String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
55 -
        String service = BaseServiceMetadata.buildServiceKey(url.getServiceInterface(), group, version);
56 +
        String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version);
56 57
        p.setService(service);
57 58
        p.setAddress(url.getAddress());
58 59
        p.setApplication(url.getParameter(Constants.APPLICATION_KEY));
@@ -91,7 +92,7 @@
Loading
91 92
        c.setHash(id);
92 93
        String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
93 94
        String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
94 -
        String service = BaseServiceMetadata.buildServiceKey(url.getServiceInterface(), group, version);
95 +
        String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version);
95 96
        c.setService(service);
96 97
        c.setAddress(url.getHost());
97 98
        c.setApplication(url.getParameter(Constants.APPLICATION_KEY));
@@ -188,4 +189,13 @@
Loading
188 189
        }
189 190
        return null;
190 191
    }
192 +
193 +
    private static String getServiceInterface(URL url) {
194 +
        String serviceInterface = url.getServiceInterface();
195 +
        if (StringUtils.isBlank(serviceInterface) || Constants.ANY_VALUE.equals(serviceInterface)) {
196 +
            serviceInterface = url.getPath();
197 +
        }
198 +
        return serviceInterface;
199 +
    }
200 +
191 201
}

@@ -110,11 +110,11 @@
Loading
110 110
                    String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
111 111
                    // NOTE: group and version in empty protocol is *
112 112
                    if (!Constants.ANY_VALUE.equals(group) && !Constants.ANY_VALUE.equals(version)) {
113 -
                        services.remove(url.getServiceInterface());
113 +
                        services.remove(getServiceInterface(url));
114 114
                    } else {
115 115
                        for (Map.Entry<String, Map<String, URL>> serviceEntry : services.entrySet()) {
116 116
                            String service = serviceEntry.getKey();
117 -
                            if (Tool.getInterface(service).equals(url.getServiceInterface())
117 +
                            if (Tool.getInterface(service).equals(getServiceInterface(url))
118 118
                                    && (Constants.ANY_VALUE.equals(group) || StringUtils.isEquals(group, Tool.getGroup(service)))
119 119
                                    && (Constants.ANY_VALUE.equals(version) || StringUtils.isEquals(version, Tool.getVersion(service)))) {
120 120
                                services.remove(service);
@@ -124,7 +124,7 @@
Loading
124 124
                }
125 125
            } else {
126 126
                if (StringUtils.isEmpty(interfaceName)) {
127 -
                    interfaceName = url.getServiceInterface();
127 +
                    interfaceName = getServiceInterface(url);
128 128
                }
129 129
                Map<String, Map<String, URL>> services = categories.get(category);
130 130
                if (services == null) {
@@ -133,7 +133,7 @@
Loading
133 133
                }
134 134
                String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
135 135
                String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
136 -
                String service = BaseServiceMetadata.buildServiceKey(url.getServiceInterface(), group, version);
136 +
                String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version);
137 137
                Map<String, URL> ids = services.get(service);
138 138
                if (ids == null) {
139 139
                    ids = new HashMap<>();
@@ -170,5 +170,14 @@
Loading
170 170
            services.putAll(categoryEntry.getValue());
171 171
        }
172 172
    }
173 +
174 +
    private String getServiceInterface(URL url) {
175 +
        String serviceInterface = url.getServiceInterface();
176 +
        if (StringUtils.isBlank(serviceInterface) || Constants.ANY_VALUE.equals(serviceInterface)) {
177 +
            serviceInterface = url.getPath();
178 +
        }
179 +
        return serviceInterface;
180 +
    }
181 +
173 182
}
174 183
Files Complexity Coverage
dubbo-admin-server/src/main/java/org/apache/dubbo/admin 18.71% 20.82%
Project Totals (144 files) 18.71% 20.82%
Notifications are pending CI completion. Periodically Codecov will check the CI state, when complete notifications will be submitted. Push notifications now.

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading