随机算法简单可行,但不够均衡,在极端情况下会造成一台服务器一直收到请求,另一个服务器一直没收到请求。所以这时候就需要轮询算法。通过依次按顺序调用服务器列表中的服务器即可。例如服务器列表中有ABC三台服务器,一个自增数字,每次自增完取3的余数,0的话取服务器A,1的话取服务器B,2的话取服务器C即可。

    1. public class RandomRobin {
    2. private static AtomicInteger index = new AtomicInteger(0);
    3. public static String getServer(){
    4. ArrayList<String> serverList = new ArrayList<>(ServerIps.LIST);
    5. if (index.get() >= serverList.size()) {
    6. index.set(0);
    7. }
    8. return serverList.get(index.getAndIncrement());
    9. }
    10. public static void main(String[] args) {
    11. for (int i = 0; i < 10; i++) {
    12. System.out.println(getServer());
    13. }
    14. }
    15. }

    image.png
    缺点:循环的时间复杂度是O(n),性能浪费。
    多线程情况:

    1. public class RandomRobin {
    2. private static AtomicInteger index = new AtomicInteger(0);
    3. static ReentrantLock lock = new ReentrantLock();
    4. private static ArrayList<String> serverList = new ArrayList<>(ServerIps.LIST);
    5. public static String getServer() {
    6. if (index.get() >= serverList.size()) {
    7. index.set(0);
    8. }
    9. return serverList.get(index.getAndIncrement());
    10. }
    11. public static void main(String[] args) {
    12. CountDownLatch count = new CountDownLatch(5);
    13. CyclicBarrier barrier = new CyclicBarrier(5);
    14. ExecutorService pool = Executors.newFixedThreadPool(5);
    15. for (int i = 0; i < 100; i++) {
    16. pool.execute(() -> {
    17. try {
    18. barrier.await();
    19. lock.lock();
    20. System.out.println("线程" + Thread.currentThread().getName() + "开始执行");
    21. System.out.println(getServer());
    22. } catch (InterruptedException e) {
    23. e.printStackTrace();
    24. } catch (BrokenBarrierException e) {
    25. e.printStackTrace();
    26. } finally {
    27. lock.unlock();
    28. count.countDown();
    29. }
    30. });
    31. }
    32. try {
    33. count.await();
    34. } catch (InterruptedException e) {
    35. e.printStackTrace();
    36. }
    37. pool.shutdown();
    38. }
    39. }