假设一个ProductSpeed有两个不同的构造器:
public class ProductSpeed {
public ProductSpeed(String name) {
...
}
public ProductSpeed(String name, int order)) {
}
}
<p class="indent">
|
第一个构造器是使用在不相关的产品的订单中。
第二个构造器是我们关注的,因为我们在向用户显示这些产品时首先进行一下排序。
产生这两个构造器的原因是:这个对象可能产生于两个不同的系统,只是在一个系统中有排序要求存在,而另外一个没有这个要求。
我们实际做的是一个对象两个不同的版本,但是我们不能取名为:ProductSpeedForSystem1′ 和 ‘ProductSpeedForSystem2′!
在领域驱动设计DDD中,我们可以认为ProductSpeed是存在两个不同有界上下文中(共享内核),如果是在一个大型整块系统中,它们是分别位于不同的包下面。
下面我们就要区分这两个不同的上下文,进一步我们会发现以第二个构造函数创建的ProductSpeed对象其实和系统其他应用并没有交互,只是为客户端排序而存在,直接服务于客户端,向外服务,而不是向内部组件提供交互(向内不能称为"服务"了),因此这个独立的上下文可以成为一个微服务。
原来我们是通过一个整块API提供所有功能,如下图的Main API:

将上下文区分开以后,微服务可以从原来整块上下文独立出来了:

微服务定义:
每个应用程序都只做一件事
•足够小,适合存在你的脑袋即可。
- “如果一个类大到我脑袋记不住就是实在太大“
•足够小,你可以把它们扔掉
- 用重写来维护
微服务类似Unix的服务:
1. 嵌入了Web容器(以往JavaEE都是服务运行在tomcat等Web容器中)
– 比如可以使用Jetty / SimpleMind
(案例:http://www.jdon.com/idea/javaee7/websocket-jetty.html),这样可以防止抽象泄漏,否则你会去阅读Tomcat源码。
– 测试(测试甚至不重要)和易部署,脱离容器,直接是一个应用,无需那么多Mock了。
2.打包成单个可执行的jar包
– 有自己独立的配置
– 标准的unix rc.d 脚本
3. 可以以类似Unix后台启动Httpd服务方式等启动
– Unix的后台守护 Daemons看样子工作这么多年很好,除非你有特殊需求,否则不要重复发明轮子。
4. 每个应用都是独立分离的,符合领域驱动设计和Conways法则的有界上下文,使用物理的实现真正分离他们。
5.如果有共同的代码,将其成为一个底层设施的库包。
–对待它们就像对待其他开源库包项目一样。
–可以将其提交到Maven中央仓库,作为一个二进制依赖包。
6. 能够自给自足Provisioned。
许多小应用程序的复杂性管理之道是在于让它们自我管理。比如ServiceA和ServiceB自己实现负载平衡和自动扩展,数据库自己实现集群。
7. 用看门狗来坚持应用的状态,类似Scala的Actor模型,如果有失败,自动重启它们。每个应用都要向外暴露它们的运行情况,以便监视。
微服务原始定义见:http://2012.33degree.org/talk/show/67