All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hippo4j.springboot.starter.remote.ServerListManager Maven / Gradle / Ivy

There is a newer version: 1.5.0
Show newest version
/*
 * 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 cn.hippo4j.springboot.starter.remote;

import cn.hippo4j.springboot.starter.config.BootstrapProperties;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * Server list manager.
 *
 * @author chen.ma
 * @date 2021/6/23 20:42
 */
@Slf4j
public class ServerListManager {

    private static final String HTTPS = "https://";

    private static final String HTTP = "http://";

    private String serverAddrsStr;

    @Getter
    volatile List serverUrls = new ArrayList();

    private volatile String currentServerAddr;

    private Iterator iterator;

    private final BootstrapProperties properties;

    public ServerListManager(BootstrapProperties dynamicThreadPoolProperties) {
        this.properties = dynamicThreadPoolProperties;
        serverAddrsStr = properties.getServerAddr();
        if (!StringUtils.isEmpty(serverAddrsStr)) {
            List serverAddrList = new ArrayList();
            String[] serverAddrListArr = this.serverAddrsStr.split(",");
            for (String serverAddr : serverAddrListArr) {
                boolean whetherJoint = StrUtil.isNotBlank(serverAddr)
                        && !serverAddr.startsWith(HTTPS) && !serverAddr.startsWith(HTTP);
                if (whetherJoint) {
                    serverAddr = HTTP + serverAddr;
                }
                currentServerAddr = serverAddr;
                serverAddrList.add(serverAddr);
            }
            this.serverUrls = serverAddrList;
        }
    }

    public String getCurrentServerAddr() {
        if (StringUtils.isEmpty(currentServerAddr)) {
            iterator = iterator();
            currentServerAddr = iterator.next();
        }
        return currentServerAddr;
    }

    Iterator iterator() {
        return new ServerAddressIterator(serverUrls);
    }

    private static class ServerAddressIterator implements Iterator {

        final List sorted;

        final Iterator iter;

        public ServerAddressIterator(List source) {
            sorted = new ArrayList();
            for (String address : source) {
                sorted.add(new RandomizedServerAddress(address));
            }
            Collections.sort(sorted);
            iter = sorted.iterator();
        }

        @Override
        public boolean hasNext() {
            return false;
        }

        @Override
        public String next() {
            return null;
        }

        static class RandomizedServerAddress implements Comparable {

            static Random random = new Random();

            String serverIp;

            int priority = 0;

            int seed;

            public RandomizedServerAddress(String ip) {
                try {
                    this.serverIp = ip;
                    /*
                     * change random scope from 32 to Integer.MAX_VALUE to fix load balance issue
                     */
                    this.seed = random.nextInt(Integer.MAX_VALUE);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public int compareTo(RandomizedServerAddress other) {
                if (this.priority != other.priority) {
                    return other.priority - this.priority;
                } else {
                    return other.seed - this.seed;
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy