SpringCloud微服務框架搭建
以上是我的springcloud項目,eureka是注冊中心,ribbon和feign都是cloud的rpc遠程調用。
首先先創建空項目Empty Project
一、注冊中心Eureka
1.創建基於web的Maven項目(springcloud)
2.創建服務注冊中心。在springcloud項目中創建SpringBoot項目(springboot):
選中項目右擊–>New–>Module
勾選Cloud Discovery–>Eureka server。以方便導包。
3.編寫springboot項目
3.1 pom.xml文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.cy</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-server</name> <description>Eureka Server project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>2021.0.1</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> </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>
網上很多用spring cloud starter eureka server 但是官方棄用了,這里使用 spring-cloud-starter-netflix-eureka-server
3.2修改application.yml文件
server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
registerWithEureka 和 fetchRegistry 設置為false,表明自己屬於服務中心主體
為什么要用yml文件?而不是xml或properties文件?
說明:xml或properties文件都是以標簽來配置數據,這樣就造成了資源的浪費,不利於我們開發大型項目,而yml(yaml)文件則取消了這樣的配置,文件中都是以數據為中心,層級結構以空格作為層級分隔符。使數據得到突出,簡化了開發,同時占用的資源也更少。
3.3編寫啟動類SpringbootApplication.java
@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
添加@EnableEurekaServer,該注解表明標注類是一個Eureka Server。
4.啟動項目
在瀏覽器中輸入http://localhost:8761/

二、 服務提供者
創建一個服務提供者 (eureka client),當client向server注冊時,它會提供一些元數據,例如主機和端口,URL,主頁等。Eureka server 從每個client實例接收心跳消息。 如果心跳超時,則通常將該實例從注冊server中刪除。
1 創建項目service-support
略,和上文相似,pom文件和yml配置見下文
2、配置
2.1 引入maven依賴
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.cy</groupId> <artifactId>service-support</artifactId> <version>0.0.1-SNAPSHOT</version> <name>service-support</name> <description>Service Support project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>2021.0.1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</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>${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>
2.2 application.yml配置
server: port: 8762 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: service-support
2.3 加注解@EnableEurekaClient
表明自己是一個eurekaclient.
@SpringBootApplication @EnableEurekaClient public class ServiceSupportApplication { public static void main(String[] args) { try{ SpringApplication.run(ServiceSupportApplication.class, args); }catch (Exception e){ e.printStackTrace(); } } }
2.4 創建controller
@RestController public class TestController { @Value("${server.port}") String port; @RequestMapping(value = "/support",method = RequestMethod.GET) public String home(@RequestParam String name) { return "hi " + name + ",i am from port:" + port; } }
2.5演示效果
需要指明spring.application.name,這個很重要,這在以后的服務與服務之間相互調用一般都是根據這個name 。 啟動工程,打開http://localhost:8761 ,即eureka server 的網址

這時打開 http://localhost:8762/support?name=forezp ,你會在瀏覽器上看到 :
hi forezp,i am from port:8762
三、 服務消費者(Feign)
什么是Feign Feign是一個聲明式的偽Http客戶端,它使得寫Http客戶端變得更簡單。使用Feign,只需要創建一個接口並注解。 它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的編碼器和解碼器。 Feign默認集成了Ribbon,並和Eureka結合,默認實現了負載均衡的效果。 簡而言之: Feign 采用的是基於接口的注解 Feign 整合了ribbon
1准備工作
啟動eureka-server,端口為8761; 啟動service-support 兩次,端口分別為8762 、8773.
2新建一個spring-boot工程,
取名為serice-feign,代碼如下:
2.1 編輯pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.cy</groupId> <artifactId>service-feign</artifactId> <version>0.0.1-SNAPSHOT</version> <name>service-feign</name> <description>Service-feign project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>2021.0.1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</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>${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>
2.2 application.yml配置
在工程的配置文件application.yml文件,指定程序名為service-feign,端口號為8765,服務注冊地址為http://localhost:8761/eureka/ ,代碼如下:
server: port: 8765 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: service-feign
2.3定義一個feign接口
/**綁定service-support服務,調用該服務的support方法*/ @FeignClient(value = "service-support") public interface SchedualServiceHi { @RequestMapping(value = "/support", method = RequestMethod.GET) String sayHiFromClientOne(@RequestParam(value = "name") String name); }
2.4一個”/hi”的API接口
@RestController public class HiController { @Autowired SchedualServiceHi schedualServiceHi; @RequestMapping(value = "/hi",method = RequestMethod.GET) public String sayHi(@RequestParam String name){ return schedualServiceHi.sayHiFromClientOne(name); } }
2.5啟動方式
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class ServiceFeignApplication { public static void main(String[] args) { SpringApplication.run(ServiceFeignApplication.class, args); } }
2.6演示效果
啟動程序,多次訪問http://localhost:8765/hi?name=forezp(http://localhost:8765/hi?name=forezp),瀏覽器交替顯示:
hi forezp,i am from port:8762 hi forezp,i am from port:8763
四、Ribbon
1、創建springboot項目,命名service-ribbon
2、編輯pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.cy</groupId> <artifactId>service-ribbon</artifactId> <version>0.0.1-SNAPSHOT</version> <name>service-ribbon</name> <description>Service-ribbon project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>2021.0.1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>--> <!-- <version>2.2.6.RELEASE</version>--> <!-- </dependency>--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.1.0.RELEASE</version> </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>${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>
3、yml文件
server: port: 8764 spring: application: name: service-ribbon eureka: client: registerWithEureka: true fetchRegistry: true serviceUrl: defaultZone: http://localhost:8761/eureka/
4、啟動類
@SpringBootApplication @EnableDiscoveryClient public class ServiceRibbonApplication { public static void main(String[] args) { SpringApplication.run(ServiceRibbonApplication.class, args); } @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } }
5、controller和service
@RestController public class HelloControler { @Autowired HelloService helloService; @RequestMapping(value = "/hi",method = RequestMethod.GET) public String hi(@RequestParam String name) { return helloService.hiService(name); } } @Service public class HelloService { @Autowired RestTemplate restTemplate; public String hiService(String name) { return restTemplate.getForObject("http://service-support/"+"support?name=" + name, String.class); } }
6、訪問
踩坑記錄:配置負載均衡ribbon
,在加入@LoadBalanced
啟動后就報錯No instances available for service-support
spring-cloud-starter-netflix-eureka-client 3.0版本的已經內置ribbon了,所以我們導入的spring-cloud-starter-netflix-ribbon會與之沖突,這里去掉spring-cloud-starter-netflix-ribbon就解決了
參考博客:https://www.cnblogs.com/wangpaipilot/articles/14372787.html
五、Hystrix斷路器
在微服務架構中,根據業務來拆分成一個個的服務,服務與服務之間可以相互調用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign來調用。為了保證其高可用,單個服務通常會集群部署。由於網絡原因或者自身的原因,服務並不能保證100%可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求涌入,Servlet容器的線程資源會被消耗完畢,導致服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重后果,這就是服務故障的“雪崩”效應。
為了解決這個問題,業界提出了斷路器模型。
7.1 什么是Hystrix
Netflix開源了Hystrix組件,實現了斷路器模式,SpringCloud對這一組件進行了整合。 在微服務架構中,一個請求需要調用多個服務是非常常見的,如下圖:

較底層的服務如果出現故障,會導致連鎖故障。當對特定的服務的調用的不可用達到一個閥值(Hystric 是5秒20次) 斷路器將會被打開。

斷路打開后,可用避免連鎖故障,fallback方法可以直接返回一個固定值。
准備工作
這篇文章基於上一篇文章的工程,首先啟動上一篇文章的工程,啟動eureka-server 工程;啟動service-hi工程,它的端口為8762。
在ribbon使用斷路器
改造serice-ribbon 工程的代碼,首先在pox.xml文件中加入spring-cloud-starter-hystrix的起步依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.1.0.RELEASE</version> </dependency>
改造service
改造HelloService類,在hiService方法上加上@HystrixCommand注解。該注解對該方法創建了熔斷器的功能,並指定了fallbackMethod熔斷方法,熔斷方法直接返回了一個字符串,字符串為”hi,”+name+”,sorry,error!”,代碼如下:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
//斷路器,遠程調用失敗的回調函數
@HystrixCommand(fallbackMethod = "hiError")
public String hiService(String name)
{
return restTemplate.getForObject("http://service-support/"+"support?name=" + name, String.class);
}
public String hiError(String name) {
return "hi," + name + ",sorry,error!";
}
}
在啟動類上加入
@SpringBootApplication @EnableDiscoveryClient @EnableHystrix //斷路器 public class ServiceRibbonApplication { public static void main(String[] args) { SpringApplication.run(ServiceRibbonApplication.class, args); } @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } }
把service-support服務停掉,然后測試
演示效果