Spring Cloud微服务-16小时搭建-实战教程(上)

前言

微服务架构以及Spring Cloud近年来越来越流行。而Spring Cloud包含内容十分庞杂,要想完全掌握需要花费大量的时间精力。学习一门技术最好的办法,是通过简单实践,搞清楚如何使用该技术的核心功能,同时把主要组件的关系搞明白。随后应用于自己的项目实践中,在实践过程中根据需要,引入各种特性,同时在需要深入研究的部分做深入研究,在遇到问题时刨根问底。真正使用至少1年半载才能谈真正掌握。而面对spring cloud全家桶式的框架,更是如此。不要被各种没听说过的名词吓到,其实spring cloud里每个框架都对应解决一个微服务中的问题,我们学习时也应该先抓住其中几个最核心的问题入手,通过实践,逐步上手,培养信心。如果一上来就通盘学习,难免会陷入贪多嚼不烂,自信受挫的窘境。

本教程紧抓住Spring Cloud中最核心的几个概念,结合实践讲解。让你能够在很短的时间内,自己搭建起一个微服务架构的系统,体验微服务中的核心组件。当然这只是个敲门砖,接下来你可以基于本教程搭建起来的微服务系统,继续学习更多的spring cloud知识。从0到1已经完成,从1到10000当然也没有那么难了。

一般来说,大家对微服务第一感觉,就是把以往一个大的系统拆解为若干个业务相对独立的小系统,小系统对外提供服务,通过相互调用完成完整的业务。这个理解是没错的(但肯定是不够的),这也是微服务系统要解决的核心问题---服务的注册和发现。此外,每个微服务都需要做到负载均衡,并且由于相互间调用频繁,一旦出现问题要能够容错。

本文第一部分所要讲解的也就是如下几个知识点:

  • 服务注册中心
  • 微服务注册
  • 服务发现与消费

正文

接下来直接进入实践部分,假定读者已经具备spring boot的基础知识,并且也已经了解微服务的基本概念。本文代码采用相关版本如下:

Spring Boot 2.0.2.RELEASE
Spring Cloud Finchley.SR2
Spring Cloud Netflix 2.0.1.RELEASE

Spring Cloud最新版本现在是Greenwich,对应的Spring Boot版本是2.1.x,你也可以尝试使用此版本。

我例子中构建工具使用gradle。当然你也可以使用Maven。

本文的实践中,我们以一个音乐网站举例,搭建三个应用,都采用集群的方式,分别为:

  • 名为beyond的服务注册中心
  • 名为song的歌曲服务
  • 名为lyric的歌词服务

song和lyric会注到服务注册中心上,song应用则会调用lyric应用的服务接口,完成自己的业务。

本文内容预计会耗费你不超过8个小时的时间去学习和实践。

一、服务注册中心

服务注册中心是微服务的核心,所有的服务只有注册到服务注册中心上,才能成为微服务中的一员,彼此调用。本节,我们将使用Spring Cloud Eureka来搭建服务注册中心。

1.1 创建一个Spring Boot的web项目。

1.2 修改构建文件build.gradle,添加对Spring Cloud的支持以及Eureka的依赖。

1.2.1添加依赖管理插件

apply plugin: 'io.spring.dependency-management'

1.2.2添加版本号变量

ext {
springCloudVersion = 'Finchley.SR2'
springCloudNetflixVersion = '2.0.1.RELEASE'
}

1.2.3添加依赖管理

dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-netflix:${springCloudNetflixVersion}"
   }
}

1.2.4添加Eureka server端依赖

dependencies {
    compile(
    	'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
        )
}

build.gradle完成代码

buildscript {
	ext {
		springBootVersion = '2.0.2.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
		classpath("org.springframework:springloaded:1.2.7.RELEASE")
	}
}

apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.liyiming.beyond'
version = '1.0'
sourceCompatibility = 1.8

repositories {
	mavenCentral()
}

configurations {
	providedRuntime
}

ext {
	springCloudVersion = 'Finchley.SR2'
	springCloudNetflixVersion = '2.0.1.RELEASE'
	junitVersion = '4.12'
	lombokVersion = '1.18.4'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-netflix:${springCloudNetflixVersion}"
	}
}

dependencies {
	compile(
			'org.springframework.boot:spring-boot-starter-web',
			'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server',
	)
	providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}

1.3 代码修改

boot主类添加@EnableEurekaServer

@EnableEurekaServer
@SpringBootApplication
public class BeyondApplication {

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

1.4、配置文件

为了测试高可用的配置中心,我们将启动两个eureka server服务,单机模拟集群环境。为了方便测试,我们创建两个配置文件,启动时分别使用。

先创建application-peer1.yml,内容如下:

server:
  port: 1111
  tomcat:
    uri-encoding: UTF-8
eureka:
  client:
    serviceUrl:
        defaultZone: http://peer2:1112/eureka/
  instance:
    hostname: peer1
spring:
  freemarker:
      template-loader-path: classpath:/templates/
      prefer-file-system-access: false
  application:
    name: eureka-server

在创建一个application-peer2.yml,内容如下

server:
  port: 1112
  tomcat:
    uri-encoding: UTF-8
eureka:
  client:
    serviceUrl:
        defaultZone: http://peer1:1111/eureka/
  instance:
    hostname: peer2
spring:
  freemarker:
    template-loader-path: classpath:/templates/
    prefer-file-system-access: false
  application:
    name: eureka-server

说明:

1、peer1端口使用1111,peer2使用端口1112.

2、设置hostname分别为peer1,peer2

3、defaultZone。peer1指向peer2,peer2指向peer1。互相注册到对方。

4、spring.application.name。为服务命名。在eureka上同名的服务属于一个服务集群。也可以用eureka.instance.appname。但spring.application.name 优先级更高。

5、spring.freemarker。配置好freemarker后,才可以正确显示eureka server的控制台页面。

 

1.5修改hosts文件

我是mac环境,打开/etc/hosts,配置peer1和peer2,如下:

127.0.0.1 peer1

127.0.0.1 peer2

 

1.6启动调试

为了实验集群的效果,我们启动两个Eureka的节点。因此在1.4中编写了两个配置文件,我们通过在IDEA中的配置,分别以这两个配置文件启动项目。IDEA中新建一个Run/Debug Configurations,选择Spring Boot,然后按照下图填好,注意红框,手动填入pee1。保存后,以同样的方式再创建一个Run/Debug Configuration,唯一不同是填入peer2。然后分别启动peer1和peer2. 如果能够正常启动,并且能看到启动log中有一行:The following profiles are active: peer1(或者是peer2)。说明已经按照不同配置文件启动成功了。

Spring Cloud微服务-16小时搭建-实战教程(上)_第1张图片

接下来我们打开浏览器,输入http://peer1:1111或者http://peer2:1112/,看到如下管理界面,说明Eureka已经启动成功。

Spring Cloud微服务-16小时搭建-实战教程(上)_第2张图片

图为我访问peer2看到的界面。可以看到Eureka-Server注册上来两个实例。另外可以看到注册上来的副本有peer1,并且是avaliable副本

至此我们已经搭建起Eureka服务注册中心集群,下一节我们来学习如何把服务注册上来。

二、微服务注册

本节我们新建一个工程,并且把他注册到刚刚搭建好的服务注册中心上。好吧,既然是实践,为了更真实,我们需要假想一个项目。我爱好音乐,假设我们建设一个音乐网站,其中一个微服务是歌曲(song),另外一个微服务是歌词(lyric)。我们先创建一个名为song的Spring Boot项目。创建完成后,按如下步骤操作。

2.1修改构建文件build.gradle

首先按照1.2.1到1.2.3进行修改。然后添加Eureka客户端的依赖:

dependencies {
    compile(
    		'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
            )
}

2.2配置文件

为了演示负载均衡,我们将会以集群的形式启动song服务,所以此处我们同样创建两个配置文件。

application-song1.yml

server:
  port: 9081
  tomcat:
    uri-encoding: UTF-8

eureka:
  client:
    service-url:
          defaultZone: http://peer1:1111/eureka/,http://peer2:1112/eureka/
spring:
  application:
    name: song

application-song2.yml

server:
  port: 9082
  tomcat:
    uri-encoding: UTF-8

eureka:
  client:
    service-url:
          defaultZone: http://peer1:1111/eureka/,http://peer2:1112/eureka/
spring:
  application:
    name: song

两份配置文件,除了server.port不同,其他全部一样。

注意配置项eureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/。这个配置项告诉了应用Eureka的地址,我们把之前创建的Eureka集群两台机器的地址都配上,以让应用注册到服务注册中心上。另外spring.application.name需要一样,这样Eureka才会认为两个song的应用属于同一个集群。

2.3编写测试代码

创建一个controller

添加一个接口:

@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello(){
    return "song application say hello";
}

2.4启动调试

按照上节启动注册中心集群的方式创建两个Run/Debug Configurations,分别使用两个不同的配置文件,然后启动,此时我们再次访问Eureka服务,看到如下界面:

Spring Cloud微服务-16小时搭建-实战教程(上)_第3张图片

可以看到song应用启动成功,有两个实例。

我们访问任意一个,比如localhost:9081/hello, 可以看到正确输出song application say hello。

至此song微服务已经成功注册到Eureka上,并且自己也是可以被成功访问到的。接下来我们将会进入最核心的服务发现与消费。

三、服务发现与消费

Spring Cloud中,服务发现由Eureka实现,而消费则是由Ribbon完成。Ribbon通过Eureka获取服务清单,轮询访问实现负载均衡。不过本文不展开讲解Ribbon的使用,而是讲解Ribbon更高层的封装Feign。Feign整合了Ribbon和Hystrix(容错处理),并且它还提供了声明式的web服务客户端定义。使用Feigin,只需要按照Spring MVC的注解方式,在调用方service层按照服务提供方的接口定义,再做一次接口声明即可。调用时,只需要调用service接口中声明的方法即可。http请求发送、负载均衡无需关注,feign都帮你处理好了。所以在实践中一般都是直接使用Feign。关于Feign的特点和简单用法可以参照下图:

Spring Cloud微服务-16小时搭建-实战教程(上)_第4张图片

使用Feign也很简单,上图已经给出了简单用法,下面我将按步骤讲解。

3.1 创建服务提供方lyric应用

我们再创建一个lyric应用,提供歌词服务,而song应用会调用lyric的服务接口。创建lyric应用的步骤同第二章讲解的创建song应用一样。只需要修改配置文件端口以及修改application.name为lyric。

同样也为lyric创建一个controller,添加一个接口,用以测试:

@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello(){
    return "lyric application say hello";
}

我们也同样启动起来两个实例,此时打开Eureka的管理界面,可以看到多了lyric的应用:

Spring Cloud微服务-16小时搭建-实战教程(上)_第5张图片

接下来我们对song应用做一些修改,通过Feign调用lyric应用的hello接口。

3.2 为song添加Feign依赖

spring cloud的相关依赖添加请参考上面章节,这里默认已经添加。使用Feign只需要再添加如下依赖:

dependencies {
    implementation('org.springframework.cloud:spring-cloud-starter-openfeign')
}

3.3 接口声明代码

3.3.1 song的boot主类增加注解

声明本应用是一个Feign的客户端

@EnableFeignClients

3.3.2  声明被调用的接口

增加service接口类,根据被调用方的接口定义,进行声明,代码示例如下:

@Service
@FeignClient("lyric")
public interface LyricServiceFeign {
    @RequestMapping("/hello")
    String hello();
}

@FeignClient("lyric"),lyric是服务方注册到Eureka的application 名称,即微服务的名称。

@RequestMapping("/hello"),声明了被调用方的接口地址。

3.4 接口调用

在需要调用服务方接口的类中,注入上步的接口类LyricServiceFeign:

@Autowired
LyricServiceFeign lyricServiceFeign;

直接调用接口的方法即可

lyricServiceFeign.hello()

此时feign会向服务方(lyric应用)发起http请求,而且负载均衡。

完全代码如下:

@Autowired
LyricServiceFeign lyricServiceFeign;

@RequestMapping(value = "/LyricHello", method = RequestMethod.GET)
public String knowledgeHello(){
    return "song invoke lyric service , "+lyricServiceFeign.hello();
}

3.5 测试

重启song应用,访问song应用的接口 http://localhost:9081/LyricHello,可以看到页面显示song invoke lyric service , lyric application say hello。并且通过多次访问,可以看到lyric不同节点均匀打印日志,说明通过feign对服务的调用是负载均衡的

四、总结

学习到这里,我们掌握了如何通过Eureka搭建服务注册中心;应用如何注册到服务注册中心;微服务之间如何通过Feign进行调用。至此,Spring Cloud最核心的内容已经通过实践,正常运转起来了。不过Spring Cloud远不止这些内容,接下来我们还会讲解网关以及分布式服务跟踪的相关实践。此外关于Eureka和Feign还需要看更多的资料,学习的更为深入。另外Feign封装的Ribbon和Hystrix,如果有时间,也是很有必要单独学习的。

相信本文的实践在8小时内是可以完成的,甚至于都用不上8个小时,但是我们的收获还是很大的,微服务的核心架子已经搭建了起来,组件间如何配合工作也很清楚。后一部分的学习是基于本文搭建起来的环境继续实践的,所以我们一定要一步步夯实,从核心内容扩散开来,去接触更多的知识。

 

你可能感兴趣的:(Spring,Cloud实践相关)