SpringBoot整合SpringCloud分布式服务

一、SpringCloud是什么

度娘:Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署

个人理解:可以发现SringCloud拥有服务发现注册、负载均衡的功能,而这两个功能,正好是dubbo所具有的功能,SpringCloud的出现,目的就是消灭分布式框架被dubbo霸气独占的局面,SpringCloud在实现服务发现注册和管控的基础上,增加了配置中心、消息总线、负载均衡、断路器、数据监控等功能。

二、SpringCloud与Dubbo的功能对比

背景

Dubbo,是阿里巴巴服务化治理的核心框架,并被广泛应用于阿里巴巴集团的各成员站点,经过不断优化,阿里把自己的核心框架对外进行开源使用,这也是阿里近几年在国内开源社区影响力较大的原因,毕竟阿里在开源社区不少做贡献,例如JStorm捐赠给Apache并加入Apache基金会等,阿里在国内眼中,已经不仅仅是一家电商公司,阿里的生态系统,让国人为之震撼,人工智能、智能点餐、无人酒店,让阿里逐步变成了一家科技领头公司。

Spring Cloud,从命名就可以知道,它是Spring Source的产物,Spring社区的强大背书可以说是Java企业界最有影响力的组织了,除了Spring Source之外,还有Pivotal和Netfix是其强大的后盾与技术输出。其中Netflix开源的整套微服务架构套件是Spring Cloud的核心。

如果拿Dubbo和Netflix对比,dubbo在国内的影响力无疑是最大的,而Netflix 面向的是国际,在国际影响力上,Netflix 无疑是大佬。无论出身如何,这些架构都能在处理分布式问题时,提供很大的帮助。

功能架构

下表是dubbot和SpringCloud功能架构对比表

包含功能 Dubbo SpringCloud
服务注册中心 Zookeeper Spring Cloud Netflix Eureka
服务调用方式 RPC REST API
服务网关 无 Spring Cloud Netflix Zuul
断路器 不完善 Spring Cloud Netflix Hystrix
分布式配置 无 Spring Cloud Config
服务跟踪 无 Spring Cloud Sleuth
消息总线 无 Spring Cloud Bus
数据流 无 Spring Cloud Stream
批量任务 无 Spring Cloud Task
more…… more…… more……

三、开始整合SpringCloud

搭建maven多模块工程(分别为服务注册中心工程eureka-server,服务提供者provider-ticket,服务消费者consumer-user),项目架构图如下

搭建父工程

1.搭建父工程SpringCloudDemo,pom文件配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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.yang.study</groupId>
<artifactId>SpringCloudDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>eureka-server</module>
<module>consumer-user</module>
<module>provider-ticket</module>
</modules>
<properties>
<spring-cloud.version>Edgware.SR3</spring-cloud.version>
</properties>
</project>

搭建服务注册中心

2.搭建服务注册中心ureka-server,pom文件配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yang.study</groupId>
<artifactId>SpringCloudDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.yang.study</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server</name>
<!-- 添加相关依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</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>
</project>

3.编写全局配置文件application.yml

1
2
3
4
5
6
7
8
9
10
server:
port: 8761
eureka:
instance:
hostname: eureka-server # eureka实例的主机名
client:
register-with-eureka: false #不把自己注册到eureka上
fetch-registry: false #不从eureka上来获取服务的注册信息--不检索服务
service-url:
defaultZone: http://localhost:8761/eureka/

4.在java文件夹下创建包名org.eureka.server,并创建服务启动类EurekaServerApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
package org.eureka.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

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

5.启动服务启动类,浏览器访问localhost:8761,显示如下

编写服务提供者

6.创建服务提供者工程provider-ticket,看标题就知道,又是售票的,哈哈,pom文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<groupId>com.yang.study</groupId>
<artifactId>provider-ticket</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>provider-ticket</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>Edgware.SR3</spring-cloud.version>
</properties>
<!--这里表明为客户端 -->
<dependencies>
<!-- 添加web支持的starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</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>

7.全局配置文件如下application.yml,Spring.application.name是应用的名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#服务启动端口号
server:
port: 8002
spring:
application:
name: provider-ticket

#注册提供配置
eureka:
instance:
prefer-ip-address: true # 注册服务的时候使用服务的ip地址
client:
service-url: #注册到指定的服务中心
defaultZone: http://localhost:8761/eureka/

8.创建常用包名(org.provider.controller\org.provider.service\org.provider.service\org.provider.service.impl),在service创建售票服务类接口。

1
2
3
4
5
6
7
8
9
10
package org.provider.service;

/**
* 售票类
* @author yzx96
*
*/
public interface TicketService{
public String buyTicket();
}

9.在service.impl创建服务实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package org.provider.service.impl;

import org.provider.service.TicketService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class TicketServiceImpl implements TicketService {
@Value("${server.port}")
private String port;
public String buyTicket() {
System.out.println(port);
return "《疯狂的石头》";
}

}

10.在controll创建控制器TicketController,自己测试接口是否可用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package org.provider.controller;
import org.provider.service.TicketService;
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.RestController;

@RestController
public class TicketController {

@Autowired
private TicketService ticketService;

// SpringCloud 整合微服务时是按照轻量级的HTTP进行通信
@GetMapping("/ticket")
public String getTicker(){
return ticketService.buyTicket();

}
}

11.在ticket创建服务启动类ProviderApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package org.provider.ticket;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableEurekaClient//本服务启动后会自动注册进eureka服务中
@ComponentScan("org.provider") //类似于Spring的基础类扫描包,用来扫描实体,接口和控制器
public class ProviderApplication {

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

12.右键启动服务启动类,查看启动日志

13.访问服务注册中心,查看

14.访问本地接口,看服务是否可用

编写服务消费者

15.创建服务消费者工程consumer-user,pom文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<groupId>com.yang.study</groupId>
<artifactId>consumer-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer-user</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>Edgware.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
</project>

16.消费者工程全局配置文件application.yml如下

1
2
3
4
5
6
7
8
9
10
11
12
spring:
application:
name: consumer-user
server:
port: 8200

eureka:
instance:
prefer-ip-address: true # 注册服务的时候使用服务的ip地址
client:
service-url:
defaultZone: http://localhost:8761/eureka/

17.创建包名(org.consumer.control\org.consumer.user),编写控制器UserController,并注入RestTemplate对象,RestTemplate对象用于在SpringCloud发现服务并调用来用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.consumer.control;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
* @author yzx96
*
*/
@RestController
public class UserController {

@Autowired
RestTemplate restTemplate;

@GetMapping("/buy")
public String butTicket(String name){
String s = restTemplate.getForObject("http://PROVIDER-TICKET/ticket/", String.class);
return name+"购买了"+s;
}
}

18.编写消费者服务启动类ConsumerApplication,并运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.consumer.user;

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.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;
@ComponentScan("org.consumer")
@EnableDiscoveryClient//开启发现服务功能
@SpringBootApplication
public class ConsumerApplication {

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

@LoadBalanced//开启负载均衡机制
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
// 用来发送http请求
}
}

19.查看服务注册中心

20.访问服务地址,进行消费者调用验证,验证成功图如下,SpringCloud搭建完成

四、总结注意点及源码下载地址

1.消费者和服务提供者的全局配置文件中需要配置注册中心的地址:为eureka.client.service-url-defaultZone

2.消费者调用服务提供者接口,采用RestTemplate对象,不懂的可以百度查一下

源码下载地址(gitHub)点击我下载,小心你的鼠标