天天看點

SpringCloud入門簡介(1)

目錄

    • SpringCloud簡介
    • 入門案例
    • 配置eureka

簡單來說,Spring Cloud是一個微服務架構的規範,注意,隻是規範,他不是任何具體的架構。我們知道java大佬最喜歡的做法就是自己制定規範,然後别人基于我這個規範來做實作。那麼這個規範裡面有什麼呢,它規定大概要有以下幾種功能。

  1. 服務的注冊與發現
  2. 負載均衡
  3. 服務熔斷和限流
  4. 智能路由
  5. 控制總線
  6. 鍊路監控

原本的單體項目一步一步劃分

SpringCloud入門簡介(1)

這樣的架構解決了單體項目幾點問題:

1、zuul網關解決了服務調用安全性的問題

2、服務注冊與發現(注冊中心)eureka解決了各層服務耦合問題,它是微服務架構的核心,有它才能将單體項目拆解成微服務架構

3、Eureka叢集解決了微服務中,注冊中心當機産生的問題

4、Ribbon負載均衡及Feign消費者調用服務,減小了各微服務伺服器的通路壓力,預設采用了經典的輪詢機制

5、熔斷器Hystrix解決了,微服務架構中伺服器雪崩現象

6、服務監控(單機Dashboard與叢集turbine),友善運維人員檢視微服務架構項目運作時,各個伺服器的運作狀态

7、服務配置中心(springcloud config),用來通過github統一管理各個微服務的配置檔案(yml檔案)

先來建立一個簡單的分布式項目,隻少有四個子產品

父工程:springcloud01

通用子產品(M):microservice-common

服務提供者(C):microservice-student-provider-1001

服務消費者(C):microservice-student-consumer-80

SpringCloud入門簡介(1)

首先第一個父工程,父工程是一個maven項目,後面的子項目都是springboot項目,是基于1.0的版本的

調整父工程的pom依賴

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.xy</groupId>
  <artifactId>springcloud01</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>springcloud01</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <druid.version>1.1.10</druid.version>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Edgware.SR4</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>1.5.13.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <!--  連接配接池  -->
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>${druid.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>
           

然後建立我們的通用子產品,添加pom依賴

<?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>
    <parent>
        <groupId>com.xy</groupId>
        <artifactId>springcloud01</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>microservice-common</artifactId>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

           

Student.java

package com.xy.microservicecommon.entity;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name="t_springcloud_student")
public class Student implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue
    private Integer id;
     
    @Column(length=50)
    private String name;
     
    @Column(length=50)
    private String grade;
     
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGrade() {
        return grade;
    }
    public void setGrade(String grade) {
        this.grade = grade;
    }
}
           

然後通用子產品不需要對資料庫進行操作,是以需要忽略jpa

在啟動類加上

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
           

建立服務提供者microservice-student-provider-1001

<?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>
    <parent>
        <groupId>com.xy</groupId>
        <artifactId>springcloud01</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.xy</groupId>
    <artifactId>microservice-student-provider-1001</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>microservice-student-provider-1001</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.xy</groupId>
            <artifactId>microservice-common</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.xy</groupId>
            <artifactId>microservice-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
           

application.yml配置檔案,如果項目啟動不了,報的是找不到yml檔案的話,可以把注釋删除試試

server:
  port: 1001
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_0524?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
           

StudentProviderController

package com.xy.microservicestudentprovider1001.controller;

import com.xy.microservicecommon.entity.Student;
import com.xy.microservicestudentprovider1001.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/student")
public class StudentProviderController {

    @Autowired
    private StudentService studentService;

    @PostMapping(value="/save")
    public boolean save(Student student){
        try{
            studentService.save(student);
            return true;
        }catch(Exception e){
            return false;
        }
    }
    @GetMapping(value="/list")
    public List<Student> list(){
        return studentService.list();
    }
    @GetMapping(value="/get/{id}")
    public Student get(@PathVariable("id") Integer id){
        return studentService.findById(id);
    }
    @GetMapping(value="/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id){
        try{
            studentService.delete(id);
            return true;
        }catch(Exception e){
            return false;
        }
    }
}
           

StudentRepository

package com.xy.microservicestudentprovider1001.repository;

import com.xy.microservicecommon.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Component;

public interface StudentRepository extends JpaRepository<Student, Integer>, JpaSpecificationExecutor<StudentRepository> {
}
           

StudentService

package com.xy.microservicestudentprovider1001.service;


import com.xy.microservicecommon.entity.Student;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import java.util.List;

@Component
public interface StudentService {
 
    public void save(Student student);
     
    public Student findById(Integer id);
     
    public List<Student> list();
     
    public void delete(Integer id);
}
           

StudentServiceImpl

package com.xy.microservicestudentprovider1001.service.impl;

import com.xy.microservicecommon.entity.Student;
import com.xy.microservicestudentprovider1001.repository.StudentRepository;
import com.xy.microservicestudentprovider1001.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentRepository studentRepository;

    @Override
    public void save(Student student) {
        studentRepository.save(student);
    }

    @Override
    public Student findById(Integer id) {
        return studentRepository.findOne(id);
    }

    @Override
    public List<Student> list() {
        return studentRepository.findAll();
    }

    @Override
    public void delete(Integer id) {
        studentRepository.delete(id);
    }

}

           

啟動類

package com.xy.microservicestudentprovider1001;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;


@EntityScan("com.xy.*.*")
@EnableEurekaClient
@SpringBootApplication
public class MicroserviceStudentProvider1001Application {
    public static void main(String[] args) {
        SpringApplication.run(MicroserviceStudentProvider1001Application.class, args);
    }
}

           

建立服務消費者microservice-student-consumer-80

pom依賴

<?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>
    <parent>
        <groupId>com.xy</groupId>
        <artifactId>springcloud01</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.xy</groupId>
    <artifactId>microservice-student-consumer-80</artifactId>
    <name>microservice-student-consumer-80</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.xy</groupId>
            <artifactId>microservice-common</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.xy</groupId>
            <artifactId>microservice-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
           

application.yml

server:
  port: 80
  context-path: /
           

SpringCloudConfig

package com.xy.microservicestudentconsumer80.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class SpringCloudConfig {
 
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

           

StudentConsumerController

package com.xy.microservicestudentconsumer80.controller;

import com.xy.microservicecommon.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
@RequestMapping("/student")
public class StudentConsumerController {

    private final static String SERVER_IP_PORT = "http://localhost:1001";
 
     @Autowired
     private RestTemplate restTemplate;
      
     @PostMapping(value="/save")
     private boolean save(Student student){
         return restTemplate.postForObject(SERVER_IP_PORT+"/student/save", student, Boolean.class);
     }
      
    @GetMapping(value="/list")
    public List<Student> list(){
        return restTemplate.getForObject(SERVER_IP_PORT+"/student/list", List.class);
    }
     
    @GetMapping(value="/get/{id}")
    public Student get(@PathVariable("id") Integer id){
        return restTemplate.getForObject(SERVER_IP_PORT+"/student/get/"+id, Student.class);
    }
     
    @GetMapping(value="/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id){
        try{
            restTemplate.getForObject(SERVER_IP_PORT+"/student/delete/"+id, Boolean.class);
            return true;
        }catch(Exception e){
            return false;
        }
    }
}
           

然後我們啟動1001端口的項目,jpa幫我們自動生成了表,在表裡加點資料,然後我們輸入

http://localhost:1001/student/list測試是否能通路,方法調用成功

SpringCloud入門簡介(1)

Eureka簡介:

Eureka是Netflix開發的服務發現架構,本身是一個基于REST的服務,主要用于定位運作在AWS域中的中間層服務,以達到負載均衡和中間層服務故障轉移的目的。SpringCloud将它內建在其子項目spring-cloud-netflix中,以實作SpringCloud的服務發現功能。

Eureka包含兩個元件:Eureka Server和Eureka Client。

Eureka Server提供服務注冊服務,各個節點啟動後,會在Eureka Server中進行注冊,這樣EurekaServer中的服務系統資料庫中将會存儲所有可用服務節點的資訊,服務節點的資訊可以在界面中直覺的看到。

Eureka Client是一個java用戶端,用于簡化與Eureka Server的互動,用戶端同時也就别一個内置的、使用輪詢(round-robin)負載算法的負載均衡器。

在應用啟動後,将會向Eureka Server發送心跳,預設周期為30秒,如果Eureka Server在多個心跳周期内沒有接收到某個節點的心跳,Eureka Server将會從服務系統資料庫中把這個服務節點移除(預設90秒)。

Eureka Server之間通過複制的方式完成資料的同步,Eureka還提供了用戶端緩存機制,即使所有的Eureka Server都挂掉,用戶端依然可以利用緩存中的資訊消費其他服務的API。綜上,Eureka通過心跳檢查、用戶端緩存等機制,確定了系統的高可用性、靈活性和可伸縮性。

類似zookeeper,Eureka也是一個服務注冊和發現元件,是SpringCloud的一個優秀子項目,不過比較坑的是,Eureka2版本已經停止更新了。但是Eureka1版本還是很穩定,功能足夠用,是以還是有必要學習下

這是eureka的作用流程圖

SpringCloud入門簡介(1)

然後我們在這個項目的基礎上繼續配置,建立一個項目microservice-eureka-server-2001

<?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>
    <parent>
        <groupId>com.xy</groupId>
        <artifactId>springcloud01</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>microservice-eureka-server-2001</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.23</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

           

application.yml配置類,如果啟動報錯嘗試把注釋去掉

server:
  port: 2001
  context-path: /
eureka:
  instance:
    hostname: localhost #eureka注冊中心執行個體名稱
  client:
    register-with-eureka: false     #false 由于該應用為注冊中心,是以設定為false,代表不向注冊中心注冊自己。
    fetch-registry: false     #false 由于注冊中心的職責就是維護服務執行個體,它并不需要去檢索服務,是以也設定為false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/       #設定與Eureka注冊中心互動的位址,查詢服務和注冊服務用到
           
package com.xy.microserviceeurekaserver2001;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class MicroserviceEurekaServer2001Application {
    public static void main(String[] args) {
        SpringApplication.run(MicroserviceEurekaServer2001Application.class, args);
    }

}
           

輸入:http://localhost:2001/

就能通路注冊中心

然後我們向Eureka中注冊服務提供者

這裡的服務者是microservice-student-provider-1001,是以向這個項目添加pom依賴

<!--添加注冊中心Eureka相關配置-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
           

并且加上application.yml配置檔案,一樣的如果報配置檔案的問題請删除注解試試

eureka:
  instance:
    hostname: localhost  #eureka用戶端主機執行個體名稱
    appname: microservice-student  #用戶端服務名
    instance-id: microservice-student:1001 #用戶端執行個體名稱
    prefer-ip-address: true #顯示IP
  client:
    service-url:
      defaultZone: http://localhost:2001/eureka   #把服務注冊到eureka注冊中心

           

然後向你的服務者的啟動類中添加一個注解,掃描你的包

@EntityScan("com.xy.*.*")
           
<option name="configurationTypes">  
      <set>  
        <option value="SpringBootApplicationConfigurationType" />  
      </set>  
 </option>