Architecture

Rate Limit 限流

Submitted by Lizhe on Tue, 07/25/2017 - 12:22

如果你还记得12306网站那个著名的 "系统太忙请稍后再试"你一定遇到过限流

或者是jd的抢购活动的"服务器太忙请稍后再试" 都是限流的结果

限流的好处在于防止非预期的请求对系统压力过大而引起的系统崩溃

一般Web系统的访问限制都可以用容器本身来实现,比如tomcat就可以在connector上面配置connection数目的限制,servlet thread限制

不过如果不同的URL需要配置不同的限制, tomcat显然是做不到的

这个时候就需要实现自己的限制

 

常用的限流算法有两种   漏桶算法和令牌桶算法

 漏桶算法

请求会先进入一个漏桶里, 假设漏桶每分钟滴4滴水, 那么就有4个请求在这一分钟里被处理,如果水桶满了, 就意味着可以goto error page 了

关于"在用户设定的时间发送邮件"的功能设计

Submitted by Lizhe on Mon, 07/17/2017 - 17:23

这个问题其实还是Brian问的, 他真的去做那个 "拍卖系统" 了

这个拍卖系统有一个需求是  " 假设用户设定的拍卖开始时间是2017年1月1日中午12点, 那么系统需要在拍卖会开始之前半个小时给参与的bidder们发送提醒邮件"

这个功能看起来貌似很简单, 不过仔细想起来以前好像还真没碰到类似的

1. 发送邮件的job触发一次之后, 就会被移除 ( 不像springbatch或者crontab那种定时器触发, 要触发好多次)

2. job的数量不固定, 以前做的job都是程序员设定的, 不会由用户创建, 所以如果job数量特别大,可能会出问题

3. job的触发时间是用户设定的, 如果同一时间有大量job需要触发, 而且如果邮件发送特别慢的话,也可能会出问题

 

下面给出两个解决方案

  • 使用atd服务实现
  • 使用redis+rabbitmq写代码实现

总的来说各有利弊, 下面请看详细

 


第一种, 使用atd服务实现

安装atd服务
yum -y install at

如何快速构建开发原型

Submitted by Lizhe on Sat, 07/08/2017 - 14:27

Brian (还是稍不留神就能打成brain =。=) 的offer差不多到手了, 为了感谢我的技术支持拉着Roc和Maven 晚上小聚了一下

总的来说我还是非常喜欢他抛给我那两套题的 ( 额...如果这东西能算是题的话 ) , 基本就是个大学生的期末大作业

第一个项目我已经提过了 如何创建restful api

个人觉得第一个项目命题的面试官明显是想考察interviewee如何进行技术选型, 如何组织代码结构, 如何处理异常, 如何进行集成和发布

第二个项目是一个竞拍系统, 题目大概是这样的

我需要一个竞拍系统, 参与的角色有一些owner,bidder什么的, 被拍卖物品只有一种是钻石, owner需要知道当前的最高价, bidder需要知道自己的报价在第几名, 然后这些数据要实时刷新

这个命题是中午11点给出的,下午1点就要面试,打电话的时候Brian在北京, 他讲完需求以后就开始问我

你看我这样设计类行不行 ( 然后他开始巴拉巴拉的讲了一堆class Owner, class Bidder 什么的 )

如何创建restful api

Submitted by Lizhe on Fri, 06/16/2017 - 15:35

展开这一话题源自一个公司的笔试题 ( 我是帮朋友做的 ), 说实话头一次碰到这样出笔试题的

题目是6个基于json格式的 restful api , 大概是 创建好友关系, 删除, 加黑名单, 活得对应用户的好友之类, 功能都不难, 给1周时间, 但是希望自己控制在4个小时之内做完

标题也挺吓人 <Full Stack Engineer> , 一开始朋友说"全栈"的时候我还是觉得挺无聊的, 试问哪个干J2EE的程序员不是html,jsp,java,服务器都能糊弄几下, 还全什么栈, 全栈这个词可能就是php写多了才弄出来的, 然后我就开始了

好吧我的实际工作断断续续大约持续了10个小时, 几乎用了两天 , 这套题比较有趣, 我有点理解他的"全栈"了, 语言不限, python , ruby, go, java 随意, 框架不限, 用什么framework都可以, 服务器不限, 估计要是用php的 Nginx也行, 最后他要求把代码放在github上这样面试官就能看见你所有的提交版本,思路是怎么样的, 然后要求提供一个公有云服务器, 最好是用Makefile或者docker把服务发布出来,或者让他们可以 1-step command to run your API server locally

"缓存"问题

Submitted by Lizhe on Thu, 06/08/2017 - 10:27

 

cache everything you can

缓存 实际上仍然是一种通过 消耗硬件资源和存储空间 换取 运行速度的手段

通过将数据转移到高速载体或者预先完成初始化动作来保证程序运行期间的速度

  • 数据库连接池
  • 线程池
  • spring 对象容器

等都是缓存技术的一种实现

我们来看几种典型应用

1. 使用静态块或静态变量

想象一下你的"商城"应用中有一个<select>选项, 用于让用户选择商品类别, 这些类别可能几年都不会更新一次, 它们被存储在文件或者数据库中, 当用户打开页面时每次都从文件系统或数据加载一遍这些数据显然不合适

最简单的做法是通过 静态变量 , 静态变量的生命周期与class在类加载器中的生命周期是一样的,所以很难被回收掉, 这个对象会一直存储在java 堆中,也就构成了一个简单的构建在堆内存上的缓存

private static List<String> types = getTypes();

"重要性"问题

Submitted by Lizhe on Wed, 06/07/2017 - 10:07

 

当你尝试构建或者更新一个系统时, 你可能经常需要考虑哪些工作是最重要的

根据以往的经验, 框架选型, 数据库设计, 开发环境的搭建 都会让人觉得很重要, 实际不然

这里 "重要性" 的概念是指 " 修改成本最大, 维护成本最高, 一旦完成就几乎无法修改 " 的部分

一个功能,一个模块或者是一个定义好的API, 如果修改它的成本越高, 它的重要性就越大

上面提到的内容中 框架选型和数据库设计 几乎是最重要的 , 改动数据库表结构意味着之前的大量DAO层工作都要重新, 如果你尝试将一个Struts项目更换成springmvc, 那么意味着所有的controller代码都要推倒重来, 在开始设计和构建系统之前,一定要明确 什么才是你系统中 "最重要" 的部分

一般来说(个人意见)

重要的部分包括

  • framework的选型
  • 数据库设计
  • 使用的数据库类型
  • 代码的组织结构(是按照层划分还是按照模块划分)
  • BO和DAO层
  • 核心业务接口

 

相对重要的部分包括

Architecture

Submitted by Lizhe on Tue, 06/06/2017 - 23:37

今天被问到如何设计API , 说实话突然被这么问有点蒙圈

7年前老白总是告诉我

如果你要做一个junior developer, 你只需要知道 "怎么做" 就可以了, 但是如果要成为一个senior , 一定要知道 "为什么这么做"

后来有机会面试别人的时候也总是喜欢问candidate "你为什么要这么做" , 得到的好答案却寥寥无几

当你去问一个求职者, "什么是单例" , 有备而来的求职者会说得条条是道, 懒汉式 饿汉式 同步 私有构造器 都会脱口而出

然后当你再去问 "什么是对象的生命周期" 他也会给出很标准的答案

可惜的是, 当提到 " 你为什么要使用spring的ioc容器时 " , 很多candidate只是说, 就是这么用的, 项目里都在用...

实际上有些年轻人(其实也只比我年轻一点点甚至是同龄人)从来没有认真使用过servlet, 也没有使用过工厂, 甚至现在的科班出身的计算机系学生也不会再考虑Cpp语言为何需要析构函数了

他们关心的也许只是 "如何搭建SSH" 开发框架, 而从来不问自己 " 我为什么要使用spring "