本篇文章给大家带来的内容是关于spring cloud是什么?spring cloud的使用介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
一、什么是Spring Cloud?
Spring提供了一系列工具,可以帮助开发人员迅速搭建分布式系统中的公共组件(比如:配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,主节点选举, 分布式session, 集群状态)。协调分布式环境中各个系统,为各类服务提供模板性配置。使用Spring Cloud, 开发人员可以搭建实现了这些样板的应用,并且在任何分布式环境下都能工作得非常好,小到笔记本电脑, 大到数据中心和云平台。
Spring Cloud是基于Spring Boot的, 最适合用于管理Spring Boot创建的各个微服务应用。要管理分布式环境下的各个Spring Boot微服务,必然存在服务的注册问题。所以我们先从服务的注册谈起。既然是注册,必然有个管理注册中心的服务器,各个在Spring Cloud管理下的Spring Boot应用就是需要注册的client。
Spring Cloud使用erureka server, 然后所有需要访问配置文件的应用都作为一个erureka client注册上去。eureka是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳,在默认情况下erureka server也是一个eureka client ,必须要指定一个 server。
1.创建Eureka Server
先创建一个spring boot的项目
pom文件
4.0.0 me.cn test 0.0.1-SNAPSHOT jar test Demo project for Spring Boot org.springframework.boot spring-boot-starter-parent 2.0.5.RELEASE UTF-8 UTF-8 10 Finchley.SR1 org.springframework.cloud spring-cloud-starter-netflix-eureka-server org.springframework.boot spring-boot-starter-test test javax.xml.bind jaxb-api 2.3.0 com.sun.xml.bind jaxb-impl 2.3.0 org.glassfish.jaxb jaxb-runtime 2.3.0 javax.activation activation 1.1.1 org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin
需要一个注解@EnableEurekaServer加在springboot工程的启动类上
@EnableEurekaServer
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}eureka server的配置文件appication.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/启动eureka server,然后访问http://localhost:8761, 界面如下, "No instances available" 表示无client注册
2.创建一个Eureka Client
pom文件
4.0.0 com.chry test1 0.0.1-SNAPSHOT test1 jar Demo Spring Boot Client org.springframework.boot spring-boot-starter-parent 1.5.3.RELEASE UTF-8 UTF-8 1.8 org.springframework.cloud spring-cloud-starter-eureka org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.cloud spring-cloud-dependencies Dalston.RC1 pom import org.springframework.boot spring-boot-maven-plugin spring-milestones Spring Milestones https://repo.spring.io/milestone false
使用@EnableEurekaClient注解表明是client
@SpringBootApplication
@EnableEurekaClient
@RestController
public class Test1Application {
public static void main(String[] args) {
SpringApplication.run(Test1Application.class, args);
}
@Value("${server.port}")
String port;
@RequestMapping("/")
public String home() {
return "hello world from port " + port; }
}yml文件的配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8762
spring:
application:
name: service-helloworld最后启动client,之后就可以在服务器端口看到该client成功注册
二、配置管理
Spring Cloud的解决方案是, 将这些配置文件放到版本管理服务器里面,Spring Cloud缺省配置使用GIT中。所有Web服务均从GIT中获取这些配置文件。由于GIT服务器与具体Web服务器之间不需要共享存储, 只要网络可达就行,从而可以实现Web服务于配置信息的存放位置的解耦。
2.1创建config Server
pom文件新加了依赖
org.springframework.cloud spring-cloud-config-server
@EnableConfigServer注解说明了一个Config Server。同样我们使用@EnableEurekaClient将它注册到服务中心。
Config server的配置文件appication.yml , 注意配置文件的url是GIT服务器的仓库地址, searchPaths配置文件所在的文件夹在仓库中的路径, 在server端不需要指定具体配置文件名, 因为具体的配置文件是什么有应用(也就是client)决定。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://gitee.com/ning9/CRUD.git
searchPaths: spring-cloud/helloworldConfig
application:
name: config-server启动Config server,访问http://localhost:8888/config-client-dev.properties就可以显示配置文件内容
2.2创建config client
启动文件
@SpringBootApplication
@RestController
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
@Value("${hello}")
String hello;
@RequestMapping(value = "/hello")
public String hello(){
return hello;
}
}yml文件
spring:
application:
name: config-client
cloud:
config:
label: master
profile: dev
uri: http://localhost:8888/
server:
port: 8881启动config-client应用后, 可以访问http://locahost/8881/hello, 可以看到,应用本身并没有直接配置hello的具体内容, 也没指定具体配置文件,所欲这些都由spring cloud框架提交给config server了。
三、配置自动刷新
首先,在pom.xml中添加以下依赖。spring-boot-starter-actuator是一套监控的功能,可以监控程序在运行时状态,其中就包括/refresh的功能。
org.springframework.boot spring-boot-starter-actuator
其次,开启refresh机制, 需要给加载变量的类上面加载@RefreshScope注解,其它代码可不做任何改变,那么在客户端执行/refresh的时候就会更新此类下面的变量值,包括通过config client从GIT获取的配置。
@SpringBootApplication
@RestController
@RefreshScope
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
@Value("${hello}")
String hello;
@RequestMapping(value = "/hello")
public String hello(){
return hello;
}
}但是这种方式需要自己手动重新运行方法,才能看到更新后的数据
四、分布式环境下自动发现配置服务
将config-server注册到服务中心
将hello world的应用注册到eureka 服务中心, 配置方法同前面一样
修改配置文件,将config-server的URL硬编码机制改成,通过服务中心根据名字自动发现机制
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/spring:
application:
name: config-client
cloud:
config:
label: master
profile: dev
discovery:
enabled: true
service-id: config-server
management:
security:
enabled: falseserver:
port: 8881我们注释掉了硬编码的config-server的URL配置, 取而代之的是服务注册中心的地址http://localhost:8761/eureka/以及配置服务的名字“config-server”, 同时打开自动发现机制discovery.enable = true. 我们在运行一下hello world应用, 可以发现, GIT里面的内容依然可以访问。此时我们的hello world应用已经完全不知道配置服务的地址,也不知道配置的内容, 所有这些都通过服务注册中心自动发现。
五、客户端的负载均衡
Spring Cloud用Ribbon来实现两个Hello World服务的负载均衡
5.1创建ribbon服务
Smart Shop商城系统是一款基于 Spring Cloud +MybatisPlus+XXL-JOB+redis+Vue的前后端分离的商城系统,采用轻量级稳定框架开发及优化核心,减少依赖,具备出色的执行效率、扩展性、稳定性。 Smart Shop 经过了生产环境反复线上论证和大量真实用户数据使用的考验。
添加pom依赖
org.springframework.cloud spring-cloud-starter-ribbon
创建启动类ServiceRibbonApplication
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}@EnableDiscoveryClient向服务中心注册,并且注册了一个叫restTemplate的bean。
@ LoadBalanced注册表明,这个restRemplate是需要做负载均衡的。
创建获取一个获取Hello内容的service类
@Service
public class HelloService {
@Autowired RestTemplate restTemplate;
public String getHelloContent() {
return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class);
}
}这里关键代码就是, restTemplate.getForObject方法会通过ribbon负载均衡机制, 自动选择一个Hello word服务,
这里的URL是“http://SERVICE-HELLOWORLD/",其中的SERVICE-HELLOWORLD是Hello world服务的名字,而注册到服务中心的有两个SERVICE-HELLOWORLD。 所以,这个调用本质是ribbon-service作为客户端根据负载均衡算法自主选择了一个作为服务端的SERVICE-HELLOWORLD服务。然后再访问选中的SERVICE-HELLOWORLD来执行真正的Hello world调用。
六、用声明式REST客户端Feign调用远端http服务
添加新的依赖
org.springframework.cloud spring-cloud-starter-feign
创建启动类,需要加上@EnableFeignClients注解以使用Feign, 使用@EnableDiscoveryClient开启服务自动发现
添加配置文件application.yml, 使用端口8902, 名字定义为service-feign, 并注册到eureka服务中心
定义Feign:一个用@FeignClient注解的接口类
@FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入; 该接口通过value定义了需要调用的SERVICE-HELLOWORLD服务(通过服务中心自动发现机制会定位具体URL); @RequestMapping定义了Feign需要访问的SERVICE-HELLOWORLD服务的URL(本例中为根“/”)
@FeignClient(value = "SERVICE-HELLOWORLD")
public interface HelloWorldService {
@RequestMapping(value = "/",method = RequestMethod.GET)
String sayHello();
}Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里
编写一个Controller。
注入之前通过@FeignClient定义生成的bean,
sayHello()映射到http://localhost:8902/hello, 在这里,我修改了Hello World服务的映射,将根“/”, 修改成了“/hello”。
@RestController
public class WebController {
@Autowired HelloWorldService helloWorldFeignService;
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String sayHello(){
return helloWorldFeignService.sayHello();
}
}七、断路器
7.1在Ribbon应用中使用断路器
先添加依赖
org.springframework.cloud spring-cloud-starter-hystrix
在Spring Boot启动类上添加@EnableCircuitBreaker注解
用@HystrixCommand注解标注访问服务的方法
@Service
public class HelloService {
@Autowired RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "serviceFailure")
public String getHelloContent() {
return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class);
}
public String serviceFailure() {
return "hello world service is not available !";
}
}@HystrixCommand注解定义了一个断路器,它封装了getHelloContant()方法, 当它访问的SERVICE-HELLOWORLD失败达到阀值后,将不会再调用SERVICE-HELLOWORLD, 取而代之的是返回由fallbackMethod定义的方法serviceFailure()。@HystrixCommand注解定义的fallbackMethod方法,需要特别注意的有两点:
第一, fallbackMethod的返回值和参数类型需要和被@HystrixCommand注解的方法完全一致。否则会在运行时抛出异常。比如本例中,serviceFailure()的返回值和getHelloContant()方法的返回值都是String。
第二, 当底层服务失败后,fallbackMethod替换的不是整个被@HystrixCommand注解的方法(本例中的getHelloContant), 替换的只是通过restTemplate去访问的具体服务。可以从中的system输出看到, 即使失败,控制台输出里面依然会有“call SERVICE-HELLOWORLD”。
7.2在Feign应用中使用断路器
用@FeignClient注解添加fallback类, 该类必须实现@FeignClient修饰的接口。
@FeignClient(name = "SERVICE-HELLOWORLD", fallback = HelloWorldServiceFailure.class)
public interface HelloWorldService {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String sayHello();
}创建HelloWorldServiceFailure类, 必须实现被@FeignClient修饰的HelloWorldService接口。注意添加@Component或者@Service注解,在Spring容器中生成一个Bean
@Component
public class HelloWorldServiceFailure implements HelloWorldService {
@Override
public String sayHello() {
System.out.println("hello world service is not available !");
return "hello world service is not available !";
}
}在application.yml中添加如下配置:
feign:
hystrix:
enabled: true八、路由网管zuul
创建新的工程添加新的依赖
org.springframework.cloud spring-cloud-starter-zuul
创建启动类: 使用@EnableZuulProxy注解
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ServiceZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceZuulApplication.class, args);
}
}编写zuul服务配置:
简单配置两个路由, 一个路由到ribbon,一个路由到feign; 由于都注册到eureka服务中心,所以都用通过serviceId来发现服务具体地址, path是路由的地址映射关系
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8904
spring:
application:
name: service-zuul
zuul:
routes:
ribbo:
path: /api-ribbon/**
serviceId: service-ribbon
feign:
path: /api-feign/**
serviceId: service-feign这时启动zuul服务, 然后访问http://localhost:8904/api-ribbon可直接路由到http://localhost:8901/.
http://localhost:8904/api-feign/hello可路由到http://localhost:8902/hello
zuul还提供了过滤功能, 只要实现接口ZuulFilter即可对请求先进行筛选和过滤之后再路由到具体服务。









