单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署
单体架构的优缺点:
**优点:**架构简单,部署成本低
**缺点:**耦合度高(维护困难,升级困难)
1.2分布式架构分布式架构:根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,称为一个服务
**优点:**降低服务耦合,有利于服务升级和拓展
**缺点:**服务调用关系错综复杂
分布式架构虽然降低了服务耦合,但是服务拆分时也有很多问题需要思考:服务拆分的粒度、服务之间调用、服务之间调用关系的管理,需要制定一套行之有效的标准来约束分布式架构。
1.3微服务架构微服务的架构特征:
单一职责:微服务拆分粒度小,每一个服务都对应唯一的业务能力,做到单一职责自治:团队独立,技术独立,独立部署和交付面向服务:服务提供统一标准的接口,与语言和技术无关隔离性强:服务调用做好隔离、容错、降级、避免出现级联问题微服务是一种经过良好架构设计的分布式架构方案
SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud
SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配
其中常见的组件包括:
服务注册发现:Eureka、Nacos、Consul服务远程调用:OpenFeign、Dubbo服务链路监控:Zipkin、Sleuth统一配置管理:SpringCloudConfig、Nacos统一网关路由:SpringCloudGateway、Zuul流控、降级、保护:Hystix、SentinelSpringCloud是微服务交媾的一站式解决方案,继承了各种优秀微服务功能组件
2.服务拆分任何分布式架构都离不开服务的拆分,微服务也一样
微服务的拆分原则:
不同微服务,不要重复开发相同的业务微服务数据独立,不要访问其他微服务的数据库微服务可以将自己的业务暴露为接口,供其他微服务调用 3.远程调用项目结构:
在order-service服务中,有一个根据id查询订单的接口:
package cn.itcast.order.web;import cn.itcast.order.pojo.Order;import cn.itcast.order.service.OrderService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/order")public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("/{orderId}")public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {// 根据id查询订单并返回return orderService.queryOrderById(orderId);}}根据id查询订单,返回值是Order对象,如图
在user-service中有一个根据id查询用户的接口:
package cn.itcast.user.web;import cn.itcast.user.pojo.User;import cn.itcast.user.service.UserService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.format.annotation.DateTimeFormat;import org.springframework.web.bind.annotation.*;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;@Slf4j@RestController@RequestMapping("/user")public class UserController {@Autowiredprivate UserService userService;/*** 路径: /user/110** @param id 用户id* @return 用户*/@GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) {return userService.queryById(id);}}查询的结果如图:
**案例需求:**修改order-service中的根据id查询订单业务,要求在查询订单的同时,根据订单中包含的userId查询出用户信息,一起返回
分析:需要在order-service中向user-service发起一个http请求,调用http://localhost:8081/user/{userId}接口
步骤:
注册一个RestTemplate的实例到Spring容器修改order-service服务中的OrderService类中的queryOrderById方法,根据Order对象中的userId查询User将查询的User填充到Order对象中返回 package cn.itcast.order.pojo;import cn.itcast.pojo.User;import lombok.Data;//Order实体类@Datapublic class Order {private Long id;private Long price;private String name;private Integer num;private Long userId;private User user;} package cn.itcast.order;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;@MapperScan("cn.itcast.order.mapper")@SpringBootApplicationpublic class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}}实现远程调用:
package cn.itcast.order.service;import cn.itcast.feign.UserClient;import cn.itcast.pojo.User;import cn.itcast.order.mapper.OrderMapper;import cn.itcast.order.pojo.Order;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);//2.调用user微服务接口,根据userId得到用户信息String url = "http://userservice/user/" + order.getUserId();User user = restTemplate.getForObject(url, User.class);//3.封装user数据到orderorder.setUser(user);// 4.返回return order;}}