文章目录
- 1、学习提纲
- 2、和单体架构的比较
- 3、认识微服务
- 4、微服务技术常用框架
- 5、SprigCloud
- 6、服务拆分
- 7、微服务远程调用
1、学习提纲
相比传统单体架构,微服务的整体架构如下图:
再引入日志、监控、持续集成、持续部署,就成了下面这个图:
对这里涉及到的技术,进行一个分类:
2、和单体架构的比较
单体架构
之前的单体架构,即将业务的所有功能集中在一个项目中开发,打成一个包进行部署。单体架构有优点:
- 架构简单
- 部署成本低
缺点则是:
- 耦合度高
微服务架构
相比单体架构,分布式架构则是根据业务功能对系统进行拆分,每个业务模块做为独立项目开发,成为一个个服务。从而:
- 降低服务的耦合
- 有利于服务的升级拓展
但此时也产生了新的问题:
- 系统怎么拆,即服务拆分粒度如何
- 服务集群的地址怎么维护
- 服务之间如何远程调用
- 服务健康状态怎么感知
3、认识微服务
微服务是一种经过良好架构设计的分布式架构方案
,微服务架构特征:
-
单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力
-
面向服务:微服务对外暴露业务接口
-
自治:团队独立、技术独立、数据独立、部署独立。即每个服务有一个小组负责,这个小组有自己的前后端、测试、运维。可以选择适合该服务的语言与技术。每个服务有自己的数据库。
-
隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题(一个服务挂了,向依赖的服务全挂了)
服务之间的调用关系错综复杂,需要进行维护,因此微服务中还有一个注册中心,去维护每个微服务的信息和监控服务的健康状态。
对于一些配置,每次去微服务代码中去修改不现实,因此,还有一个配置中心,去统一管理每个微服务的配置。
最后再加上一个网关做为访问的入口,就得到了这样的架构:
4、微服务技术常用框架
微服务这种技术需要技术框架来进行落地,最常用的是SpringCloud和阿里巴巴的Dubbo。下面做个对比:
企业中常用的一个情况是:
- SpringCloud技术栈
- 接口采用Restful风格
- 服务调用采用Feign方式
5、SprigCloud
SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud
SpringCloud集成了下面的各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配。
SpringCloud和SpringBoot的版本适配情况:
6、服务拆分
微服务拆分的注意事项:
-
单一职责:不同微服务,不要重复开发相同业务
-
数据独立:不要访问其它微服务的数据库
-
面向服务:将自己的业务暴露为接口,供其它微服务调用
案例:
在IDEA中导入Demo工程:
这里有两个模块:
调用一下两个模块的接口:
到此,可以看到拆分完成,不同的模块干不同的职责,order模块查订单,user模块查用户。并且数据库也做了分离。每个微服务有自己独立的数据库。
7、微服务远程调用
需求:根据订单id查询订单的同时,把订单所属的用户信息一起返回
# 两个信息在不同的数据库
# 查询这两个信息得用两个模块的接口(这里只是举例,当然你强行在其中一个模块创建mapper并指定数据库也能实现,但这首先不符合微服务规范,因为操作了其他微服务的数据库。其次当这里的接口实现很复杂,不再是一句SQL能完成的时候,这么操作就不现实了)
分析:
实现远程调用:
像在浏览器发送HTTP请求得到用户信息一样,在模块中发送HTTP请求也可以得到响应。那如何在Java代码中发起合HTTP请求呢?
实现微服务调用的步骤:
STEP1:
在调用方的(配置类)启动类中注册RestTemplate
//Bean的注入只能放在配置类中,而@SpringBootApplication注解的启动类本身也是配置类
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
STEP2:
在需要远程调用其他服务的方法中,使用restTemplate对象,调用getForObject方法或者postForObjecct方法,传入调用的url,和需要的类型(就可以json反序列化出User.class类型的对象)
@Service
public class OrderService{
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId){
//查询订单
Order order = orderMapper.findById(orderId);
//查询用户
String url = "http://localhost:8081/user/" + order.getUserId();
//这里的url参数,浏览器中是个啥,这里也就是个啥,一样的
User user = restTemplate.getForObject(url,User.class);
//封装user信息,order对象中有引用属性User类型
order.setUser(user);
return order;
}
}
重启order服务:
到此,跨服务的调用实现。