什么是微服务

假设一个ProductSpeed有两个不同的构造器:


public class ProductSpeed {
public ProductSpeed(String name) {
...
}

public ProductSpeed(String name, int order)) {

}
}

第一个构造器是使用在不相关的产品的订单中。

第二个构造器是我们关注的,因为我们在向用户显示这些产品时首先进行一下排序。

产生这两个构造器的原因是:这个对象可能产生于两个不同的系统,只是在一个系统中有排序要求存在,而另外一个没有这个要求。

我们实际做的是一个对象两个不同的版本,但是我们不能取名为: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

微服务有两个特点,通过将Tomcat等Web容器放入自身,这与传统JavaEE方式相反,以此从物理实现DDD有界上下文分离,从而实现模块化,这种方式区别于传统的复杂的OSGI。

OSGI真的要该抛弃了。

说白了:微服务推翻了OSGI和JavaEE容器的统治。

而这一个革命性推翻不是从Java内部发生的,是从Node.js那里开始的:
http://www.jdon.com/46024
[该贴被banq于2013-12-26 10:26修改过]

"微服务“似乎又是一个新名词、新概念,目前技术发展带来的各种新名词总是令人眼花缭乱。
如何保持真我,适当地引入新技术呢?在我看来,只要抓住两点即可:
1、如何保证:同一个逻辑只在同一个地方出现;
2、面对快速变化的业务,该技术是否能让我更好地如何灵活适应?

  用“微服务”的思路看DDD,可能也是一种颠覆。
  把一个类的读、写方法直接暴露成服务,让client决定如何组装不同类的服务而应对不同的业务场景。我是赞同这种方式的,因为它既可以保持“单一逻辑的纯洁性”,又可以灵活适应各种业务场景以及变化。
  这种做法与DDD是完全不同的,因为DDD只有在领域模型的Service层才能对外服务。同时,这种思路也打破了DDD中的聚合根对DDD中各个类的方法的“家长式的专制”,仿佛是“决不允许直接找我闺女,所有对外的行为必须征求我这个当爹的许可”。在我看来,这是对传统DDD的一种天性的解放。
  不知大家怎么看。

2013-12-28 12:09 "@flyzb"的内容
在我看来,这是对传统DDD的一种天性的解放 ...

呵呵,注意文中有一句:“每个应用都是独立分离的,符合领域驱动设计和Conways法则的有界上下文,使用物理的实现真正分离他们”

微服务=有界上下文, DDD=服务+聚合根实体。如果把聚合根实体看成是演员,那么有界上下文是舞台。DDD本来是这么定义,有可能我们以前误解了,只注重实体,或只注重聚合根,忽视上下文,这三个一个都不能少,见这个帖子:
http://www.jdon.com/46024/5#23144230

微服务是对DDD落地的一种实施,通过微服务,真正在物理实施上做到了有界上下文,微服务所以等同于DDD的有界上下文。微服务和DDD的服务某种程度是一致的,微服务应该是从外部对DDD服务的称谓,任何一个DDD服务都可以成为一个微服务,但是不代表业务逻辑就全部在微服务中实现,这个在DDD中对服务定义已经很清楚。

微服务的微是针对SOA的粗粒度服务而言,SOA倡导粗粒度服务,这对于外部流程设计是有利的,使得外部流程BPML等不会涉及过多领域内部特征,注重流程。所以,如果两者结合,需要一个微服务的组合器组合成粗粒度的服务,可以通过事件总线实施,也可以通过一些中间件,如使用Fabric3实现模块化:http://www.jdon.com/soa/modularity.html

[该贴被banq于2013-12-28 18:35修改过]

1.上下文(或者Client)和聚合(包含聚合内的类)的场景/业务相关性,把这种相关性分离出聚合所应该承担的责任,然后微服务的形式来呈现。
2.这种微服务应该是领域模型内部的,细粒度的业务实现。
3.是对DDD的一种实施途径/或者补充完善,并没有冲突。
4.以上是个人的理解,请指正。有一个问题,构造函数是一种途径,方法重载我觉得也应该是一种途径,不知道是否如此。

  “微服务”的提出是为了适应快速变化的业务。而从对业务变化的稳定度来讲,在“上下文”、“聚合”和“类的方法”三这者中“上下文”和“类的方法”都是相对稳固的,因为这两者的变化一般都是以扩展方式而变化的,而“聚合”是在“上下文”和“类的方法”的基础上提炼出来的,是最难确认的,也是最容易出偏差的,同时也是大家容易发生争论的地方。
  所以我主张弱化“聚合”,用上下文中的“组合”来替代“聚合”。从逻辑的可维护性上来说,这种做法更容易被开发人员所接受。

2013-12-29 13:52 "@flyzb"的内容
微服务”的提出是为了适应快速变化的业务。而从对业务变化的稳定度来讲,在“上下文”、“聚合”和“类的方法”三这者中“上下文”和“类的方法”都是相对稳固的,因为这两者的变化一般都是以扩展方式而变化的,而“聚合”是在“上下文”和“类的方法”的基础 ...

1.微服务的主要用途应该不是解决快速变化的业务,个人认为微服务是相对”细粒度“的业务实现,是一种责任的分配。
2.聚合的确立是基于上下文的,如果上下文是稳定的,聚合也应该相对稳定。
3.如果用”组合“去替代”聚合“,用于组合的组件是什么呢?是不是还是聚合体?

跟OSGi啥区别