从App业务逻辑中提炼API接口

  2.1 从App业务逻辑中提炼API接口
  
  业务逻辑思维导图
  
  功能-业务逻辑思维导图
  
  基本功能模块关系
  
  功能模块接口UML(设计出API)
  
  在设计稿标注API
  
  编写API文档
  
  2.2 设计API的要点
  
  根据对象设计API
  
  API的命名
  
  API的安全性
  
  API所返回的数据:禁止返回Null值
  
  图片的处理:图片数据库保存原图,在App客户端本地缓存图片不存在时,按图片尺寸向服务端请求动态生成。
  
  返回的提示信息:给用户看的提示和给程序员看的提示。
  
  在线API测试文档:使用Swagger-UI搭建,按TDD(测试驱动开发)原则进行开发。
  
  在App客户端启动时调用一个API获取必要的初始化信息:比如App版本
  
  关于API的版本升级问题:V2版本的API的Controller必须要继承V1版本的Controller,V2版本的API只重写需要改动的API。
  
  2.3 如何选择合适的数据库产品
  
  2.3.1 Redis、MongoDB、MySQL读写数据的区别
  
  Redis的数据是存放在服务器的内存,当内存用满了后需要扩容,就只能使用Redis的分布式方案。为了防止断电或Redis程序重启造成内容数据的丢失,可调整Redis配置文件,按照一定的策略把数据持久化传到硬盘。
  
  MongoDB同时使用了硬盘和内存,其使用了操作系统提供的MMAP(内存文件映射)机制进行数据文件的读写,MMAP可以把文件直接映射到进程的内存空间中,这样文件就会在内存中有对应的地址,这时对文件的读写是能通过操作内存进行的,而不需要使用传统的如fread、fwrite文件操作方式。
  
  MySQL的数据是放在硬盘中的。虽然MySQL也有缓存,但MySQL缓存的是查询的结果,而不是缓存数据。
  
  2.3.2 Redis、MongoDB、MySQL查找数据的区别
  
  Redis的数据是基于“键值对”存储。Redis查找数据,每次都是直奔目标,读写速度当然快。
  
  MongoDB和MySQL中查找数据,有两种模式:知道id或索引,不知道id或索引。前者直奔目标,效率高;后者逐个查找,效率低。
  
  2.3.3 Redis、MongoDB、MySQL适用场景
  
  Redis适用场景:读写频率高的数据、热点数据。
  
  MongoDB适用场景:网站数据(实时的插入、更新与查询),大尺寸、低价值的数据,高伸缩性的场景(数十或者数百台服务器组成的数据库),存储地理坐标的数据;不适合高度事务性的系统、传统的商业智能应用及需要复杂SQL的问题。
  
  MySQL适用场景:事务性的系统(涉及金钱),需要复杂SQL的问题。
  
  2.4 如何选择消息队列软件
  
  2.4.1 为什么使用消息队列
  
  将一些需要花比较多的时间,而且迟点完成不影响整个任务的完成进度的小任务,放到消息队列中,可加快后台请求的响应时间;比如发送邮件、发送短信、推送消息等任务就非常适合放到消息队列中。同时消息队列也能把大量的并发请求变成串行的请求,减轻服务器的负担。
  
  2.4.2 消息队列的工作流程
  
  App后台(队列生产者)把消息推入到消息队列;
  
  守护进程(队列消费者)不断地检测消息队列中有没有新的消息,没有消息就休息一会儿再检测消息队列中有没有新的消息(这样做能避免消息队列占据过多的服务器资源),有消息的话就从消息队列取出消息,用新的线程处理相关的业务,在主线程中继续检测消息队列是否有新消息。
  
  2.4.3 常见的一些消息队列产品
  
  RabbitMQ:重量级的消息队列,适合企业级的开发,其支持大量的协议,比如AMQP、XMPP、SMTP、STOMP;同时RabbitMQ自带了一个Web监控界面,可方便监控队列的情况。
  
  Redis:虽然是一个key-value系统,但其也支持队列这种数据格式,可看作是一个轻量级的消息队列。在App后台架构中Redis被广泛使用,如果把其作为消息队列,能减少项目中的运维成本。
  
  ZeroMQ:号称最快的消息队列,尤其针对大吞吐量的需求场景。
  
  ActiveMQ
  
  2.5 使用分布式服务实现业务的复用
  
  随着业务不断增加,后台系统由一个单一的应用慢慢膨胀为一个巨无霸系统,它聚合了大量的应用和服务,各个模块之间由很多功能重复实现,造成了开发、运维、部署的麻烦。
  
  2.5.1 巨无霸系统的危害
  
  维护上的麻烦
  
  代码管理上的不方便
  
  数据库连接资源的耗尽
  
  ublic boolean offer(E e) {
if (e == null) throw new NullPointerException();
final AtomicInteger count = this.count;
if (count.get() == capacity) return false; // 如果队列已满,直接返回失败
int c = -1;
Node<E> node = new Node<E>(e); // 将数据封装为节点
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
if (count.get() < capacity) {
enqueue(node); // 入队
c = count.getAndIncrement();
if (c + 1 < capacity) // 如果队列未满,则继续唤醒 putCondition 条件队列
notFull.signal();
}
} finally {
putLock.unlock();
}
if (c == 0) // 如果添加之前的容量为0,说明在出队的时候有竞争,则唤醒 takeCondition
signalNotEmpty(); // 因为是两把锁,所以在唤醒 takeCondition的时候,还需要获取 takeLock
return c >= 0;
}
private void enqueue(Node<E>www.60910.cn node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
last = last.next = node; // 连接节点,并设置尾节点
}

3. 出队
public E take(www.17093.cn) throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly(www.078881.cn);
try {
while (count.get(www.18037.cn) == 0) { // 如果队列为空,则加入 takeCondition 条件队列
notEmpty.await();
}
x = dequeue(); // 出队
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal(); // 如果队列还有剩余,则继续唤醒 takeCondition 条件队列
} finally {
takeLock.unlock();
}
if (c == capacity) // 如果取之前队列是满的,说明入队的时候有竞争,则唤醒 putCondition
signalNotFull(); // 同样注意是两把锁
return x;
}
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
// assert head.item == null;
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC // 将next引用指向自己,则该节点不可达,在下一次GC的时候回收
head = first;
E x = first.item;
first.item = null;
return x;
  
  把重复实现的模块独立部署为远程服务,新增的业务调用远程服务所提供的功能实现相关的业务,不依赖于里面具体的代码实现。当远程服务里面的业务需要发生变化时,只要接口的传入参数和返回值保持不变,就不会影响到调用这些远程服务的业务。
  
  2.5.3 远程服务的实现
  
  REST
  
  REST(Representational State Transfer),即表述性状态传递,它是一组架构约束条件和原则。满足这些约束条件的原则的应用程序或设计就是RESTful。
  
  REST架构的特点:每一个URI代表一种资源;客户端和App后台之间,传递这种资源的某种表述;客户端通过GET、POST、PUT、DELETE等HTTP动词,对App后台资源进行操作,实现“表述性状态传递”。
  
  REST设计原则中最重要的是请求是无状态的。
  
  RPC
  
  RPC(Remote Procedure Call),即远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
  
  开源的RPC库
  
  阿里巴巴开源Dubbo,其是一个分布式服务框架,致力于提供高性能和透明化的RPC远程调用服务和SOA服务治理方案。
  
  当当网在Dubbo的基础上实现了如下的新功能,并将其命名为Dubbox。
  
  支持REST风格远程调用(HTTP+JSON/XML)。
  
  支持基于Kryo和FST的Java高效序列化实现。
  
  支持基于嵌入式Tomcat的HTTP remoting体系。
  
  将Dubbo中Spring由2.x升级到目前常用的3.x版本。
  
  将Dubbo中的Zookeeper客户端升级到最新的版本,以修正老版本中包含的bug。
  
  2.6 搜索技术入门
  
  常见的开源搜索软件介绍
  
  Lucene
  
  Solr
  
  ElasticSearch
  
  Sphinx
  
  CoreSeek
  
  2.7 定时任务
  
  Linux定时任务Crontab
  
  Java定时任务框架Quartz

上一篇:浅谈ThreadLocal模式


下一篇:设计模式浅谈----策略模式(c#及java实现)