本篇文章帶給大家的內容是關於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檔
<?xml version="1.0" encoding="UTF-8"?> <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>me.cn</groupId> <artifactId>test</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>test</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>10</java.version> <spring-cloud.version>Finchley.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </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>
需要一個註解@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檔
<?xml version="1.0" encoding="UTF-8"?> <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.chry</groupId> <artifactId>test1</artifactId> <version>0.0.1-SNAPSHOT</version> <name>test1</name> <packaging>jar</packaging> <description>Demo Spring Boot Client</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.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-web</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>Dalston.RC1</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> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
使用@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檔案新加入了依賴關係<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
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 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; } }
spring: application: name: config-client cloud: config: label: master profile: dev uri: http://localhost:8888/ server: port: 8881
三、設定自動刷新
首先,在pom.xml中加入以下依賴。spring-boot-starter-actuator是一套監控的功能,可以監控程式在執行時狀態,其中就包含
/refresh的功能。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
@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服务
添加pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
创建启动类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服务
添加新的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
创建启动类,需要加上@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应用中使用断路器
先添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
在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
创建新的工程添加新的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency>
创建启动类: 使用@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即可对请求先进行筛选和过滤之后再路由到具体服务。
以上是spring cloud是什麼? spring cloud的使用介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!