Spring Cloud 微服務架構解決方案

律二萌萌噠發表於2020-11-02

Spring Cloud 微服務架構解決方案

1. 目標

1、能說出微服務架構特點。

2、能說出微服務技術棧的構成。

3、理解Spring Cloud Eureka服務治理的流程。

4、理解Spring Cloud Ribbon負載均衡的應用方法。

5、理解Spring Cloud Hystrix 斷路保護的應用方法。

6、理解Spring Cloud Zuul 閘道器的作用及方法。

7、瞭解Spring Cloud Config、Spring Cloud Bus、Spring Cloud Sleuth等其它子專案的應用場景。

2. 理解微服務

2.1 軟體架構演進

  • 軟體架構的發展經歷了從單體結構、垂直架構、SOA架構到微服務架構的過程。

2.1.1 單體架構

在這裡插入圖片描述特點:

  1. 所有的功能整合在一個專案工程中。
  2. 所有的功能打一個war包部署到伺服器。
  3. 應用與資料庫分開部署。
  4. 通過部署應用叢集和資料庫叢集來提高系統的效能。

優點:

  • 專案架構簡單,前期開發成本低,週期短,小型專案的首選。

缺點:

  1. 全部功能整合在一個工程中,對於大型專案不易開發、擴充套件及維護。
  2. 系統效能擴充套件只能通過擴充套件叢集結點,成本高、有瓶頸。
  3. 技術棧受限。

2.1.2 垂直架構

在這裡插入圖片描述特點:

  1. 以單體結構規模的專案為單位進行垂直劃分專案即將一個大專案拆分成一個一個單體結構專案。
  2. 專案與專案之間的存在資料冗餘,耦合性較大,比如上圖中三個專案都存在客戶資訊。
  3. 專案之間的介面多為資料同步功能,如:資料庫之間的資料庫,通過網路介面進行資料庫同步。

優點:

  1. 專案架構簡單,前期開發成本低,週期短,小型專案的首選。
  2. 通過垂直拆分,原來的單體專案不至於無限擴大。
  3. 不同的專案可採用不同的技術。

缺點:

  1. 全部功能整合在一個工程中,對於大型專案不易開發、擴充套件及維護。
  2. 系統效能擴充套件只能通過擴充套件叢集結點,成本高、有瓶頸。

2.1.3 SOA架構

在這裡插入圖片描述
特點:

  1. 基於SOA的架構思想將重複公用的功能抽取為元件以服務的方式給各各系統提供服務

  2. 各各專案(系統)與服務之間採用webservice、rpc等方式進行通訊。

  3. ESB企業服務匯流排作為專案與服務之間通訊的橋樑

優點:

  1. 將重複的功能抽取為服務,提高開發效率,提高系統的可重用性、可維護性
  2. 可以針對不同服務的特點制定叢集及優化方案。
  3. 採用ESB減少系統中的介面耦合。

缺點:

  1. 系統與服務的界限模糊,不利於開發及維護。
  2. 雖然使用了ESB,但是服務的介面協議不固定,種類繁多,不利於系統維護。
  3. 抽取的服務的粒度過大,系統與服務之間耦合性高

2.1.1 微服務架構

在這裡插入圖片描述特點:

  1. 將系統服務層完全獨立出來,並將服務層抽取為一個一個的微服務
  2. 微服務遵循單一原則
  3. 微服務之間採用RESTful等輕量協議傳輸

優點:

  1. 服務拆分粒度更細,有利於資源重複利用,提高開發效率。
  2. 可以更加精準的制定每個服務的優化方案,提高系統可維護性。
  3. 微服務架構採用去中心化思想,服務之間採用RESTful等輕量協議通訊,相比ESB更輕量。
  4. 適用於網際網路時代,產品迭代週期更短。

缺點:

  1. 微服務過多,服務治理成本高,不利於系統維護。
  2. 分散式系統開發的技術成本高(容錯、分散式事務等),對團隊挑戰大。

2.2 什麼是微服務

為適應企業的業務發展,提高軟體研發的生產力,降低軟體研發的成本,軟體架構也作了升級和優化,將一個獨立的系統拆分成若干小的服務,每個小服務執行在不同的程式中,服務與服務之間採用http 輕量協議(比如流行的RESTful)傳輸資料,每個服務所擁有的功能具有獨立性強、高內聚的特點,這樣的設計就實現了單個服務的高內聚,服務與服務之間的低耦合效果,這一個一個的小服務就是微服務,基於這種方法設計的系統架構即微服務架構

2.3 Spring Cloud技術棧

2.3.1 微服務的技術棧

在這裡插入圖片描述

  • 負載均衡,閘道器路由:高可用、叢集部署,校驗、請求轉發、服務整合。
  • 服務治理:服務註冊、發現。
  • 容錯:避免雪崩。
  • 監控跟蹤:監控資源利用、服務響應、容器資源利用情況。
  • 訊息匯流排:訊息佇列、非同步通訊。
  • 配置管理:統一配置管理。

2.3.2 Spring Cloud是什麼

  • Spring Cloud為開發人員構建微服務架構提供了完整的解決方案,SpringCloud是若干個框架的集合,它包括spring-cloud-config、spring-cloud-bus等近20個子專案,它提供了服務治理、服務閘道器、智慧路由、負載均衡、斷路器、監控跟蹤、分散式訊息佇列、配置管理等領域的解決方案

2.3.3 Spring Cloud技術棧

微服務的興起出現了很多優秀的公司和技術:
服務治理:Dubbo(阿里巴巴)、Dubbox(噹噹)、Eureka(Netflix)等 。
配置管理:Disconf(百度)、QConf(360)、Diamood(淘寶)等 。
服務跟蹤:Hydra(京東)、Zipkin(Twitter)、Sleuth(Spring Cloud)等 。

Spring Cloud 提供一站式的微服務架構解決方案,如下圖:

在這裡插入圖片描述

2.3.4 為什麼使用Spring Cloud

  • 微服務架構的優點表明它可以提高我們的生產力,但是分散式系統本身的技術成本問題給網際網路那些創業型公司不少的挑戰,阿里、百度等巨頭所提供的微服務技術只是解決其中某個問題,而整合封裝這些優秀的技術恐怕是Spring最擅長的領域了,Spring Cloud也正因為此而誕生。

  • 使用Spring Cloud來構建微服務架構可以省去你整合各家技術的成本,Spring Cloud為我們構建微服務架構提供了一站式的解決方案,就好比當初Spring誕生是為解決EJB企業應用開發的眾多問題而提供的一站式輕量級企業應用開發解決方案一樣,隨著使用Spring Cloud公司數量的增加,相信微服務將被Spring Cloud一統江湖。

2.3.5 Netflix公司介紹

Spring Cloud的很多技術來源於Netfix(https://netflix.github.io/),摘自百度百科的資訊如下:
在這裡插入圖片描述
在這裡插入圖片描述

3. 開發環境

3.1 Java8

  • Spring Cloud是基於Java構建,本課程使用Java8作為基礎平臺。

3.2 Maven

  • 優秀的架構離不開優秀的專案構建工具,本課程採用Maven來構建(使用apache-maven-3.3.9-bin)。

3.3 Spring Boot

Spring Cloud是基於Spring Boot構建,本課程使用Spring Boot 1.5.4版本。

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>

3.4 Spring Cloud

Spring Cloud為了避免和各子專案的版本名稱混淆,它採用倫敦地鐵站命名。
當前版本情況如下:
在這裡插入圖片描述

本課程 使用Dalston.SR3版本。

 <!-- 匯入Spring Cloud的依賴管理 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

3.5 MySQL

MySQL作為資料庫的第二把交椅甚至直逼Oralce這個老大,在網際網路開發中MySQL的應用是最廣泛的。本課程採用MySQL5來構建架構。

3.6 IDEA

IntelliJ IDEA功能的強大及易用性不亞於Eclipse,據統計其使用人數已直逼Eclipse,成為老大指日可待。
本課程 使用IDEA作為開發工具。

4. 服務治理

4.1 什麼是服務治理

微服務架構的缺點中最主要的就是由於微服務數量眾多導致維護成本巨大,服務治理為解決此問題而產生的。服務治理的作用是讓維護人員從人工維護中解放出來由服務自維護,微服務作為服務提供方主動向服務治理中心註冊,服務的消費方通過服務治理中心查詢需要的服務並進行呼叫。

如下圖:
在這裡插入圖片描述

4.2 Spring Cloud Eureka

Spring Cloud Eureka 是對Netflix公司的Eureka的二次封裝它實現了服務治理的功能,Spring Cloud Eureka提供服務端與客戶端,服務端即是服務註冊中心,客戶端完成服務的註冊與發現。服務端和客戶端均採用Java語言編寫(Eureka支援多語言)。

如下圖顯示了Eureka Server與Eureka Client的關係:

在這裡插入圖片描述

4.3 架構

在這裡插入圖片描述

4.4 實戰

4.4.1 流程圖

在這裡插入圖片描述

4.4.2 開發並部署 Eureka Server

1、建立Spring Boot工程

SpringBoot啟動類

package cn.itcast.microservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer //宣告這是一個Eureka服務
@SpringBootApplication
public class SpringcloudEurekaApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringcloudEurekaApplication.class, args);
	}

}

2、在pom.xml中新增依賴(spring boot 、spring cloud、Eureka Server)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>cn.itcast</groupId>
	<artifactId>springcloud-eureka</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springcloud-eureka</name>
	<description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!-- 匯入Spring Cloud的依賴管理 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- 匯入Eureka服務的依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <!-- 資原始檔拷貝外掛 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
                <version>2.6</version>
            </plugin>
            <!-- java編譯外掛 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3、配置application.yml

server:
  port: ${port} #服務埠 通過啟動指令碼傳入引數

spring:
  application:
    name: itcast-microservice-eureka #指定服務名

eureka:
  client:
    registerWithEureka: true #是否將自己註冊到Eureka服務中,本身就是所有無需註冊
    fetchRegistry: true #是否從Eureka中獲取註冊資訊
    serviceUrl: #Eureka客戶端與Eureka服務端進行互動的地址
      defaultZone: ${eureka.server}
  instance:
    prefix-ip-address: true #將自己的ip地址註冊到Eureka服務中
    ip-address: 127.0.0.1
    instance-id: ${spring.application.name}:${server.port} #指定例項id
  server:
    enable-self-preservation: false #禁用自我保護模式
    eviction-interval-timer-in-ms: 60000 #清理間隔(單位毫秒 預設是60*1000)

4、部署兩臺Eureka Server,並且互相註冊,實現高可用。

在這裡插入圖片描述注意:如果沒有設定Eureka Server的複製結點eureka預設會找8761埠。

5、配置兩個啟動指令碼

在這裡插入圖片描述
在這裡插入圖片描述
6、啟動eureka1和eureka2,並分別訪問地址 http://localhost:6868/

在這裡插入圖片描述
http://localhost:6869/

在這裡插入圖片描述

4.4.1 開發使用者資訊服務

使用者資訊服務實現使用者資訊查詢、使用者註冊、使用者資訊修改等功能。
開發使用者資訊服務採用Spring Boot、SpringMVC、Mybatis架構,資料庫採用MySqL5。

SQL語句:

CREATE TABLE user (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '使用者名稱',
  `password` varchar(32) NOT NULL COMMENT '密碼,加密儲存',
  `name` varchar(50) DEFAULT NULL COMMENT '名字',
   email varchar(30),
  `birthday` datetime NOT NULL COMMENT '生日',
   sex char(2) not null,
   state char(1) not null,
   code varchar(10),
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 COMMENT='使用者表';

4.4.2 服務註冊

服務註冊完成將使用者資訊服務註冊到Eureka Server中,供服務消費方查詢。

1、在使用者資訊服務中配置Eureka服務中心地址及使用者資訊服務名稱。
2、在SpringBoot的啟動類中新增註解@EnableDiscoveryClient
3、注意Eureka服務中心地址配置兩個,因為有兩臺Eureka服務中心。
4、使用者服務註冊中心啟動兩個服務,為後邊測試負載均衡準備。

專案結構:
在這裡插入圖片描述UserController.class

package com.itheima.microservice.user.controll;
import com.itheima.microservice.user.pojo.User;
import com.itheima.microservice.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by Administrator on 2017/12/6.
 * 需要熱載入的bean需要加上@RefreshScope註解,
 * 當配置發生變更的時候可以在不重啟應用的前提下完成bean中相關屬性的重新整理。
 */
@RestController
@RefreshScope
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 對外提供介面服務,根據賬號查詢使用者資訊
     *
     * @param username
     * @return
     */
    @GetMapping(value = "user/{username}")
    public User getUserByUsername(@PathVariable("username") String username) {
        return this.userService.getUserByUsername(username);
    }
}

UserService.class

package com.itheima.microservice.user.service;
import com.itheima.microservice.user.mapper.UserMapper;
import com.itheima.microservice.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
 * Created by Administrator on 2017/12/6.
 */
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 根據賬號查詢使用者
     *
     * @param username
     * @return
     */
    public User getUserByUsername(String username) {
        return userMapper.getUserByUsername(username);
    }

}

UserApplication.class 啟動類

package com.itheima.microservice.user.mail;
import com.itheima.microservice.user.util.SpringContextUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
 * Created by Administrator on 2017/12/6.
 */
@EnableDiscoveryClient
@SpringBootApplication
@ComponentScan(basePackages={"com.itheima.microservice"})
@MapperScan("com.itheima.microservice.user.mapper")
public class UserApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(UserApplication.class, args);
        SpringContextUtils.setApplicationContext(applicationContext);
    }

}

UserMapper.class

package com.itheima.microservice.user.mapper;
import com.itheima.microservice.user.pojo.User;

/**
 * Created by Administrator on 2017/12/8.
 */

public interface UserMapper {
    User getUserByUsername(String username);
}

User.class

package com.itheima.microservice.user.pojo;
import java.util.Date;

/**
 * Created by Administrator on 2017/12/10.
 */
public class User {
    private String id;

    private String username;

    private String password;

    private String name;

    private String email;

    private Date birthday;

    private String sex;

    private int state;

    private String code;

    public String getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }

    public Date getBirthday() {
        return birthday;
    }

    public String getSex() {
        return sex;
    }

    public int getState() {
        return state;
    }

    public String getCode() {
        return code;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void setState(int state) {
        this.state = state;
    }

    public void setCode(String code) {
        this.code = code;
    }
    public User(String id, String username, String password, String name, String email, Date birthday, String sex, Integer state, String code) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.name = name;
        this.email = email;
        this.birthday = birthday;
        this.sex = sex;
        this.state = state;
        this.code = code;
    }

    public User() {
    }
    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", state=" + state +
                ", code='" + code + '\'' +
                '}';
    }
}

SpringContextUtils.class

package com.itheima.microservice.user.util;
import org.springframework.context.ApplicationContext;

/**
 * Created by Administrator on 2017/12/8.
 */
public class SpringContextUtils {
    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext context) {
        applicationContext = context;
    }

    public static Object getBean(String beanId) {
        return applicationContext.getBean(beanId);
    }
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.itheima.microservice.user.mapper.UserMapper">

    <select id="getUserByUsername" resultType="User">
               SELECT id,username,password,name,email,birthday,sex,state
               FROM user WHERE username = #{username}
    </select>
</mapper>

application.yml

server:
  port: ${port} #服務埠
spring:
  application:
    name: itcast-microservice-user #指定服務名
################################################################
# mysql 屬性配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://127.0.0.1:3306/store?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: root

#  jpa:
#    hibernate:
#      #ddl-auto: create #ddl-auto:設為create表示每次都重新建表
#      ddl-auto: update #ddl-auto:設為update表示每次都不會重新建表
#    show-sql: true
################################################################
################################################################
#spring整合Mybatis環境
#pojo別名掃描包
mybatis:
  type-aliases-package: com.itheima.microservice.user.pojo
################################################################
################################################################
eureka:
  client:
    registerWithEureka: true #是否將自己註冊到Eureka服務中,預設為true
    fetchRegistry:  true  #是否從Eureka中獲取註冊資訊,預設為true
    serviceUrl: #Eureka客戶端與Eureka服務端進行互動的地址
      defaultZone: http://127.0.0.1:6868/eureka/,http://127.0.0.1:6869/eureka/
    eurekaServerConnectTimeoutSeconds: 60
    eurekaServerReadTimeoutSeconds: 60
  instance:
    prefer-ip-address:  true  #將自己的ip地址註冊到Eureka服務中
    ip-address: 127.0.0.1
    instance-id: ${spring.application.name}:${server.port} #指定例項id
    lease-expiration-duration-in-seconds: 30 #續約更新時間間隔(預設30秒)
    lease-renewal-interval-in-seconds: 10 # 續約到期時間(預設90秒)
    leaseRenewalIntervalInSeconds: 10 #心跳時間
################################################################

################################################################
logging:
  level:
    root: debug
#    org.springframework.web: DEBUG
  file: /log/log/my_provide.log
  pattern:
    console: "%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n"
    file: "%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n"
################################################################

management:
  security:
    enabled: false #是否開啟actuator安全認證

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>cn.itcast</groupId>
	<artifactId>user</artifactId>
	<version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>
    <!-- 匯入Spring Cloud的依賴管理 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!--監控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--整合springmvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 匯入Eureka服務的依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.dataformat</groupId>
                    <artifactId>jackson-dataformat-xml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--整合mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
        <!-- 連線池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
        <!--配置管理-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!--整合訊息匯流排 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <!--啟動連線配置管理失敗重試-->
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!--熱部署-->
        <!--<dependency>-->
        <!--<groupId>org.springframework.boot</groupId>-->
        <!--<artifactId>spring-boot-devtools</artifactId>-->
        <!--<optional>true</optional> &lt;!&ndash; 這個需要為 true 熱部署才有效 &ndash;&gt;-->
        <!--</dependency>-->
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <!-- 資原始檔拷貝外掛 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
                <version>2.6</version>
            </plugin>
            <!-- java編譯外掛 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!--spring boot 與maven整合外掛 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

新增啟動配置

在這裡插入圖片描述在這裡插入圖片描述
訪問如下:user服務已經註冊到eureka server中

在這裡插入圖片描述
訪問地址,資料成功返回

在這裡插入圖片描述

5. 負載均衡

5.1 什麼是負載均衡

  • 負載均衡是微服務架構中必須使用的技術,通過負載均衡來實現系統的高可用、叢集擴容等功能。負載均衡可通過硬體裝置及軟體來實現,硬體比如:F5、Array等,軟體比如:LVS、Nginx等 。

如下圖是負載均衡的架構圖:

在這裡插入圖片描述

  • 使用者請求先到達負載均衡器(也相當於一個服務),負載均衡器根據負載均衡演算法將請求轉發到微服務。負載均衡演算法有:輪訓、隨機、加權輪訓、加權隨機、地址雜湊等方法,負載均衡器維護一份服務列表,根據負載均衡演算法將請求轉發到相應的微服務上,所以負載均衡可以為微服務叢集分擔請求,降低系統的壓力。

5.2 Spring Cloud Ribbon

Spring Cloud Ribbon是基於客戶端的負載均衡工具,負載均衡分為服務端負載均衡和客戶端負載均衡,3.1小節的圖形指的是服務端負載均衡,客戶端負載均衡與服務端負載均衡的區別在於客戶端要維護一份服務列表,Ribbon從Eureka Server獲取服務列表,Ribbon根據負載均衡演算法直接請求到具體的微服務,中間省去了負載均衡服務。
如下圖是Ribbon負載均衡的流程圖:
在這裡插入圖片描述

  • 1、在消費微服務中使用Ribbon實現負載均衡,Ribbon先從Eureka Server中獲取服務列表。
  • 2、Ribbon根據負載均衡的演算法進行負載均衡,將請求轉發到其它微服務

5.3 實戰

在這裡插入圖片描述

5.3.1 開發單點登入服務

單點登入服務提供使用者登入、使用者退出等功能。
單點登入服務需要呼叫使用者資訊服務查詢使用者資訊。
單點登入服務採用Spring Boot、SpringMVC開發。

5.3.2 服務發現

單點登入服務需要從EurekaServer查詢使用者資訊服務。
1、配置Eureka Server服務地址。
2、在SpringBoot的啟動類中新增註解@EnableDiscoveryClient

在這裡插入圖片描述

5.3.3 Ribbon程式設計

1、定義RestTemplate物件
2、配置 @LoadBalanced
3、設定負載均衡演算法。
4、使用RestTemplate呼叫微服務。

在這裡插入圖片描述
在這裡插入圖片描述

6. 容錯保護

6.1 什麼是容錯保護

  • 容錯保護是指微服務在執行過程中出現錯誤並從錯誤中恢復的能力。微服務容錯性不好很容易導致雪崩效應,什麼是雪崩效應?摘自百度百科中的定義:

在這裡插入圖片描述

  • 微服務的雪崩效應表現在服務與服務之間呼叫,當其中一個服務無法提供服務可能導致其它服務也死掉,比如:單點登入服務呼叫使用者資訊服務查詢使用者資訊,由於使用者資訊服務無法提供服務導致單點登入服務一直等待,從而導致使用者登入、使用者退出功能無法使用,像這樣由一個服務所引起的一連串的多個服務無法提供服務即是微服務的雪崩效應

6.2 Spring Cloud Hystrix

Spring Cloud Hystrix 是基於Netflix的開源框架Hystrix的整合,它實現了斷路器、執行緒隔離、訊號隔離等容錯功能
下圖是Hystrix斷路器示意圖:
在這裡插入圖片描述

6.3 實戰

1.要在服務消費方新增hystrix。
在這裡插入圖片描述
2、使用Hystrix實現容錯。
在這裡插入圖片描述3、在Spring boot的啟動類上新增@EnableHystrix註解

在這裡插入圖片描述

7. 服務閘道器

7.1 什麼是服務閘道器

  • 服務閘道器是在微服務前邊設定一道屏障,請求先到服務閘道器,閘道器會對請求進行過慮、校驗、路由等處理。有了服務閘道器可以提高微服務的安全性,校驗不通過的請求將被拒絕訪問。

  • 前邊介紹的Ribbon客戶端負載均衡技術可以不用經過閘道器,因為通常使用Ribbon完成微服務與微服務之間的內部呼叫,而對那些對外提供服務的微服務,比如:使用者登入、提交訂單等,則必須經過閘道器來保證微服務的安全。

7.2 Spring Cloud Zuul

Spring Cloud Zuul是整合Netflix公司的Zuul開源專案實現的微服務閘道器,它實現了請求路由、負載均衡、校驗過慮等 功能。

在這裡插入圖片描述

7.3 實戰

在這裡插入圖片描述
1、部署使用者資訊服務A、單點登入服務B,每個服務部署至少兩臺機器。
2、將使用者資訊服務A、單點登入服務B註冊到EurekaServer中。
3、開發並部署zuul。
在這裡插入圖片描述
4、在zuul中配置路由
在這裡插入圖片描述5、可以定義filter,需要整合zuul提供filter類,進行校驗攔截。
6、在spring boot的啟動類中配置註解
在這裡插入圖片描述7、根據上邊的路由配置訪問微服務。
在這裡插入圖片描述

凡是以/sso/打頭的請求,路由到 itcast-microservice-sso微服務。
在這裡插入圖片描述

7.4 總結

zuul閘道器,不僅提供對外服務訪問 ,微服務也可以通過zuul請求其它的微服務。

相關文章