SpringCloud
1.認識微服務
1.1單體架構
單體架構:將業務的所有功能集中在一個項目中開發,打成一個包部署
單體架構的優缺點:
**優點:**架構簡單,部署成本低
**缺點:**耦合度高(維護困難,升級困難)
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、Sentinel
SpringCloud是微服務交媾的一站式解決方案,繼承了各種優秀微服務功能組件
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實體類
@Data
public 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")
@SpringBootApplication
public 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;@Service
public 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;}
}