目录
一.微服务架构衍变
二.SpringCloud 概述
三.SpringCloud 实战
1.1 单体架构
1.2 SOA 架构
1.3 微服务架构
“微服务”最初是由 软件工程师 Martin Fowler 2014 年写的《MicroServices》中提出来的
微服务架构是复杂的业务组件和,实际上也是一种面向服务的体现,他说SOA架构的一种实现,但是相比传统的SOA架构来讲它更为轻便】敏捷和简单。微服务架构的风格,就是将单一程序开发成一个微服务,每个微服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP RESTFUL API.这些服务围绕业务能力来划分构建的,并通过完全自动化部署机制来独立部署,这些服务可以使用不同的编程语言,以及不同数据存储技术,以保证最低限度的中式管理
优点:
1,由于每个服务都是独立并且微小的,由单独的团队负责,仍然可以采用敏捷开发模式,自由的选择合适的技术,甚至可以重写老服务,当然也要遵守统一的API约定
2.每一个微服务都是独立部署的,可以进行快速迭代部署,根据各自服务需求选择合适的虚拟机和使用最匹配的服务资源要求的硬件
3.降低系统之间的耦合性,因为采用HTTP方式交互,各个微服务可以使用不同的编程语言实现
缺点:
1.微服务应用作为分布式系统带来了复杂性。各个微服务进行分布式独立部署,当进行模块调用的时候,分布式变的更加麻烦
2.微服务架构一般使用各个独立数据库,分布式事务的实现更具挑战性。
3.测试微服务变的复杂,当一个服务依赖另一个服务时,测试时需要另一个服务的支持
4.部署基于微服务的应用也很复杂,独立微服务的部署不但变得复杂,而且需要更高级别的自动化
概述:
Spring Cloud的首要目标就是通过提供系列开发组件和框架,帮助开发者迅速搭建分布式的微服务系统。Spring Cloud是通过包装其它技术框架来实现的,例如包装开源的Netflix oss组件,实现了一套基于注解、java配置和基于模板开发的微服务框架。springCloud 框架来自于Spring Resources社区,由Pivotal和Netflix两大公司和其他开发者提供技术上的更新迭代
SpringCloud 是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、短路器、数据监控等,都可以用SpringBoot 的开发风格做到一键启动和部署。springcloud是基于springboot。
2.1 SpringCloud 的特性
Spirng Cloud专注于提供良好的开箱即用经验的典型用例和可扩展性机制覆盖。
分布式/版本配置
服务注册和发现
路由
service - to - service调用
负载均衡
断路器
分布式消息传递
2.2 SpringCloud 的组成
利用Eureka组件可以很轻松地实现服务的注册和发现的功能
2.熔断组件Hystrix
它提供了熔断功能,能够组织分布式系统中出现联动故障
3.负载均衡组件Ribbon
Ribbon是将负载均衡逻辑封装在客户端中,并且运行在客户端的进程里
4.声明式调用Feign
Feign使得服务调用变得更加简单优雅
5.路由网关zuul
zuul作为微服务系统的网关组件,用于构建边界服务,致力于动态路由、过滤、监控、弹性伸缩和安全
6.Spring Cloud Config
config server可以从本地仓库读取配置文件,也可以从远处git仓库读取,是SpirngCloud分布式开发下的配置中心组件
2.3 SpringCloud 的版本
2.4 SpringCloud 和 Dubbo 的比较
springcloud的通信方式大多数是基于http restful风格的,服务与服务之间无关、无耦合。由于采用的是http rest,此服务无关乎语言和平台,只需要提供API接口就可以实现相互调用。dubbo的通信方式基于远程调用,对接口、平台和语言有较强依赖,如果需要实现跨平台代用服务,需要额外的中间件
基于RPC协议的dubbo速率上要比基于http的springcloud效率高很多
3.1 创建父工程
创建父工程:micro-service-parent,通过父工程统一管理 SpringCloud 组件的版本号。我 使 用 jdk 为 1.8 版 本 , springBoot 为 2.0.6.RELEASE 版 本 , SpringCloud 为Finchley.RELEASE 版本。
使用 IDEA 创建 spring 实例工程,如图:
修改 Pom 文件如下:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.0.6.RELEASE
com.spring.microservice
micro-service-parent
0.0.1-SNAPSHOT
micro-service-parent
Demo project for Spring Boot
micro-service-registry
micro-service-publish
micro-service-consumer
micro-service-feign
micro-service-zull
1.8
Finchley.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
3.2 Eureka
3.2.1 Eureka 概述
和 Zookeeper 类似,Eureka 是一个用于服务注册和发现的组件。Eureka 分为 Eureka Server 和 Eureka Client,Eureka Server 为 Eureka 服务注册中心,Eureka Client 为 Eureka客户端。
服务注册是指向服务注册中心注册一个服务实例,服务提供者将自己的服务信息(如服务名、IP地址等)告知服务注册中心。服务发现是指当服务消费者需要另一个服务时,服务注册中心能够告知服务消费者它所要消费服务的实例信息(如服务名、地址等)。通常情况下一个服务既是服务提供者,也是消费者。服务消费者一般使用http协议或者消息组件这种轻量级的通信机制来进行服务消费
3.2.2 注册中心 Eureka Server
创建 micro-service-parent 子工程 micro-service-registry,并依赖 eureka-server。
4.0.0
com.spring.microservice
micro-service-parent
0.0.1-SNAPSHOT
com.spring.microservice
micro-service-registry
0.0.1-SNAPSHOT
micro-service-registry
jar
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.boot
spring-boot-starter-test
test
#注册中心端口
server.port=8081
#设置当前实例的主机名称
eureka.instance.hostname=localhost
#默认是启动服务注册的 此处关闭服务注册 表示不向注册中心注册自己
eureka.client.registerWithEureka=false
#由于注册中心的职责是维护服务实例,不需要检索服务,所以设置为 false
eureka.client.fetch-registry=false
#注册中心服务 URL
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${s
erver.port}/eureka/
#注册中心服务名
spring.application.name=eurka-server
3.1.3 服务发布 Eureka Clinet
修改 pom 文件依赖信息:
4.0.0
com.spring.microservice
micro-service-parent
0.0.1-SNAPSHOT
com.spring.microservice
micro-service-publish
0.0.1-SNAPSHOT
micro-service-publish
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-test
test
#指定服务端口
server.port=8082
#指定服务名称
spring.application.name=service-hi
#指定服务注册中心地址
eureka.client.service-url.defaultZone=http://localhost:8081/eureka/
@SpringBootApplication
@EnableEurekaClient
public class MicroServicePublishApplication {
public static void main(String[] args) {
SpringApplication.run(MicroServicePublishApplication.class, args);
}
}
3.1.4 Eureka Server 的高可用
#注册中心端口
server.port=8181
#设置当前实例的主机名称
eureka.instance.hostname=server
#默认是启动服务注册的 此处关闭服务注册 表示不向注册中心注册自己
eureka.client.registerWithEureka=false
#由于注册中心的职责是维护服务实例,不需要检索服务,所以设置为 false
eureka.client.fetch-registry=false
#注册中心服务 URL
eureka.client.service-url.defaultZone=http://localhost:8081/eureka/
#注册中心服务名
spring.application.name=eurka-server
#注册中心端口
server.port=8081
#设置当前实例的主机名称
eureka.instance.hostname=server2
#默认是启动服务注册的 此处关闭服务注册 表示不向注册中心注册自己
eureka.client.registerWithEureka=false
#由于注册中心的职责是维护服务实例,不需要检索服务,所以设置为 false
eureka.client.fetch-registry=false
#注册中心服务 URL 此处写其他注册中心服务 URL
eureka.client.service-url.defaultZone=http://localhost:8181/eureka/
#注册中心服务名
spring.application.name=eurka-server
3.1.5 Eureka Client 的高可用
修改 application.properties 文件,端口为 8089:
#指定服务端口
server.port=8089
#指定服务名称
spring.application.name=service-hi
#指定服务注册中心地址
eureka.client.service-url.defaultZone=http://localhost:8081/eureka/
3.3 Ribbon
3.2.1 Ribbo 概述
负载均衡是指将负载分摊到多个执行单元上,常见的负载均衡有两种方式。一种是独立进程单元,通过负载均衡策略,将请求转发到不同的执行单元上,例如nginx。另一种是负载均衡逻辑以代码的形式封装到服务消费者的客户端上,服务消费者客户端维护了一份服务提供的信息列表,有了信息列表,通过负载均衡策略将请求分摊给多个服务提供者,从而达到负载均衡的目的
ribbon是Netflix公司开源的一个负载均衡的组件,它属于上述的第二种方式,是将负载均衡逻辑封装在客户端中,并且运行在客户端的进程里,ribbon作为服务消费者的负载均衡器,有两种使用方式,一种是何restTemplate相结合,另一种是feign相结合。feign已经默认继承了ribbon
3.2.2 RestTemplate 消费案例
4.0.0
com.spring.microservice
micro-service-parent
0.0.1-SNAPSHOT
com.spring.microservice
micro-service-consumer
0.0.1-SNAPSHOT
micro-service-consumer
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
修改 application,properties 配置文件,指定相关信息
#指定 ribbon 服务名称
spring.application.name=eureka-ribbon-client
#设定当前服务端口
server.port=8083
#指定服务注册中心地址
eureka.client.service-url.defaultZone=http://localhost:8081/eureka
@SpringBootApplication
@EnableEurekaClient
public class MicroServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(MicroServiceConsumerApplication.class, args);
}
}
package com.spring.micro.service.consumer.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
package com.spring.micro.service.consumer.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class RibbonService {
@Autowired
RestTemplate restTemplate;
public String hi(String name) {
return
restTemplate.getForObject("http://service-hi/hi?name=" + name, String.class);
}
}
package com.spring.micro.service.consumer.controller;
import com.spring.micro.service.consumer.service.RibbonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RibbonController {
@Autowired
RibbonService ribbonService;
@RequestMapping("/hi")
public String hi(@RequestParam(required = false, defaultValue = "") String
name) {
return ribbonService.hi(name);
}
}
查看注册中心,可以看到服务消费方也是服务注册方:
3.2.3 负载均衡案例
3.4 Feign
3.4.1 Feign 概述
Feign受Retrofit、JAXRS-2.0和websocket影响,采用了声明式的api接口风格,将javahttp客户端绑定到它的内部。Feign的首要目的是将Javahttp客户端调用过程变得简单
3.4.2 Feign 案例
修改 pom 文件相关信息:
4.0.0
com.spring.microservice
micro-service-parent
0.0.1-SNAPSHOT
com.spring.microservice
micro-service-feign
0.0.1-SNAPSHOT
micro-service-feign
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
#指定服务名称
spring.application.name=eureka-feign-client
#指定服务端口
server.port=8084
#指定注册中心 url
eureka.client.service-url.defaultZone=http://localhost:8081/eureka/
package com.spring.microservice.feign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class MicroServiceFeignApplication {
public static void main(String[] args) {
SpringApplication.run(MicroServiceFeignApplication.class, args);
}
}
package com.spring.microservice.feign.client;
import com.spring.microservice.feign.config.FeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "service-hi", configuration = FeignConfig.class)
public interface EurekaClientFeign {
@RequestMapping(value = "hi", method = RequestMethod.GET)
String sayHi(@RequestParam(value = "name") String name);
}
package com.spring.microservice.feign.controller;
import com.spring.microservice.feign.client.EurekaClientFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FeignController {
@Autowired
EurekaClientFeign eurekaClientFeign;
@GetMapping("/hi")
public String sayHi(@RequestParam(defaultValue = "", required = false) String name) {
return eurekaClientFeign.sayHi(name);
}
}
package com.spring.microservice.feign.config;
import feign.Retryer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static java.util.concurrent.TimeUnit.SECONDS;
@Configuration
public class FeignConfig {
@Bean
public Retryer feignRetryer() {
return new Retryer.Default(100, SECONDS.toMillis(1), 3);
}
}
3.3.3 负载均衡案例
3.5 Hystrix
3.5.1 Hystrix 概述
在分布式系统中,服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务出现故障,导致依赖于他们的其它服务出现远程调度的线程阻塞Hystrix是Netflix公司开源的一个项目,它提供了熔断器功能,能够阻止分布式系统中出现联动故障。Hystrix是通过隔离服务的访问点阻止联动故障的,并提供了故障的解决方案,从而提高了整个分布式系统的弹性
3.5.2 Hystrix 案例
feign.hystrix.enabled=true
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableDiscoveryClient
public class MicroServiceFeignApplication {
public static void main(String[] args) {
SpringApplication.run(MicroServiceFeignApplication.class, args);
}
}
@Component
public class EurekaClientHystric implements EurekaClientFeign {
@Override
public String sayHi(String name) {
return "sorry:" + name;
}
}
@FeignClient(value = "service-hi", configuration = FeignConfig.class, fallback = EurekaClientHystric.class)
public interface EurekaClientFeign {
@RequestMapping(value = "hi", method = RequestMethod.GET)
String sayHi(@RequestParam(value = "name") String name);
}
3.6 Zuul
3.6.1 Zuul 概述
zuul作为微服务系统的网关组件,用于构建边界服务(dgService),致力于动态路由、过滤、监控、弹性伸缩和安全。
3.6.2 Zuul 案例
4.0.0
com.spring.microservice
micro-service-parent
0.0.1-SNAPSHOT
com.spring.microservice
micro-service-zull
0.0.1-SNAPSHOT
micro-service-zull
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-zuul
org.springframework.boot
spring-boot-starter-test
test
#指定服务端口
server.port=8085
#指定服务名称
spring.application.name=service-zuul
#指定注册中心地址
eureka.client.service-url.defaultZone=http://localhost:8081/eureka/
#指定 api-a 请求调用的服务
zuul.routes.api-a.path=/api-a/**
zuul.routes.api-a.service-id=eureka-ribbon-client
#指定 api-b 请求调用的服务
zuul.routes.api-b.path=/api-b/**
zuul.routes.api-b.service-id=eureka-feign-client
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
@EnableDiscoveryClient
public class MicroServiceZullApplication {
public static void main(String[] args) {
SpringApplication.run(MicroServiceZullApplication.class, args);
}
}
3.7 Config
3.7.1 Config 概述
Springc config是springcloud组建中的分布式配置中心。该组件分为服务端和客户端,服务端可以读取管理远程仓库中的配置文件,客户端可以获取到服务端的配置信息。
3.6.2 Config 案例
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.0.6.RELEASE
com.microservice
micro-service-config
0.0.1-SNAPSHOT
micro-service-config
Demo project for Spring Boot
pom
config-server
config-client
1.8
Finchley.RELEASE
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
3.7.2 Config-Server 案例
4.0.0
com.microservice
micro-service-config
0.0.1-SNAPSHOT
com.microservice
config-server
0.0.1-SNAPSHOT
config-server
Demo project for Spring Boot
org.springframework.cloud
spring-cloud-config-server
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
spring.application.name=config-server
server.port=8086
#git 仓库地址
spring.cloud.config.server.git.uri=https://github.com/soulstare89/Springclou
dConfig
#仓库路径
spring.cloud.config.server.git.searchPaths=resp
#配置仓库的分支
spring.cloud.config.label=master
#访问 git 仓库的用户名
spring.cloud.config.server.git.username= #访问 git 仓库的密码
spring.cloud.config.server.git.password= #指定服务注册地址
eureka.client.serviceUrl.defaultZone=http://localhost:8081/eureka/
#开发环境 dev
spring.profiles.active=dev
package com.micro.service.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
3.7.3 Config-Client 案例
4.0.0
com.microservice
micro-service-config
0.0.1-SNAPSHOT
com.microservice
config-client
0.0.1-SNAPSHOT
config-client
Demo project for Spring Boot
org.springframework.cloud
spring-cloud-starter-config
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-maven-plugin
#指明配置文件
spring.application.name=config-client
#指明远程仓库的分支
spring.cloud.config.label=master
#开发环境配置文件
spring.cloud.config.profile=dev
#指明配置服务中心的网址。
spring.cloud.config.uri= http://localhost:8086/
server.port=8087
#eureka.client.serviceUrl.defaultZone=http://localhost:8081/eureka/
#是从配置中心读取文件。
#spring.cloud.config.discovery.enabled=true
#配置中心的 servieId,即服务名。
#spring.cloud.config.discovery.serviceId=config-server
@SpringBootApplication
@EnableDiscoveryClient
@RefreshScope
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
3.7.4 Config 高可用案例
将配置中心config server做成一个微服务,并且将其集群化,从而达到高可用。配置中心 config server高可用的架构图如图。configserver和configclient想eureka server注册,并且将config server 多实例集群部署
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
#指定服务注册地址
eureka.client.serviceUrl.defaultZone=http://localhost:8081/eureka/
@EnableEurekaClient
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication
修改 config-client 的依赖信息,添加 eureka-client:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
#指明配置文件
spring.application.name=config-client
#指明远程仓库的分支
spring.cloud.config.label=master
#开发环境配置文件
spring.cloud.config.profile=dev
#指明配置服务中心的网址。
#spring.cloud.config.uri= http://localhost:8088/
server.port=8087
#指定注册中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:8081/eureka/
#是从配置中心读取文件。
spring.cloud.config.discovery.enabled=true
#配置中心的 servieId,即服务名。
spring.cloud.config.discovery.serviceId=CONFIG-SERVER