1. 程式人生 > >SpringCloud搭建基於Eureka服務中心的微服務體系

SpringCloud搭建基於Eureka服務中心的微服務體系

一、單體系統與微服務體系

在以往傳統的企業系統架構中,所有的業務介面都被集中在同個單體應用中。在業務需求不龐大的情況下,這樣的系統架構在開發、測試、部署時都還比較方便,但是隨著企業的發展,更多的業務需求也隨之而來,單體應用為了滿足這些需求就必須增加相應的業務模組,單體應用就會顯得越來越臃腫;由於單體應用的所有業務都執行在同一個系統程序中,即使我們只是修改了一個很小的功能,也需要將整個專案全量更新上線,進而導致影響其他功能;單體應用的架構和業務邏輯對所有參與的開發者都是開放的,這就帶來了一定的風險,某個開發者的一個誤操作就有可能影響整個系統。

基於以上幾點,分散式的微服務體系應運而生,它將系統內的各個功能模組拆分成不同的服務,這些服務都可以獨立部署和擴充套件;由於各服務都執行在各自的程序中,每個服務的更新或是中斷都不會影響其他服務;不同的業務可以根據不同的需求去自定義技術平臺、伺服器配置、資料庫配置等,從而避免出現“殺雞用牛刀”等情況;開發者只需根據業務劃分,維護自己負責的服務,降低了開發風險。

二、SpringCloud簡介

SpringCloud是一個基於SpringBoot的微服務架構開發工具。他提供了微服務開發所需的配置管理、服務發現、斷路器、智慧路由、微代理、控制匯流排、全域性鎖、決策競選、分散式會話和叢集狀態管理等元件。最重要的是,跟spring boot框架一起使用的話,會讓你開發微服務架構的雲服務非常好的方便。SpringBoot旨在簡化建立產品級的 Spring 應用和服務,簡化了配置檔案,使用嵌入式web伺服器,含有諸多開箱即用微服務功能。

三、核心結構分析

整個微服務體系主要由三個核心模組組成:Eureka服務註冊中心、服務提供者、服務消費者。

Eureka服務註冊中心:Eureka提供的服務端,用於註冊、發現、

他們的邏輯關係如下圖所示,稍後會結合具體實現,進行分析。

四、具體實現

1、建立Eureka服務註冊中心:

1.1 建立SpringBoot工程

以idea為例,建立一個SpringBoot工程,在選擇依賴的時候,在Cloud Discovery下找到EureKa Server並勾選,這樣選擇之後,idea就會幫助我們補充好pom中需要的依賴,其他一路next即可;

1.2 配置application.properties:

server.port:服務監聽的埠
eureka.instance.hostname:eureka例項的主機名稱;
eureka.client.register-with-eureka:是否將本專案作為服務註冊到服務中心,由於本專案就是服務中心,所以就設定為false;
eureka.client.fetch-registry:是否需要檢索服務,這裡也不需要;
eureka.client.service-url.defaultZone:eureka服務中心的訪問地址;
spring.application.name:eureka服務中心的應用名稱;

server.port=1112

eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

spring.application.name=eureka_server

1.3 設定Application,開啟EurekaServer:

package com.eureka_center;

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

@SpringBootApplication
@EnableEurekaServer
public class EurekaCenterApplication {

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

設定完成後,執行專案,看到如下介面證明執行成功:

2、建立並註冊服務提供者:

2.1 建立一個Spring Boot應用

可以直接通過IDE建立,也可以進入https://start.spring.io/進行建立;

2.2 配置pom.xml

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

	<groupId>com.service_provider</groupId>
	<artifactId>service_provider</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>service_provider</name>
	<description>service_provider for Spring Cloud</description>

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

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.SR1</spring-cloud.version>
	</properties>

	<dependencies>

		<!--全棧web開發模組,包含嵌入式Tomcat、SpringMVC-->
		<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>

		<!--Eureka服務端依賴-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
			<version>1.3.6.RELEASE</version>
		</dependency>

	</dependencies>


	<!--Spring Cloud 依賴-->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>


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


</project>

這裡有一點要注意,就是SpringCloud的版本要與springboot相對應,我這裡使用的SpringBoot的版本是2.0.5.RELEASE對應的SpringCloud版本是Finchley.SR1。(可以直接套用之前配置eureka服務中心的SpringCloud)

2.3 配置application.properties:

server.port=9001
spring.application.name=hello-service
eureka.client.service-url.defaultZone=http://localhost:1112/eureka/

2.4 新建一個RestController

DiscoveryClinet用於幫助客戶端與eureka server互相協作:

1、向server註冊服務例項;
2、向server服務租約;
3、服務關閉期間,向server取消租約;
4、查詢服務例項列表;

這裡建立了一個RestController,查詢服務例項列表並列印所有服務,並且返回HelloWorld;

package com.service_provider.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


/**
 *
 * @author yuyan
 * @create 2018-10-23 14:31
 **/
@RestController
public class HelloController {

   private Logger logger = LoggerFactory.getLogger(this.getClass());

   @Autowired
   DiscoveryClient client;

   @RequestMapping("/hello")
   public String index(){
      for(String service:client.getServices()){
         List<ServiceInstance> services  = client.getInstances(service);
         for(ServiceInstance serviceInstance:services){
            logger.info("/hello, host:" + serviceInstance.getHost() + ", service_id:" + serviceInstance.getServiceId());
         }
      }

      return "Hello World";
   }

}

2.5 設定Application,通過EnableDiscoveryClient註解,讓該應用註冊成為Eureka客戶端應用;

package com.service_provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class ServiceProviderApplication {

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

設定完成後,執行專案,執行成功後就可以在EurekaCenter的管理介面上,檢視到服務資訊:

3、建立服務消費者

3.1 建立一個Spring Boot應用

3.2 配置pom.xml:

同樣,需要引入SpringCloud和Eureka服務端依賴,這裡多引入了一個ribbon依賴,用於實現客戶端的負載均衡,關於負載均衡,會在後面進行解釋;

<?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.ribbon_consumer</groupId>
	<artifactId>ribbon_consumer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>ribbon_consumer</name>
	<description>ribbon_consumer</description>

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

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.SR1</spring-cloud.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.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
			<version>1.3.6.RELEASE</version>
		</dependency>


		<!--Finchley的SpringCloud不能使用這個-->
		<!--<dependency>-->
			<!--<groupId>org.springframework.cloud</groupId>-->
			<!--<artifactId>spring-cloud-starter-ribbon</artifactId>-->
		<!--</dependency>-->

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</dependency>
		<!--<dependency>-->
			<!--<groupId>org.springframework.cloud</groupId>-->
			<!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
		<!--</dependency>-->



	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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


</project>

3.3 配置application.properties:

server.port=9000
spring.application.name=consumer
eureka.client.service-url.defaultZone=http://localhost:1112/eureka/

3.4 配置Application主類:

與服務提供者類似,通過EnableDiscoveryClient註解,讓服務消費者註冊成為Eureka客戶端應用,並且在該主類中建立RestTemplate的SpringBoot例項,通過LoadBalanced開啟客戶端負載均衡;

package com.service_consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class ServiceConsumerApplication {

	@Bean
	@LoadBalanced//開啟客戶端負載均衡
	RestTemplate restTemplate(){
		return new RestTemplate();
	}

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

3.5 建立一個RestController,用來呼叫服務提供者的服務:

通過restTemplate以get方式呼叫服務名稱為HELLO-SERVICE的hello介面,並且返回介面的結果;這裡使用的是服務名,而不是具體的ip或是域名作為訪問地址,服務名可以通過Eureka控制檯獲取,或者通過DiscoveryClient獲得服務列表;

package com.service_consumer.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class ConsumerController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/hello_consumer", method = RequestMethod.GET)
    public String helloConsumer(){
       
        return restTemplate.getForEntity("http://HELLO-SERVICE/hello/",String.class).getBody();

    }

}


配置完成後,執行專案,執行成功後,開啟Eureka服務控制檯:

可以看到現在有兩個應用,分別是一個消費者和一個提供者,現在訪問localhost:9000/hello_consumer:

成功的返回了服務提供者的返回值:Hello World

至此,一個基於基於Eureka服務中心的微服務體系就搭建成功了!