一 微服務
1.1簡單了解?SpringCloud?
SpringCloud是目前國內使用最廣泛的微服務框架。官網地址:Spring Cloud。
SpringCloud集成了各種微服務功能組件,并基于SpringBoot實現了這些組件的自動裝配,從而提供了良好的開箱即用體驗:
1.2微服務中的常用組件(面試)
我們腦海中因該出現一幅圖:
- 首先,我們肯定有無數個小的微服務.
- 這無數個微服務之間是不是要進行一個相互調用,那么就會用到 OpenFeign 這樣的組件.
- 這么多服務要相互調用,怎么去管理呢,這就需要用到 nacos 組件去做注冊中心,那么所有的服務就會去找注冊中心去注冊自己的服務.
- 那么我拉取到的服務可能是一個列表,那么將來在遠程調用的時候就需要做負載均衡,就需要使用 LoadBalancer 這個組件.
- 這么多服務將來要做統一配置的管理怎么辦,就需要引入 nacos 作為配置中心.
- 這時候微服務集群就形成了,將來對外提供服務,是不是隨便什么人都能訪問呢?顯然不行,所有在微服務群前面就需要有 gateway 網關 作為入口.
- 那么就算你可以訪問了,萬一流量激增,引起微服務雪崩,給我整個服務搞崩了,肯定不行,因此就需要 sentinel 來做限流、熔斷降級保護.
- 還有一個問題,在分布式系統下,就會引發分布式事務問題,如何解決呢,這就需要 Seata 上場了.
實際上,微服務的組件遠不止于此,還有很多的組件,但是以上呢,就是我們最常用的幾個組件啦!
二 服務拆分與遠程調用
1 服務拆分
前面我們了解到微服務需要對一塊大的服務,拆分成多個小的微服務,那么這個拆分的粒度我們應該如何去把控呢?需要我們注意一下幾點:
1. 單一職責:不同微服務,不要重復開發相同業務
2. 數據獨立:不要訪問其它微服務的數據庫
3. 面向服務:將自己的業務暴露為接口,供其它微服務調用
例如:我們將一個大的服務拆分成了訂單模塊和用戶模塊,并且每一個微服務有自己的數據庫(訂單數據庫和用戶數據庫)。由于在不同的數據庫中,因此只能通過訂單 id 查詢訂單數據,或者通過用戶 id 查詢用戶數據,不能交叉訪問,如下圖
2 遠程調用
相同的服務,我們可以直接通過 mapper 調用其數據庫,不同的服務如何相互調用呢?辦法很簡單,就如上圖,用戶模塊提供公開的訪問接口("/user/{id}"),訂單模塊主動向用戶模塊發送 http 請求獲取數據,這樣就做到了跨服務之間的調用~
2.1注冊RestTemplate
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;import javax.management.MXBean;@MapperScan("cn.itcast.order.mapper")
@SpringBootApplicationpublic class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}/*** 創建RestTemplate并注入Spring容器 ,發送http請求的** @return*/@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}}
2.2 Mapper調用
在訂單服務中,通過 RestTemplate 的 getForObject / postForObject 方法來構造get / post 請求(此處顯然使用 get 請求獲取用戶數據),請求中攜帶的參數便是訂單表中的 userId 數據,當用戶微服務接收到請求后,就可以根據 userId 獲取用戶數據,最后返回到訂單服務中,這樣就實現了跨服務調用
package cn.itcast.order.service;import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查詢訂單Order order = orderMapper.findById(orderId);//2. 利用RestTemplate發起http請求,查詢用戶//2.1url路徑String url = "http://localhost:8081/user/" + order.getUserId();// 2.2發送http請求,實現遠程調用--對應get請求User user = restTemplate.getForObject(url, User.class);//3.封裝user到orderorder.setUser(user);// 4.返回return order;}
}