SpringCloud
概述
優缺點
傳統網站
springcloud和dubbo區別
實操
第一個springcloud專案,實現多模組的生產消費場景
三個模組,api,consumer,provider
新建maven專案
外部pom檔案,注意對應springcloud和springboot版本
<?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.suda</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>springcloud-api</module>
<module>springcould-provider</module>
<module>springcloud-consumer</module>
<module>springcloud-eureka</module>
</modules>
<!--打包方式pom-->
<packaging>pom</packaging>
<properties>
<junit.version>4.12</junit.version>
<lombok.version>1.16.10</lombok.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<!--springcloud dependence-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring boot dependence-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--database-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
<!--sprintboot starter-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--log and test-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.3.0-alpha5</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
api
僅包含一個實體類
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.suda</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.suda</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--dependence used in this project,if configed in parent pom, don't need to align the version-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
Department.class
package com.suda.springcloud.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true) //鏈式寫法
public class Department implements Serializable {
private Long departmentId;
private String departmentName;
private String dbSource;
//這個資料存在哪個資料庫,微服務中,一個服務對應一個資料庫,同一個資訊可能在不同資料庫
public Department(String departmentName){
this.departmentName=departmentName;
}
}
provider
提供所有服務
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.suda</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>som.suda</groupId>
<artifactId>springcould-provider</artifactId>
<dependencies>
<!--load the api module just write-->
<dependency>
<groupId>com.suda</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</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-jetty</artifactId>
</dependency>
<!--hot deploy-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<!--<version></version>-->
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 8001
mybatis:
type-aliases-package: com.suda.springcloud.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
config-location: classpath:mybatis/mybatis-config.xml
# configuration:
# map-underscore-to-camel-case: true
spring:
application:
name: springcloud-provider
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8&useSSL=true&useLegacyDatetimeCode=false&serverTimezone=America/New_York
username: spark
password: 123456
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
<!--駝峰命名和資料庫欄位不匹配解決方案-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
dao/IDepartmentDao
package com.suda.springcloud.controller;
import com.suda.springcloud.pojo.Department;
import com.suda.springcloud.service.IDepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DepartmentController {
@Autowired
private IDepartmentService departmentService;
@PostMapping("/department/add")
public boolean addDepartment(Department department){
return departmentService.addDepartment(department);
}
@GetMapping("/department/get/{id}")
public Department addDepartmentById(@PathVariable("id") Long id){
return departmentService.queryById(id);
}
@GetMapping("/department/list")
public List<Department> queryDepartmentById ( ){
return departmentService.queryAll();
}
}
mapper/departmentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suda.springcloud.dao.IDepartmentDao">
<insert id="addDepartment" parameterType="Department">
insert into department(department_name, db_source) values (#{departmentName}, DATABASE())
</insert>
<select id="queryById" resultType="Department" parameterType="Long">
select * from department where department_id = #{departmentId}
</select>
<select id="queryAll" resultType="Department">
select * from db01.department
</select>
</mapper>
service/IDepartmentService
package com.suda.springcloud.service;
import com.suda.springcloud.pojo.Department;
import java.util.List;
public interface IDepartmentService {
public boolean addDepartment(Department department);
public Department queryById(Long id);
public List<Department> queryAll();
}
service/DepartmentServiceImpl
package com.suda.springcloud.service;
import com.suda.springcloud.dao.IDepartmentDao;
import com.suda.springcloud.pojo.Department;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DepartmentServiceImpl implements IDepartmentService{
@Autowired
private IDepartmentDao departmentDao;
public boolean addDepartment(Department department) {
return departmentDao.addDepartment(department);
}
public Department queryById(Long id) {
return departmentDao.queryById(id);
}
public List<Department> queryAll() {
return departmentDao.queryAll();
}
}
controller/DepartmentController
package com.suda.springcloud.controller;
import com.suda.springcloud.pojo.Department;
import com.suda.springcloud.service.IDepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DepartmentController {
@Autowired
private IDepartmentService departmentService;
@PostMapping("/department/add")
public boolean addDepartment(Department department){
return departmentService.addDepartment(department);
}
@GetMapping("/department/get/{id}")
public Department addDepartmentById(@PathVariable("id") Long id){
return departmentService.queryById(id);
}
@GetMapping("/department/list")
public List<Department> queryDepartmentById ( ){
return departmentService.queryAll();
}
}
consumer
負責請求provider
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.suda</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.suda</groupId>
<artifactId>springcloud-consumer</artifactId>
<dependencies>
<dependency>
<groupId>com.suda</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
config/ConfigBean
package com.suda.springcloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {
//註冊 RestTemplate
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
conftoller/DepartmentConsumerController
package com.suda.springcloud.controller;
import com.suda.springcloud.pojo.Department;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DepartmentConsumerController {
//RestTemplate ... register it in spring,
//使用restful風格,從消費端訪問生產端,獲取資料。
@Autowired
private RestTemplate restTemplate;
private static final String rest_url_prefix = "http://localhost:8001";
@RequestMapping("/consumer/department/get/{id}")
public Department get(@PathVariable("id")Long id){
return restTemplate.getForObject(rest_url_prefix+"/department/get/"+id, Department.class);
}
@RequestMapping("/consumer/department/add")
public boolean add(Department department){
return restTemplate.postForObject(rest_url_prefix+"/department/add",department, Boolean.class);
}
@RequestMapping("/consumer/department/getall")
public List<Department> getList(){
return restTemplate.getForObject(rest_url_prefix+"/department/list",List.class);
}
}
application.yml
server:
port: 80
至此可以實現訪問consumer來獲得provider的服務,精髓在於使用restful風格,實現跨服務資料傳輸。
Eureka服務註冊與發現
eureka服務註冊中心實現
1.構建註冊中心服務模組
寫一個服務註冊模組,這部分是server端
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.suda</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.suda</groupId>
<artifactId>springcloud-eureka</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false # 是否向註冊中心註冊自己
fetch-registry: false
service-url: # 監控頁面
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# defaultZone: http://localhost:7001/eureka/
EurekaServer_7001.java主函式,注意註解
package com.suda.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer // 服務端的啟動類
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class, args);
}
}
2.將provider加進註冊中心
向pom.xml中新增erreka依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--完善監控資訊-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
departmentController類中新增服務檢視功能
@Autowired
private DiscoveryClient client;
// 獲取註冊的微服務資訊
@GetMapping("/department/discovery")
public Object discovery(){
List<String> services = client.getServices();
System.out.println(services);
// 得到一個具體的微服務資訊
List<ServiceInstance> instances = client.getInstances("springcloud-provider");
for (ServiceInstance instance : instances) {
System.out.println(instance.getHost()+"\t"+instance.getInstanceId()+"\t"+instance.getUri());
}
return client;
}
在主類上加註解
package com.suda.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //在服務啟動後自動註冊
@EnableDiscoveryClient //服務發現
public class DepartmentProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DepartmentProvider_8001.class, args);
}
}
application.yml新增註解
server:
port: 8001
mybatis:
type-aliases-package: com.suda.springcloud.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
config-location: classpath:mybatis/mybatis-config.xml
# configuration:
# map-underscore-to-camel-case: true
spring:
application:
name: springcloud-provider
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8&useSSL=true&useLegacyDatetimeCode=false&serverTimezone=America/New_York
username: spark
password: 123456
#eureka
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
instance:
instance-id: springcloud-provider #修改eureka上預設描述資訊
info:
app.name: springcloud-eureka
效果
可見spring單體專案到springcloud只需要幾個註解和幾行程式碼,體現出非侵入性。
註冊中心叢集
製作三個註冊中心模組並互相繫結
修改eureka對應application.yml配置
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false # 是否向註冊中心註冊自己
fetch-registry: false
service-url: # 監控頁面
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# defaultZone: http://localhost:7001/eureka/
defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/
修改provider/application.yml配置
#eureka
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
instance:
instance-id: springcloud-provider #修改eureka上預設描述資訊
info:
app.name: springcloud-eureka
啟動三個註冊中心和provider服務
問題,發現使用三個中心都使用localhost,三個中心無法互相發現,而且只有1-2個註冊中心能發現服務,猜測是三臺主機都叫localhost導致,故修改如下
修改主機host
修改eureka的application.yml
server:
port: 7003
eureka:
instance:
hostname: eureka7003
client:
register-with-eureka: false # 是否向註冊中心註冊自己
fetch-registry: false
service-url: # 監控頁面
defaultZone: http://eureka7001:7001/eureka/,http://eureka7002:7002/eureka/
# defaultZone: http://localhost:7001/eureka/
修改provider的application.yml
server:
port: 8001
mybatis:
type-aliases-package: com.suda.springcloud.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
config-location: classpath:mybatis/mybatis-config.xml
# configuration:
# map-underscore-to-camel-case: true
spring:
application:
name: springcloud-provider
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8&useSSL=true&useLegacyDatetimeCode=false&serverTimezone=America/New_York
username: spark
password: 123456
#eureka
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider #修改eureka上預設描述資訊
info:
app.name: springcloud-eureka
展示,註冊中心可以互相發現,服務也可以發現
Eureka和Zookeeper
zookeeper保證的cp,容忍服務可用性差,但一致性必須高,
Ribbon
Ribbon實現負載均衡
在消費端修改
pom.xml新增依賴
<!--ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
application.yml 配置eureka
server:
port: 80
#eureka config
eureka:
client:
register-with-eureka: false # 不需要註冊消費端
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
configBean加註解
@Configuration
public class ConfigBean {
//註冊 RestTemplate
@Bean
// 配置實現負載均衡
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
departmentConsumer.java 加註解
@SpringBootApplication
@EnableEurekaClient
public class DepartmentConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DepartmentConsumer_80.class,args);
}
}
controller/DepartmentConsumerController.java 修改訪問地址
package com.suda.springcloud.controller;
import com.suda.springcloud.pojo.Department;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DepartmentConsumerController {
//RestTemplate ... register it in spring,
//使用restful風格,從消費端訪問生產端,獲取資料。
@Autowired
private RestTemplate restTemplate;
//單機用這個訪問地址
// private static final String rest_url_prefix = "http://localhost:8001";
// 通過ribbon實現負載均衡,通過服務名來訪問,實現動態訪問
private static final String rest_url_prefix = "http://springcloud-provider";
@RequestMapping("/consumer/department/get/{id}")
public Department get(@PathVariable("id")Long id){
return restTemplate.getForObject(rest_url_prefix+"/department/get/"+id, Department.class);
}
@RequestMapping("/consumer/department/add")
public boolean add(Department department){
return restTemplate.postForObject(rest_url_prefix+"/department/add",department, Boolean.class);
}
@RequestMapping("/consumer/department/getall")
public List<Department> getList(){
return restTemplate.getForObject(rest_url_prefix+"/department/list",List.class);
}
}
模擬負載均衡
再造兩個生產者,對應資料庫db01,db02
複製目錄出現問題,導致8002,8003執行找不到主類
啟動七個服務:
結果:
預設輪詢查詢,且找不到三
注意:在mapper中寫增刪查改的時候,不要加上資料庫名,否則查詢的資料庫單一。
自定義Ribbon負載均衡演算法
不能喝主類在一個目錄,不然會被springscan到,所以可以放上一級目錄
Feign
服務熔斷
測試
1.拷貝一份provider,新建hystrix
2.匯入pom依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
3.controller/DepartmentController.java只寫兩個方法測試
package com.suda.springcloud.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.suda.springcloud.pojo.Department;
import com.suda.springcloud.service.IDepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DepartmentController {
@Autowired
private IDepartmentService departmentService;
@GetMapping("/department/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGetById")
public Department getDepartmentById(@PathVariable("id") Long id) {
Department department = departmentService.queryById(id);
if(department == null){
throw new RuntimeException("the user is not exist");
}
return department;
}
public Department hystrixGetById(@PathVariable("id") Long id) {
return new Department().setDepartmentId(id)
.setDepartmentName("without the user information_hystrix")
.setDbSource("no this database in MySql");
}
// @PostMapping("/department/add")
// public boolean addDepartment(Department department){
// return departmentService.addDepartment(department);
// }
//
// @GetMapping("/department/get/{id}")
// public Department addDepartmentById(@PathVariable("id") Long id){
// return departmentService.queryById(id);
// }
//
// @GetMapping("/department/list")
// public List<Department> queryDepartmentById ( ){
// return departmentService.queryAll();
// }
@Autowired
private DiscoveryClient client;
// 獲取註冊的微服務資訊
@GetMapping("/department/discovery")
public Object discovery(){
List<String> services = client.getServices();
System.out.println(services);
// 得到一個具體的微服務資訊
List<ServiceInstance> instances = client.getInstances("springcloud-provider");
for (ServiceInstance instance : instances) {
System.out.println(instance.getHost()+"\t"+instance.getInstanceId()+"\t"+instance.getUri());
}
return client;
}
}
4.主類+熔斷註解
package com.suda.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableEurekaClient //在服務啟動後自動註冊
@EnableDiscoveryClient //服務發現
@EnableCircuitBreaker //開啟熔斷
public class DepartmentProvider_hystrix {
public static void main(String[] args) {
SpringApplication.run(DepartmentProvider_hystrix.class, args);
}
}
結果:
服務降級
服務降級是指某個服務不可用後,返回較友好的提示介面,並且不影響使用者訪問其他服務,需要自定義類,並實現之前寫的IDepartmentClientService介面
package com.suda.springcloud.service;
import com.suda.springcloud.pojo.Department;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
//服務降級
@Component
public class DepartmentClientServiceFallbackFactory implements FallbackFactory {
public IDepartmentClientService create(Throwable throwable) {
return new IDepartmentClientService() {
public Department queryById(Long id) {
return new Department().setDepartmentId(id)
.setDepartmentName("客戶端提供了降級操作,這個服務已關閉")
.setDbSource("沒有資料");
}
public List<Department> queryAll() {
return (List<Department>) new Department().setDepartmentId((long) 0)
.setDepartmentName("客戶端提供了降級操作,這個服務已關閉")
.setDbSource("沒有資料");
}
public Department addDepartment(Department department) {
return new Department().setDepartmentId((long) 0)
.setDepartmentName("客戶端提供了降級操作,這個服務已關閉")
.setDbSource("沒有資料");
}
};
}
}
HystrixDashboard
配置監控客戶端
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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.suda</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.suda</groupId>
<artifactId>springcloud-consumer-dashboard</artifactId>
<dependencies>
<dependency>
<groupId>com.suda</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<!--ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
application.xml
server:
port: 9001
Dashboard9001
package com.suda.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
@EnableCircuitBreaker
public class Dashboard9001 {
public static void main(String[] args) {
SpringApplication.run(Dashboard9001.class, args);
}
}
provider端
pom新增
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
啟動函式
@SpringBootApplication
@EnableEurekaClient //在服務啟動後自動註冊
@EnableDiscoveryClient //服務發現
@EnableCircuitBreaker
public class DepartmentProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DepartmentProvider_8001.class, args);
}
@Bean
public ServletRegistrationBean HystrixMetricsStreamServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
bean.addUrlMappings("/actuator/hystrix.stream");
return bean;
}
}
Zuul路由閘道器
實戰
新建路由模組
pom新增配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
application。yml
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: zuul9527.com
prefer-ip-address: true
info:
app.name: springcloud
company.name: com.suda
zuul:
routes:
departments:
serviceId: springcloud-provider
path: /mydept/* #修改url路徑
# ignored-services: springcloud-provider #不能用這個路徑訪問
# ignored-services: "*"
啟動類
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
SpringCloud Config
參考自狂神
相關文章
- 【SpringCloud】SpringCloud(二)之RibbonSpringGCCloud
- 【SpringCloud】(一):SpringCloud入門程式SpringGCCloud
- SpringCloud學習之路(一)- 走進SpringCloudSpringGCCloud
- springCloud/印象SpringGCCloud
- springcloud~SentinelSpringGCCloud
- SpringCloud學習筆記:SpringCloud簡介(1)SpringGCCloud筆記
- SpringCloud學習筆記(一) 搭建一個SpringCloudSpringGCCloud筆記
- SpringCloud系列(一)SpringGCCloud
- SpringCloud之zuulSpringGCCloudZuul
- SpringCloud之HystrixSpringGCCloud
- SpringCloud之EurekaSpringGCCloud
- springcloud介紹SpringGCCloud
- SpringCloud(三) ZuulSpringGCCloudZuul
- SpringCloud (一) EurekaSpringGCCloud
- SpringCloud、Dubbo、IstioSpringGCCloud
- SpringCloud 總覽SpringGCCloud
- springcloud整合sleuthSpringGCCloud
- SpringCloud-84SpringGCCloud
- SpringCloud-85SpringGCCloud
- SpringCloud-86SpringGCCloud
- SpringCloud-87SpringGCCloud
- SpringCloud-88SpringGCCloud
- SpringCloud-89SpringGCCloud
- SpringCloud-90SpringGCCloud
- SpringCloud之GatewaySpringGCCloudGateway
- springcloud學習SpringGCCloud
- SpringCloud入門SpringGCCloud
- SpringCloud-NacosSpringGCCloud
- SpringCloud(四)DockerSpringGCCloudDocker
- SpringCloud(六)RabbitMQSpringGCCloudMQ
- SpringCloud Alibaba開篇:SpringCloud這麼火,為何還要學習SpringCloud Alibaba?SpringGCCloud
- 每天學點SpringCloud(十四):Zipkin使用SpringCloud Stream以及ElasticsearchSpringGCCloudElasticsearch
- springcloud微服務分散式雲架構-SpringCloud簡介SpringGCCloud微服務分散式架構
- (一)springcloud微服務分散式雲架構-SpringCloud簡介SpringGCCloud微服務分散式架構
- SpringCloud Nacos 配置中心SpringGCCloud
- springcloud-路由gatewaySpringGCCloud路由Gateway
- SpringCloud微服務治理SpringGCCloud微服務
- Springcloud(二) feignSpringGCCloud