Spring cloud是一个基于Spring Boot实现的服务治理工具包,在微服务架构中用于管理和协调服务的。
组成部分

spingcloud的五大神兽
服务发现——Netflix Eureka
客服端负载均衡——Netflix Ribbon/Feign
服务网关——Netflix Zuul
断路器——Netflix Hystrix
分布式配置——Spring Cloud Config
Spring cloud入门-搭建环境
1)建环境
以maven多模块化的方法搭建
2)注册中心
由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑。
3)服务提供者
4)服务消费者

1.1. 搭建环境pxm.xml配置
1<properties> 2<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 3<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 4<java.version>1.8</java.version> 5<spring-cloud.version>Finchley.SR1</spring-cloud.version> 6<springboot.version>2.0.5.RELEASE</springboot.version> 7</properties> 8 9<dependencyManagement> 10<dependencies> 11<dependency> 12<groupId>org.springframework.cloud</groupId> 13<artifactId>spring-cloud-dependencies</artifactId> 14<version>${spring-cloud.version}</version> 15<type>pom</type> 16<scope>import</scope> 17</dependency> 18<dependency> 19<groupId>org.springframework.boot</groupId> 20<artifactId>spring-boot-dependencies</artifactId> 21<version>${springboot.version}</version> 22<type>pom</type> 23<scope>import</scope> 24</dependency> 25</dependencies> 26</dependencyManagement>
-
Spring cloud入门-Eureka注册中心
-
由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑。
Eureka是netflix的一个子模块,也是核心模块之一,Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了 服务发现和注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务,而不需要修改服务调用的配置文件了,功能类似于dubbo的注册中心,比如zookeeper。
原理

三大角色:
Eureka server提供服务注册和发现
Eureka Server提供服务注册服务。各个服务提供者节点启动后,会在Eureka Server中进行注册,这样Eureka server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到
Service Provider服务提供方将自身服务注册到Eureka,从而使服务消费方能够找到。
Service Consumer服务消费方从Eureka获取注册服务列表,从而能够消费服务。
Eureka client是一个java客户端,用于简化eureka server的交互,在应用启动后,将会向Eureka Server发送心跳。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表把这个服务节点移除。
注册中心的搭建
创建一个普通maven项目
1dependency> 2<groupId>org.springframework.boot</groupId> 3<artifactId>spring-boot-starter-web</artifactId> 4</dependency> 5<dependency> 6<groupId>org.springframework.boot</groupId> 7<artifactId>spring-boot-starter-test</artifactId> 8</dependency> 9 10<!--Eureka服务端支持--> 11<dependency> 12<groupId>org.springframework.cloud</groupId> 13<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> 14</dependency>
yum配置
1server: 2 port: 7001 3eureka: 4 instance: 5 hostname: localhost 6 client: 7 registerWithEureka: false #是否要注册到eureka 8 fetchRegistry: false #表示是否从Eureka Server获取注册信息 9serviceUrl: 10 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置
主类
1@SpringBootApplication 2@EnableEurekaServer//标识是eureka服务端 3public class EnrekaServerApplication_7001 { 4public static void main(String[] args) { 5 SpringApplication.run(EnrekaServerApplication_7001.class); 6 } 7}
注意事项
自我保护引发的错误

Eureka Server 在运行期间会去统计**心跳失败比例在 15 分钟之内是否低于 85%,**如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等
搭建服务提供者
在搭建服务提供者模块之前我们要创建一个模块,这个模块是公共模块,用来存放工共的数据
然后就是创建服务提供者,
pom.xml配置
1<dependencies> 2<!--公共代码依赖--> 3<dependency> 4<groupId>cn.itsource.springcloud</groupId> 5<artifactId>User_interface</artifactId> 6<version>1.0-SNAPSHOT</version> 7</dependency> 8 9<!--springboot支持--> 10<dependency> 11<groupId>org.springframework.boot</groupId> 12<artifactId>spring-boot-starter-web</artifactId> 13</dependency> 14<dependency> 15<groupId>org.springframework.boot</groupId> 16<artifactId>spring-boot-starter-test</artifactId> 17</dependency> 18 19<!--eureka客户端支持 --> 20<dependency> 21<groupId>org.springframework.cloud</groupId> 22<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 23</dependency> 24</dependencies>
yum配置
1server: 2 port: 8001 3spring: 4 application: 5 name: USER-PROVIDER #不要使用下划线 6eureka: 7 client: 8 service-url: 9 defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿
程序主方法
1@SpringBootApplication 2@EnableEurekaClient //表示是eureka的客户端 3public class UserProviderApplication_8001 { 4public static void main(String[] args) { 5 SpringApplication.run(UserProviderApplication_8001.class); 6 } 7}
contrller层进行测试
1@RestController 2@RequestMapping("/provider") 3public class UserController { 4 5// @Autowired 6 // private IUserService userService; 7@RequestMapping("/user/{id}") //user/1 8public User getUser(@PathVariable("id") Long id) { 9 10// 正常应该调用service获取用户,现在模拟一下 11return new User(id, "zs"); 12 } 13}
服务消费者搭建
pom.xml配置
1dependency> 2<groupId>cn.itsource.springcloud</groupId> 3<artifactId>User_interface</artifactId> 4<version>1.0-SNAPSHOT</version> 5</dependency> 6 7<!--springboot支持--> 8<dependency> 9<groupId>org.springframework.boot</groupId> 10<artifactId>spring-boot-starter-web</artifactId> 11</dependency> 12<dependency> 13<groupId>org.springframework.boot</groupId> 14<artifactId>spring-boot-starter-test</artifactId> 15</dependency>
yml配置
1server: 2 port: 9001 3spring: 4 application: 5 name: USER_CONSUMER
主程序
1package cn.itsource.springcloud; 2 3import org.springframework.boot.SpringApplication; 4import org.springframework.boot.autoconfigure.SpringBootApplication; 5 6@SpringBootApplication 7public class UserConsumerAppliction_9001 { 8public static void main(String[] args) { 9 SpringApplication.run(UserConsumerAppliction_9001.class); 10 } 11}
测试
调用服务提供者的接口
1@Configuration // <beans></beans> 2public class CfgBean { 3 4@Bean //<bean class="org.springframework.web.client.RestTemplate"></bean> 5public RestTemplate getRestTemplate(){ 6return new RestTemplate(); 7 } 8} 9 10@RestController 11@RequestMapping("/consumer") 12public class UserController { 13 14//多个方法调用只需改一处就ok 15public static final String URL_PREFIX = "http://localhost:8001"; 16 17@Autowired 18private RestTemplate restTemplate; 19 20@RequestMapping("/user/{id}") 21public User getUser(@PathVariable("id")Long id){ 22//调用远程服务 http请求 23String url = URL_PREFIX+"/provider/user/"+id; 24return restTemplate.getForObject(url,User.class ); 25 } 26}
实现集群
实现集群以注册中心为例。我们新建一个操作中心,操作i方法和之前的一样,yml的配置方式变化
1server: 2 port: 7001 3eureka: 4 instance: 5 hostname: eureka-7001.com 6 client: 7 registerWithEureka: false #是否要注册到eureka 8 fetchRegistry: false #表示是否从Eureka Server获取注册信息 9 serviceUrl: 10 #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置 11 defaultZone: http://eureka-7002.com:7002/eureka/ #集群配置,如果有多个,有逗号分割,不要包含自己
7002: 模块application.yml
1server: 2 port: 7002 3eureka: 4 instance: 5 hostname: eureka-7002.com 6 client: 7 registerWithEureka: false #是否要注册到eureka 8 fetchRegistry: false #表示是否从Eureka Server获取注册信息 9 serviceUrl: 10 #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置 11 defaultZone: http://eureka-7001.com:7001/eureka/ #集群配置,如果有多个,有逗号分割,不要包含自己
映射hosts 模拟域名解析 C:\Windows\System32\drivers\etc
127.0.0.1 eureka-7001.com
127.0.0.1 eureka-7002.com
然后就是在消费端需要注意,
把8001服务提供方代码分别注册到7001和7002两个注册中心去;完成集群操作
1server: 2 port: 8001 3spring: 4 application: 5name: user-provider #不要使用下划线 6eureka: 7 client: 8 service-url: 9 #defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿 10 defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka 11instance: 12 prefer-ip-address: true #显示客户端真实ip
负载均衡
为什么需要负载均衡
为了提供并发量,有时同一个服务提供者可以部署多个。这个客户端在调用时要根据一定的负责均衡策略完成负载调用。
1.1. Ribbon负载均衡
Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端负载均衡算法。Ribbon客户端组件提供一系列完善的配置项,如,连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,
1.1.1. 集成原理

在服务器方配置负载均衡
我们新建一个服务端和之前的一样的,然后在消费端进行配置
·
1<!--eureka客户端,服务消费者也要从注册中心获取可用服务列表--> 2<dependency> 3 <groupId>org.springframework.cloud</groupId> 4 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 5</dependency> 6 7<!--客户端负载均衡实现 ribbon--> 8<dependency> 9 <groupId>org.springframework.cloud</groupId> 10 <artifactId>spring-cloud-starter-ribbon</artifactId> 11</dependency> 12<dependency> 13 <groupId>org.springframework.cloud</groupId> 14 <artifactId>spring-cloud-starter-config</artifactId> 15</dependency>
9001消费方引入ribbon
1port: 9001 2eureka: 3 client: 4 registerWithEureka: false #不注册到Eureka,不在注册中心显示 5 service-url: 6 #defaultZone: http://localhost:7001/eureka 7 defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka
主方法
1@SpringBootApplication 2@EnableEurekaClient 3public class UserConsumerApplicaton_9001 { 4public static void main(String[] args) { 5 SpringApplication.run(UserConsumerApplicaton_9001.class); 6 } 7}
新建一个类用来获取RestTemplate
1@Configurationpublic class CfgBean { @Bean @LoadBalanced //开启负载均衡 public RestTemplate getRestTemplate() { return new RestTemplate(); } //随机策略 @Bean public IRule myRule(){ return new RandomRule();//通过随机算法分配服务端 }} 2 3@Configuration 4public class CfgBean { 5 6@Bean 7 @LoadBalanced //开启负载均衡 8public RestTemplate getRestTemplate(){ 9return new RestTemplate(); 10 } 11} 12 13@RestController 14@RequestMapping("/consumer") 15public class UserController { 16 17//多个方法调用只需改一处就ok 18 //public static final String URL_PREFIX = "http://localhost:8001"; 19public static final String URL_PREFIX ="http://USER-PROVIDER"; //通过服务名从注册中心获取服务列表,通过负载均衡调用 20 21@Autowired 22private RestTemplate restTemplate; 23 24@RequestMapping("/user/{id}") 25public User getUser(@PathVariable("id")Long id){ 26//调用远程服务 http请求 27String url = URL_PREFIX+"/provider/user/"+id; 28return restTemplate.getForObject(url,User.class ); 29 } 30}
完后启动就能完成负载均衡
Feign负载均衡
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。
Feign是以接口方式进行调用,而不是通过RestTemplate来调用,feign底层还是ribbo,它进行了封装,让我们调用起来更加happy.
通过客户端进行负载均衡
新建一个客户端
pom配置
1<dependencies> 2<!--公共代码依赖--> 3<dependency> 4<groupId>cn.itsource.springcloud</groupId> 5<artifactId>User_interface</artifactId> 6<version>1.0-SNAPSHOT</version> 7</dependency> 8 9<!--springboot支持--> 10<dependency> 11<groupId>org.springframework.boot</groupId> 12<artifactId>spring-boot-starter-web</artifactId> 13</dependency> 14<dependency> 15<groupId>org.springframework.boot</groupId> 16<artifactId>spring-boot-starter-test</artifactId> 17</dependency> 18 19<!--eureka客户端,服务消费者也要从注册中心获取可用服务列表--> 20<dependency> 21<groupId>org.springframework.cloud</groupId> 22<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 23</dependency> 24 25<!--feign的支持--> 26<dependency> 27<groupId>org.springframework.cloud</groupId> 28<artifactId>spring-cloud-starter-openfeign</artifactId> 29</dependency> 30</dependencies>
配置yml
1server: 2 port: 9002 3eureka: 4 client: 5 registerWithEureka: false #不注册到Eureka,不在注册中心显示 6 service-url: 7 #defaultZone: http://localhost:7001/eureka 8 defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka
主方法
1 @SpringBootApplication 2@EnableEurekaClient 3@EnableFeignClients(basePackages = "cn.itsource.microservice") //不在当前包下面 4public class UserConsumerFeign9002Application { 5 6 public static void main(String[] args) { 7 SpringApplication.run(UserConsumerFeign9002Application.class, args); 8 } 9}
写一个接口,这个接口中的方法要和服务提供者里面访问地址和参数等保持一致。
1@FeignClient(value = "USER-PROVIDER") 2@RequestMapping("/provider") 3public interface UserCilent { 4@RequestMapping("/user/{id}") //user/1 5User getUser(@PathVariable("id") Long id); 6}
在Controller中进行调用
1@RestController 2@RequestMapping("/consumer") 3public class UserController { 4@Autowired 5private UserCilent userCilent; 6@RequestMapping("/user/{id}") 7public User getUser(@PathVariable("id")Long id){ 8 System.out.println(userCilent.getClass()); 9return userCilent.getUser(id); 10 } 11}