1200ms到250ms

毕业工作半年以来,这是我的第一篇博客,为时不晚。
Times were Good。
一直在选取博客的主题应该写些什么,犹豫许久, 毕竟活在当下,每天大部分时间都是在工作中度过,也只能写一些工作中所遇到的琐事了。

(1200ms -> 250ms)
这周排期的时候接了一个简历投递落地页改版需求,效果大概是这样:
原来的页面:

新的页面:

当时评审的时候觉得没有什么需要注意的点,跟产品们简单对了下就开始设计开发了。(^_-)
两天之后,自信满满的拿着刚开发的项目部署到沙箱上进行测试,看返回的数据没什么问题,但总感觉请求速度有点慢,F12打开一看,F5了无数次发现平均请求时间竟然高达1.2s。对于一个平均响应时间在250ms的集群来说这肯定是不能接受的。o(╥﹏╥)o
于是乎,浏览了下整个代码,心里一凉,一个请求调用了总计有32次服务,这能不慢吗?
简单架构图:

由于一次请求要批量获取10条数据,并且10条数据的属性需要通过三个不同的业务线获取,导致网络I/O繁多。
最开始的设计(根据上图):
站点循环调用代理服务中方法获取每一条属性,代理服务接口再调用其他业务线的服务,当需要循环调用三个其他业务线的服务时,这种方式网络I/O数为: ( 10(站点->代理服务) + 10(代理服务->其他业务线服务)) * 3 = 60(次),网络开销非常大,导致接口响应时间基本在1200ms以上。
第一步优化:
*在代理服务中加缓存(通过redis实现),由于获取的数据内容更新不是很频繁,加入了缓存之后,缓存命中率很高,在(10(代理服务->其他业务线服务))这一项上有较大的改进,基本可以抵消掉这一部分的网络开销。响应时间:1200ms+ -> 1000ms
第二步优化:
*在代理服务中新增批量查询接口,在(10(站点->代理服务))这一项上将10这个常量转化为了1,公式转化为:(站点->代理服务 + 10(代理服务->其他业务线服务) (有缓存)) * 3。进一步减少了网络开销,响应时间:1000ms -> 800ms
第三步优化:
*在站点层使用多线程(threadpool + countdownlatch + 策略模式),在调用服务查询数据时,由于数据存储在不同的业务线上,不会存在线程查询不一致的情况,响应时间公式得到最终转化:(站点->代理服务 + 10(代理服务->其他业务线服务) (有缓存))* 1, 第二个10已经向相关业务线的同学提了建议,增加批量接口,响应时间:800ms -> 250ms。
最终的效果:

回顾整个优化过程,其中优化的最明显的就在最后一步,所以最后写了个 (threadpool + countdownlatch + 策略模式)demo:
CountDownLatchTest类:
public class CountDownLatchTest {

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
        CountDownLatch countDownLatch = new CountDownLatch(3);

        ServiceWorker workerForCateName = new ServiceWorker(new HashSet<String>(), new CateNameStrategy(), countDownLatch);
        ServiceWorker workerForCityName = new ServiceWorker(new HashSet<String>(), new CityNameStrategy(), countDownLatch);
        ServiceWorker workerForFirstCate = new ServiceWorker(new HashSet<String>(), new FirstCateStrategy(), countDownLatch);

        executor.execute(workerForCateName);
        executor.execute(workerForCityName);
        executor.execute(workerForFirstCate);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(workerForCateName.getResultMap().get("CateName") + "," + workerForCityName.getResultMap().get("CityName")
                + "," + workerForFirstCate.getResultMap().get("FirstCate"));
    }
}
ServiceWorker类:
class ServiceWorker implements Runnable {
    //批量处理set
    private Set<String> set;
    //持有一个具体的策略对象
    private ServiceStrategy strategy;
    //结果集
    private Map<String, String> resultMap;
    //latch
    private CountDownLatch latch;

    public ServiceWorker(Set<String> set, ServiceStrategy strategy, CountDownLatch latch) {
        this.set = set;
        this.strategy = strategy;
        this.latch = latch;
    }

    public Map<String, String> getResultMap() {
        return resultMap;
    }

    @Override
    public void run() {
        try {
            this.resultMap = strategy.choiceService(set);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            latch.countDown();
        }
    }
}
ServiceStrategy类:
public interface ServiceStrategy {
    Map<String, String> choiceService(Set<String> set) throws Exception;
}
具体实现类 CateNameStrategy、CityNameStrategy、FirstCateStrategy实现接口方法调用相应的服务即可。
对于上面所说的ThreadPool、CountDownLatch、策略模式可以查看我博客中其他转载的一些好文~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值