面试题目

本文最后更新于:1 个月前

使用url实现访问一个非80端口的服务

Nginx实现代理转发

面试官问了一个问题,如何,当时靠着感觉说了nginx的反向代理的实现,后面查询了实现方法,nginx确实可以实现这个功能。

实现也很简单,配置一个ngnix的转发功能即可

server {
    listen       80;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    location / {
        proxy_pass http://localhost:8099/;
    }
}

Nginx实现反向代理

主要配置为upstream字段,其中配置了已经部署的服务器地址,默认的负载均衡规则是轮询,也可以配置为根据权重分配访问,还有IP_Hash规则。

upstream myservice {
    server 127.0.0.1:8081;
    server 127.0.0.1:8083;
    # server 127.0.0.1:8847;
}

server {
    listen       80;
    server_name  localhost;

    location / {
    proxy_pass http://myservice;
}

限流算法–保证api每秒钟只能被访问10次

可以使用令牌桶算法实现

  • 令牌的生成:系统以固定的速率向令牌桶中添加令牌
  • 令牌的消耗:每个传入的请求或操作需要从令牌桶中取出一个令牌才能继续执行。如果桶中没有令牌,则请求必须等待直到桶中有可用的令牌
  • 令牌的限制:令牌桶中的数量不能超过10个,保证任何时间传输的峰值速率不会超出预设的上限
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class RateLimiter {
    private Semaphore semaphore;
    private int maxPermits;
    private TimeUnit timePeriod;
    private long rateLimitRefreshPeriod;
    private long lastRefreshTime;

    public RateLimiter(int maxPermits, TimeUnit timePeriod) {
        // 信号量
        this.semaphore = new Semaphore(maxPermits);
        // 单位时间内的最大访问次数
        this.maxPermits = maxPermits;
        // 时间单位
        this.timePeriod = timePeriod;
        // 刷新的周期1s
        this.rateLimitRefreshPeriod = timePeriod.toMillis(1);
        this.lastRefreshTime = System.currentTimeMillis();
    }

    public boolean tryAcquire() {
        refreshPermits();
        return semaphore.tryAcquire();
    }

    private synchronized void refreshPermits() {
        long now = System.currentTimeMillis();
        // 如果当前时间与最后更新时间间隔超过了刷新周期,则向令牌桶中添加令牌
        if (now - lastRefreshTime > rateLimitRefreshPeriod) {
            // 向令牌桶中添加新的令牌
            semaphore.release(maxPermits - semaphore.availablePermits());
            // 更新最后的刷新时间
            lastRefreshTime = now;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        RateLimiter rateLimiter = new RateLimiter(10, TimeUnit.SECONDS);

        // 模拟请求
        for (int i = 0; i < 100; i++) {
            if (rateLimiter.tryAcquire()) {
                System.out.println("Request " + i + " is allowed at " + System.currentTimeMillis());
            } else {
                System.out.println("Request " + i + " is denied at " + System.currentTimeMillis());
            }
            Thread.sleep(50); // 模拟请求间隔时间
        }
    }
}
0请求成功, 剩余令牌数量9 当前时间:17136816448491请求成功, 剩余令牌数量8 当前时间:17136816449042请求成功, 剩余令牌数量7 当前时间:17136816449673请求成功, 剩余令牌数量6 当前时间:17136816450304请求成功, 剩余令牌数量5 当前时间:17136816450925请求成功, 剩余令牌数量4 当前时间:17136816451546请求成功, 剩余令牌数量3 当前时间:17136816452177请求成功, 剩余令牌数量2 当前时间:17136816452798请求成功, 剩余令牌数量1 当前时间:17136816453419请求成功, 剩余令牌数量0 当前时间:171368164540410请求失败, 剩余令牌数量0 当前时间:171368164546511请求失败, 剩余令牌数量0 当前时间:171368164552712请求失败, 剩余令牌数量0 当前时间:171368164559113请求失败, 剩余令牌数量0 当前时间:171368164565314请求失败, 剩余令牌数量0 当前时间:171368164571415请求失败, 剩余令牌数量0 当前时间:171368164577616请求失败, 剩余令牌数量0 当前时间:171368164583717请求成功, 剩余令牌数量9 当前时间:171368164589918请求成功, 剩余令牌数量8 当前时间:171368164596219请求成功, 剩余令牌数量7 当前时间:171368164602420请求成功, 剩余令牌数量6 当前时间:171368164608621请求成功, 剩余令牌数量5 当前时间:171368164614922请求成功, 剩余令牌数量4 当前时间:171368164621123请求成功, 剩余令牌数量3 当前时间:171368164627424请求成功, 剩余令牌数量2 当前时间:171368164633625请求成功, 剩余令牌数量1 当前时间:171368164639826请求成功, 剩余令牌数量0 当前时间:1713681646461

从打印的日志可以看到,实现了每秒钟只能访问10次的限制


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

 目录

Copyright © 2020 my blog
载入天数... 载入时分秒...