微服务的特点
-
单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责;
-
微:微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小,但是五脏俱全。
-
面向服务:面向服务是说每个服务都要对外暴露服务接口API,并不关心服务的技术实现,做到与平台无关、与语言无关,也不限定什么技术实现,只要提供Rest接口即可。
-
自治:自治是说服务间互相独立,互不干扰;
- 团队独立:每个服务都是一个独立的开发团队;
- 技术独立:因为是面向服务,提供Rest接口,使用什么技术没有别人干涉;
- 前后端分离:采用前后端分离开发,提供统一Rest接口,后端不再为PC、移动端开发不同接口。
- 数据库分离:每个服务都使用自己的数据源;
- 部署独立:服务间虽然由调用,但要做到服务重启不影响其他服务。有利用持续集成和持续交付。每个服务都是独立的组件,可复用,可替换,降低耦合,容易维护。
微服务结构图
远程调用方式
常见的远程调用方式
- RPC:Remote Process Call 远程过程调用,类似的还有RMI。自定义数据格式,基于原生TCP通信,速度快,效率高。比如早期的webservice和现在的Dubbo,都是RPC典型;
- Http:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式,现在客户端浏览器与服务端通信基本都是采用http协议,也可以用来进行远程服务调用,缺点是消息封装臃肿。
认识RPC
RPC是一个计算机通信协议,该协议允许运行与一台计算机的程序调用另一台计算机的子程序,而程序员无需额外的为这个交互作用编程。简单地说A计算机提供一个服务,B计算机可以像嗲用本地服务那样调用A计算机的服务。
RPC主要做到两点
- 实现远程调用其他计算机的服务;
- 向调用本地服务一样调用远程服务;
认识http
Http协议:超文本传输协议,是一种应用层写给,规定了网络传输的请求格式、响应格式、资源定位和操作的方式等,底层基本上都采用TCP协议作为底层传输协议,也可以使用其他网络传输协议。说到这里大家可能觉得Http和RPC的远程非常像,都是按照某种规定好的数据格式进行网络通信,有请求,有响应,两者非常相似,但是还是存在一些细微的差别:
-
RPC并没有规定数据传输格式,这个格式可以任意指定,不同的RPC协议,数据格式不一定相同。
-
Http中还定义了资源定位的路径,RPC不需要;
-
最重要的一点:RPC需要满足像调用本地服务一样调用远程服务,也就是对调用过程在API层面进行封装。Http协议没有这样的要求,因此请求、响应等细节需要自己去实现。
- 优点:RPC方式更加透明,对用户方便,Http方式灵活,没有规定API和语言、跨语言、跨平台。
- 缺点:RPC方式需要在API层面进行封装,限制了开发的语言环境。
如何选择?
- 速度方面:RPC比http要快,因为http协议的信息都比较臃肿,不过可以采用gzip压缩;
- 实现难度:RPC实现较为复杂,http相对比较简单;
- 灵活性:http更胜一筹,因为它不短信实现细节,跨平台、跨语言;
适用场景
- 如果对效率要求更高,并且开发过程适用统一的技术栈,那么RPC比较适合;
- 如果需要更加灵活,跨平台,跨语言,显然http更合适。
Http客户端工具
既然微服务选择了http,那么我们就需要自己来实现对请求和响应的处理,就像浏览器对请求、响应的封装解析处理,不过开源世界已经有很多客户端工具能帮我们做这个事:
- HttpClient;
- OKHttp;
- URLConnection
使用HttpClient
public class HttpTests {
CloseableHttpClient httpClient;
@Before
public void init() {
httpClient = HttpClients.createDefault();
}
@Test
public void testGet() throws IOException {
HttpGet request = new HttpGet("http://localhost:8081/1");
String response = this.httpClient.execute(request, new BasicResponseHandler());
System.out.println(response);
}
@Test
public void testPost() throws IOException {
HttpGet request = new HttpGet("http://www.oschina.net/");
request.setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
String response = this.httpClient.execute(request, new BasicResponseHandler());
System.out.println(response);
}
@Test
public void testGetPojo() throws IOException {
HttpGet request = new HttpGet("http://localhost/hello");
String response = this.httpClient.execute(request, new BasicResponseHandler());
System.out.println(response);
}
}
Spring的RestTemplate
Spring提供了一个RestTemplate模板工具,对基于Http的客户端进行封装,并且实现了对象与json的序列化和反序列化们非常方便,RestTemplate并没有限定Http的客户端类型,而是进行了抽象,目前常用的3种都有支持:HTTPClient、OKHttp、JDK原生的URLConnection(默认的)
@SpringBootApplication
public class HttpDemoApplication {
public static void main(String[] args) {
SpringApplication.run(HttpDemoApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = HttpDemoApplication.class)
public class HttpDemoApplicationTests {
@Autowired
private RestTemplate restTemplate;
@Test
public void httpGet() {
User user = this.restTemplate.getForObject("http://localhost:8081/1", User.class);
System.out.println(user);
}
}
认识SpringCloud
简介
SpringCloud时Spring旗下的项目之一,Spring最擅长的就是集成,把世界上最好的框架拿来集成到自己的项目中。
SpringCloud也是一样的,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理、服务发现、智能路由、熔断器、控制总线、集群状态等等功能。
涉及的部分组件:
- netfix;
- Eureka:注册中心;
- Zuul:服务网关;
- Ribbon:负载均衡;
- Feign:服务调用;
- Hystix:熔断器
架构图
版本
SpringCloud的版本命名比较特殊,因为不是一个组件,而是许多组件的集合,它的命令是以A到Z的为首字母的单词组成的。
组件的版本: