anchor.diff:  
   github: https://github.com/wushaobo/zipper
   
  -docker: https://hub.docker.com/r/wushaobo/zipper+docker: https://hub.docker.com/r/wushaobo/zipper
  
positive.code: 
  对纠结用户下载流量大小的人，告诉你打包下载的内容是经过 gzip 再由浏览器解开的，你可以安心了。
  
  === 资源考虑：按流处理
  
  既然放弃压缩，省下的工作都是I/O，即搬运源文件内容到服务器，再以一个文件的形式搬运到用户手里，为什么中间要存一次文件呢？我们大可以把前后两个管道接上，拿到的每一块源文件内容都立即倒手给用户。
  
negative.code: - IE和现代浏览器对UTF8文件名的对待是有区分的，我们在服务端都满足它们。
  - 不同浏览器对特殊字符的转换也是有差异的，我们在服务里直接统一改好名，同时做到区别重名。
  
  ==== 别拼接源文件地址进 URL
  提出打包下载请求肯定要带着若干源文件的地址，发一个 POST ajax 请求比较理想。因为若选 GET 请求只能拼 URL，源文件地址的URL长度和数目未知，存在超过 URL 长度限制的可能（IE有2084个字节的限制）。
  
  POST 请求带回一个固定长度的存根，在回调方法里再组装一个下载打包文件的 URL，直接打开它就可以启动下载了。这两个请求的衔接是一个用户无法干预的连贯动作，所以时间很快，所以把存根存放在内存数据库如 Redis 中可以设一个很快的过期时间。
  
  image:zipper/request_sequence_diagram.png[]
  
  [[cluster]]
  === 高可用、高并发考虑：集群方案
  看了前文，你该知道这个服务被设计成独立无状态的。和其他集群一样，一个负载均衡器就可实现。
  
  但是前文我说过是用 docker 部署的，我推荐在几个VM之间建 docker swarm，直接利用 docker 的 ingress 网络特性来做负载均衡，通过横向扩展 docker swarm 中节点数目和container数目来支持更高并发。
  
  存根依赖的内存数据库如 Redis 自然也需要做集群，负载很小，只为高可用。
  
  [[implementation]]
  == 实现
  你很走运，我已实现好了，拿去吧~
  
  