一、微服务导学
1.1 对比单体架构与分布式架构
单体架构
将业务的所有功能集中再一个项目中开发,打成一个包部署。
分布式架构
缺点: 模块多导致部署麻烦;架构复杂,难度大
1.2 微服务
经过良好架构设计的分布式架构方案,微服务架构特征:
缺点:架构更复杂,运维、监控、部署难度提高
为了实现高内聚,低耦合,降低程序之间的影响
1.2.1 微服务结构
注册中心:维护微服务里面每个节点的信息,并且监控节点的状态
配置中心:统一管理整个微服务群的配置。利用通知的方式让对应的服务去监控配置的变化,从而实现配置的更新
服务网关:作为入口。用户访问网关,然后由网关把请求路由到我们的微服务群(路由的时候还可以做负载均衡,路由的时候以及服务调用的过程中我们要做好服务的容错处理)
1.2.2
若使用Hoxton.SR10,则对应spring boot版本2.3.x版本
二、服务的拆分及远程调用
2.1 服务拆分注意事项
不同微服务,不要重复开发相同业务
微服务数据独立,不要访问其他微服务的数据库(每个微服务都有自己独立的数据库,从根源上杜绝了耦合性的一些业务)
将自己的业务暴露为接口,供其他微服务调用
2.2服务拆分
我们可以准备两个不同的database去存储这些表,如下图所示
之后启动两个服务,下面的两个服务就符合拆分原则,order服务查寻订单,user服务查询用户,除此之外数据库也做了分离,每个服务都对应一个数据库而不是对应一张表
总结
微服务需要根据业务模块拆分,做到单一职责,不要重复开发相同业务
微服务可以将业务暴露为接口,供其他微服务使用
不同微服务都应该有自己独立的数据库
2.3 微服务远程调用
2.3.1 根据订单id查询订单功能
案例:根据订单id查询订单的同时,把订单所属的用户信息一起返回
如下图所示,当我们查询订单信息的时候,发现最后一个参数"user"为null,下面我们就要实现"user"参数复制
下图所示的需求更清晰
那订单模块不能直接昂问用户模块的数据库,订单模块怎么获取用户信息呢? 答案是远程调用!
2.3.1.1怎么远程调用?
分析如下图所示:
订单模块可以通过http的形式向用户模块发送http请求从而获取到对应的用户数据
在订单数据表中我们发现有"user_id"字段,我们完全可以使用"user_id"字段的数据作为http请求的参数来获取用户数据
2.3.1.2 那订单模块怎么发送http请求?
第一步:注册RestTemplate
在order-service的OrderApplication中注册RestTemplate
通过@Bean的方式将RestTemplate注册为spring对象,将来我们在任何地方都能够注入这个对象
bean的注入一般放在配置类中,一般带有@SpringBootApplication的启动类也是配置类,那我们也可以在启动类中注入bean,注入之后我们便可以使用RestTemplate发送http请求
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
第二步:发送HTTP请求并封装数据
下面这个实体类就是我们要封装之后的
@Data
public class Order {
private Long id;
private Long price;
private String name;
private Integer num;
private Long userId;
private User user;
}
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单 从数据库中获取订单,订单数据中有user_id字段的值,我们要用这个字段的值找user
Order order = orderMapper.findById(orderId);
//2. 利用RestTemplate发起HTTP请求,获取用户
// get请求:getForObject(url路径,返回值类型)
// 我们下面的返回值类型不需要JSON,而是需要一个User对象的形式,所以写User.class
// post请求:postForObject()
String url = "http://localhost:8081/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);
//3. 封装user到Order中
order.setUser(user);
// 4.返回
return order;
}
最终访问时带有user用户信息,说明我们封装成功!!!
2.3.2 远程调用总结
基于RestTemplate发起的http请求实现远程调用
http请求做远程调用是与语言无关的调用,只要知道对方的ip、端口、接口路径、请求参数即可