为了项目名称不要太长,把SpringCloudMicroService缩写为SCMS。
SCMS-Parent 各个模块的聚合工程同时也是父工程
SCMS-API 公共API工程模块
SCMS-Provider-Dept8001 服务提供者,通过8001端口访问
SCMS-Consummer-Dept80 服务消费者,通过80端口访问
UTF-8
1.8
1.8
4.12
1.2.17
org.springframework.cloud
spring-cloud-dependencies
Dalston.SR1
pom
import
org.springframework.boot
spring-boot-dependencies
1.5.9.RELEASE
pom
import
mysql
mysql-connector-java
5.0.4
com.alibaba
druid
1.0.31
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.0
ch.qos.logback
logback-core
1.2.3
junit
junit
${junit.version}
test
log4j
log4j
${log4j.version}
在SCMS-Parent工程上点右键,然后new
包名:com.atguigu.cloud.entities
public class Dept implements Serializable{
private static final long serialVersionUID = 1L;
private Integer deptNo;
private String deptName;
private String dbSource;
……
在SCMS-Parent工程上点右键,然后new
mysql
mysql-connector-java
com.alibaba
druid
ch.qos.logback
logback-core
org.mybatis.spring.boot
mybatis-spring-boot-starter
org.springframework.boot
spring-boot-starter-jetty
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework
springloaded
org.springframework.boot
spring-boot-devtools
DROP DATABASE IF EXISTS `cloud_db_one`;
CREATE DATABASE `cloud_db_one` CHARACTER SET utf8 COLLATE utf8_bin;
USE cloud_db_one;
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`dept_no` int(11) NOT NULL AUTO_INCREMENT,
`dept_name` varchar(500) DEFAULT NULL,
`db_source` varchar(500) DEFAULT NULL,
PRIMARY KEY (`dept_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES ('1', 'IT', DATABASE());
INSERT INTO `dept` VALUES ('2', 'HR', DATABASE());
INSERT INTO `dept` VALUES ('3', 'MIS', DATABASE());
INSERT INTO `dept` VALUES ('4', 'FUN', DATABASE());
INSERT INTO `dept` VALUES ('5', 'WM', DATABASE());
INSERT INTO `dept` VALUES ('6', 'EI', DATABASE());
INSERT INTO `dept` VALUES ('7', 'UU', DATABASE());
包名:com.atguigu.springcloud.mapper
package com.atguigu.springcloud.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.atguigu.cloud.entities.Dept;
@Mapper//千万记得加这个注解!!!
public interface DeptMapper {
Dept findById(Integer deptNo);
List findAll();
boolean addDept(Dept dept);
}
位置:
INSERT INTO dept(dept_name,db_source) VALUES(#{deptName},DATABASE());
位置:
位置:
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml
type-aliases-package: com.atguigu.cloud.entities
mapper-locations:
spring:
application:
name: Atguigu-SCMS-Dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/cloud_db_one
username: root
password: root
dbcp2:
min-idle: 5
initial-size: 5
max-total: 5
max-wait-millis: 200
spring.application.name配置的是这个微服务的名字,将来在注册中心中显示的和消费端引用的都是这个名字。
4.6. Service层
4.6.1. 接口
package com.atguigu.springcloud.service;
import java.util.List;
import com.atguigu.cloud.entities.Dept;
public interface DeptService {
Dept findById(Integer deptNo);
List findAll();
boolean addDept(Dept dept);
}
4.6.2. 实现类
package com.atguigu.springcloud.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.atguigu.cloud.entities.Dept;
import com.atguigu.springcloud.mapper.DeptMapper;
import com.atguigu.springcloud.service.DeptService;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public Dept findById(Integer deptNo) {
return deptMapper.findById(deptNo);
}
@Override
public List findAll() {
return deptMapper.findAll();
}
@Override
public boolean addDept(Dept dept) {
return deptMapper.addDept(dept);
}
}
4.7. Controller层
package com.atguigu.springcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.atguigu.cloud.entities.Dept;
import com.atguigu.springcloud.service.DeptService;
@RestController//相当于@Controller+@ResponseBody
public class DeptController {
@Autowired
private DeptService deptService;
@RequestMapping(value="/dept/add", method=RequestMethod.POST)
public boolean add(@RequestBody Dept dept) {
return deptService.addDept(dept);
}
@RequestMapping(value="/dept/get/{deptNo}", method=RequestMethod.GET)
public Dept get(@PathVariable("deptNo") Integer deptNo) {
return deptService.findById(deptNo);
}
@RequestMapping(value="/dept/get/all", method=RequestMethod.GET)
public List getAll() {
return deptService.findAll();
}
}
4.8. 主程序
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SCMSProviderDept8001 {
public static void main(String[] args) {
SpringApplication.run(SCMSProviderDept8001.class, args);
}
}
4.9. 测试
以Spring Boot App的方式运行工程
通过浏览器访问http://localhost:8001/dept/get/all
5. SCMS-Consummer-Dept80创建过程
5.1. 创建Maven模块
在SCMS-Parent工程上点右键,然后new
5.2. 编辑pom.xml
org.springframework.boot
spring-boot-starter-web
org.springframework
springloaded
org.springframework.boot
spring-boot-devtools
com.atguigu.scms
SCMS-API
0.0.1-SNAPSHOT
5.3. 创建application.yml
server:
port: 80
5.4. 创建ConfigBean类
package com.atguigu.cloud.config.beans;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
相当于
5.5. 创建DeptControllerConsummer类
package com.atguigu.cloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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 com.atguigu.cloud.entities.Dept;
@RestController
public class DeptControllerConsummer {
private static final String REST_URL_PREFIX = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consummer/dept/add")
public boolean add(Dept dept) {
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class);
}
@RequestMapping("/consummer/dept/get/{deptNo}")
public Dept get(@PathVariable("deptNo") Integer deptNo) {
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+deptNo, Dept.class);
}
@SuppressWarnings("unchecked")
@RequestMapping("/consummer/dept/get/all")
public List getAll() {
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/all", List.class);
}
}
5.6. 主程序
5.7. 测试
以Spring Boot App方式运行程序
访问http://localhost/consummer/dept/get/all
6. 遗留问题
Consummer通过http://localhost:8001来访问Provider中提供的服务需要知道IP地址和端口号,但是Provider微服务是有名字的,如果能够通过名字代替IP地址和端口号就能够简单很多,该如何做到呢?
我们下面要学习的Eureka注册中心可以解决这个问题。
SpringCloud 单机版Eureka
简介
Eureka相当于我们熟悉的Zookeeper,用来注册我们的微服务。
创建SCMS-Eureka-7000工程模块
2.1. 创建Maven模块
2.2. 编辑pom.xml
org.springframework.cloud spring-cloud-starter-eureka-server org.springframework springloaded org.springframework.boot spring-boot-devtools2.3. 创建application.yml
server:
port: 7000
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http:// e u r e k a . i n s t a n c e . h o s t n a m e : {eureka.instance.hostname}: eureka.instance.hostname:{server.port}/eureka/ #指定客户端访问Eureka服务端的URL地址
2.4. 主程序
@SpringBootApplication
@EnableEurekaServer //把当前微服务标记为Eureka注册中心,接受其他微服务的注册
public class SpringCloudEurekaApp {
public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaApp.class, args);
}
}
2.5. 测试
以Spring Boot App方式运行工程
访问http://localhost:7000
将SCMS-Provider-Dept8001注册进Eureka
3.1. 编辑pom.xml
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-config
3.2. 编辑application.yml
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka
参照:defaultZone: http:// e u r e k a . i n s t a n c e . h o s t n a m e : {eureka.instance.hostname}: eureka.instance.hostname:{server.port}/eureka/
3.3. 修改SCMS-Provider-Dept8001主程序
@SpringBootApplication
@EnableEurekaClient //该微服务将参照application.yml中的配置注册到Eureka
public class SCMSProviderDept8001 {
public static void main(String[] args) {
SpringApplication.run(SCMSProviderDept8001.class, args);
}
}
3.4. 测试
在Eureka微服务已经启动的前提下,启动SCMS-Provider-Dept8001。
4.2. 编辑application.yml
eureka:
client:
register-with-eureka: false #当前是微服务的调用端、消费端,不进行注册
service-url:
defaultZone: http://localhost:7000/eureka
4.3. 修改SCMS-Consummer-Dept80主程序
@SpringBootApplication
@EnableEurekaClient
public class SCMSConsummer80 {
public static void main(String[] args) {
SpringApplication.run(SCMSConsummer80.class, args);
}
}
4.4. 修改ConfigBean
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
这里其实已经用到了Ribbon,这是SpringCloud技术栈中的负载均衡工具,后面会讲到,现在你先知道Eureka需要和Ribbon配合起来才能实现服务名替代效果。
4.5. 用微服务名替代IP地址加端口号
//private static final String REST_URL_PREFIX = “http://localhost:8001”;
private static final String REST_URL_PREFIX = “http://ATGUIGU-SCMS-DEPT”;
SpringCloud 集群版Eureka
2.2. 创建SCMS-Eureka-7001和SCMS-Eureka-7002工程
类似于创建SCMS-Eureka-7000
2.3. 编辑pom.xml
org.springframework.cloud
spring-cloud-starter-eureka-server
org.springframework
springloaded
org.springframework.boot
spring-boot-devtools
2.4. 编辑application.yml
2.4.1. 7000
server:
port: 7000
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://www.eureka7001.com:7001/eureka/,http://www.eureka7002.com:7002/eureka/ #指定客户端访问Eureka服务端的URL地址
2.4.2. 7001
配置7000和7002的地址
2.4.3. 7002
配置7000和7001的地址
2.5. 测试
分别以Spring Boot App方式运行三个工程,访问其中一个
http://www.eureka7000.com:7000/
3.2. 启动SCMS-Provider-Dept8001
3.3. 查看服务注册情况
SpringCloud Ribbon
cloud_db_two
;cloud_db_two
CHARACTER SET utf8 COLLATE utf8_bin;dept
;dept
(dept_no
int(11) NOT NULL AUTO_INCREMENT,dept_name
varchar(500) DEFAULT NULL,db_source
varchar(500) DEFAULT NULL,dept_no
)– Records of dept
INSERT INTO dept
VALUES (‘1’, ‘IT’, DATABASE());
INSERT INTO dept
VALUES (‘2’, ‘HR’, DATABASE());
INSERT INTO dept
VALUES (‘3’, ‘MIS’, DATABASE());
INSERT INTO dept
VALUES (‘4’, ‘FUN’, DATABASE());
INSERT INTO dept
VALUES (‘5’, ‘WM’, DATABASE());
INSERT INTO dept
VALUES (‘6’, ‘EI’, DATABASE());
INSERT INTO dept
VALUES (‘7’, ‘UU’, DATABASE());
DROP DATABASE IF EXISTS cloud_db_three
;
CREATE DATABASE cloud_db_three
CHARACTER SET utf8 COLLATE utf8_bin;
USE cloud_db_three;
DROP TABLE IF EXISTS dept
;
CREATE TABLE dept
(
dept_no
int(11) NOT NULL AUTO_INCREMENT,
dept_name
varchar(500) DEFAULT NULL,
db_source
varchar(500) DEFAULT NULL,
PRIMARY KEY (dept_no
)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
– Records of dept
INSERT INTO dept
VALUES (‘1’, ‘IT’, DATABASE());
INSERT INTO dept
VALUES (‘2’, ‘HR’, DATABASE());
INSERT INTO dept
VALUES (‘3’, ‘MIS’, DATABASE());
INSERT INTO dept
VALUES (‘4’, ‘FUN’, DATABASE());
INSERT INTO dept
VALUES (‘5’, ‘WM’, DATABASE());
INSERT INTO dept
VALUES (‘6’, ‘EI’, DATABASE());
INSERT INTO dept
VALUES (‘7’, ‘UU’, DATABASE());
2.2. 新建8002和8003工程
SCMS-Provider-Dept8002
SCMS-Provider-Dept8003
pom.xml文件内容和8001一致,Java代码也一致
2.3. 修改8002和8003的yml文件
从8001那里把application.yml复制过来,然后修改下面配置项
server.port: 8002
spring.datasource.url: jdbc:mysql://localhost:3306/cloud_db_two
server.port: 8003
spring.datasource.url: jdbc:mysql://localhost:3306/cloud_db_three
注意:8001和8002以及8003要想成为一个集群,分担负载,那么对外暴露的微服务名称必须一致。也就是说,spring.application.name配置项要一致。这里我们都是复制过来的,不修改就可以了。
2.4. 启动Provider集群并测试
http://localhost:8001/dept/get/all
http://localhost:8002/dept/get/all
http://localhost:8003/dept/get/all
3. 负载均衡测试
我们前面为了Consummer80工程能够通过微服务名称调用微服务其实已经完成Ribbon的配置了,这里再重申一下Ribbon的配置:
3.1. 确认pom.xml文件
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-ribbon
org.springframework.cloud
spring-cloud-starter-config
3.2. 确认ConfigBean中getRestTemplate()方法注解
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
3.3. 访问Consummer80工程
http://localhost/consummer/dept/get/all
如果看到不同请求访问时看到的数据库名数据不一样那么说明负载均衡配置成功。
SpringCloud Feign
2.2. 创建DeptClientService接口
package com.atguigu.cloud.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.atguigu.cloud.entities.Dept;
//指定要调用的微服务名称
@FeignClient(value=“ATGUIGU-SCMS-DEPT”)
public interface DeptClientService {
@RequestMapping(value="/dept/add", method=RequestMethod.POST)
public boolean add(Dept dept);
@RequestMapping(value="/dept/get/{deptNo}", method=RequestMethod.GET)
public Dept get(@PathVariable("deptNo") Integer deptNo);
@RequestMapping(value="/dept/get/all", method=RequestMethod.GET)
public List getAll();
}
3. 创建SCMS-Consummer-Feign工程
SCMS-Consummer-Feign工程是SCMS-Consummer-Dept80的升级版,所以有些配置相似。
3.1. 创建Maven模块
pom.xml文件和SCMS-Consummer-Dept80工程一致。
3.2. 创建Controller
这时不再需要RestTemplate了,Feign中也内置了Ribbon。
package com.atguigu.cloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.atguigu.cloud.entities.Dept;
import com.atguigu.cloud.service.DeptClientService;
@RestController
public class FeignController {
@Autowired
private DeptClientService feignService;
@RequestMapping(value="/consummer/feign/dept/add",method=RequestMethod.POST)
public boolean add(Dept dept) {
return feignService.add(dept);
}
@RequestMapping(value="/consummer/feign/dept/get/{deptNo}",method=RequestMethod.GET)
public Dept getById(@PathVariable("deptNo") Integer deptNo) {
return feignService.get(deptNo);
}
@RequestMapping(value="/consummer/feign/dept/get/all", method=RequestMethod.GET)
public List getList() {
return feignService.getAll();
}
}
3.3. 创建主程序
package com.atguigu.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SCMSConsummerFeigh {
public static void main(String[] args) {
SpringApplication.run(SCMSConsummerFeigh.class, args);
}
}
SpringCloud Hystrix
在微服务架构体系下,服务间的调用错综复杂,交织成一张大网。如果其中某个节点突然无法正常工作,则访问它的众多服务都会被卡住,进而有更多服务被卡住,系统中的线程、CPU、内存等资源有可能被迅速耗尽,最终整个服务体系崩溃。
我们管这样的现象叫服务雪崩。
1.2. Hytrix介绍
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
Hytrix能够提供服务降级、服务熔断、服务限流、接近实时的监控等方面的功能。
2. 服务熔断机制
熔断机制是应对雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速响应错误信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
2.1. 创建SCMS-Provider-Hystrix-8004工程
2.2. 编辑pom.xml
在SCMS-Provider-Dept8001基础上添加Hystrix依赖
org.springframework.cloud
spring-cloud-starter-hystrix
2.3. 编辑yml文件
在SCMS-Provider-Dept8001基础上修改端口号和应用名称
server:
port: 8004
spring:
application:
name: Atguigu-SCMS-Hystrix-Dept
2.4. Java代码
把SCMS-Provider-Dept8001的Java代码复制过来。
2.4.1. 修改DeptController
我们发现@HystrixCommand注解的fallbackMethod属性指定的方法入参和返回值都和原方法一致。这就保证了原方法出现问题时可以由fallbackMethod方法来接替,从而返回一个可以让调用者继续执行其他任务的响应信息。
package com.atguigu.springcloud.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.atguigu.cloud.entities.Dept;
import com.atguigu.springcloud.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@RequestMapping(value="/dept/get/{deptNo}", method=RequestMethod.GET)
@HystrixCommand(fallbackMethod="hystrixGet")
public Dept get(@PathVariable("deptNo") Integer deptNo) {
Dept dept = deptService.findById(deptNo);
if(dept == null) {
throw new RuntimeException("未找到和"+deptNo+"对应的信息!");
}
return dept;
}
public Dept hystrixGet(@PathVariable("deptNo") Integer deptNo) {
return new Dept(deptNo, "与"+deptNo+"对应的Dept信息未找到!", "对应数据库信息未找到!");
}
}
2.4.2. 修改主程序
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker //启用对Hystrix熔断机制的支持
public class SCMSProviderHystrixDept {
public static void main(String[] args) {
SpringApplication.run(SCMSProviderHystrixDept.class, args);
}
}
2.5. 测试
这时启动Eureka集群和SCMS-Provider-Hystrix-8004工程即可。
http://localhost:8004/dept/get/3
{“deptNo”:3,“deptName”:“MIS”,“dbSource”:“cloud_db_three”}
http://localhost:8004/dept/get/344
{“deptNo”:344,“deptName”:“与”+deptNo+“对应的Dept信息未找到!”,“dbSource”:“对应数据库信息未找到!”}
3. 服务降级机制
3.1. 简介
服务降级处理是在客户端(Consummer端)实现完成的,与服务端(Provider端)没有关系。当某个Consummer访问一个Provider却迟迟得不到响应时执行预先设定好的一个解决方案,而不是一直等待。
3.2. 修改SCMS-API工程
3.2.1. 创建一个工厂类实现FallbackFactory接口
package com.atguigu.cloud.service.factory;
import java.util.List;
import org.springframework.stereotype.Component;
import com.atguigu.cloud.entities.Dept;
import com.atguigu.cloud.service.DeptClientService;
import feign.hystrix.FallbackFactory;
@Component //非常容易忘!!!
public class DeptClientServiceFallBackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept get(Integer deptNo) {
return new Dept(deptNo, "与"+deptNo+"对应的信息未找到[Consummer]", "数据库不存在");
}
@Override
public List getAll() {
return null;
}
@Override
public boolean add(Dept dept) {
// TODO Auto-generated method stub
return false;
}
};
}
}
3.2.2. 修改DeptClientService接口的@FeignClient注解
@FeignClient(
value=“ATGUIGU-SCMS-DEPT”,
fallbackFactory=DeptClientServiceFallBackFactory.class)
public interface DeptClientService {
3.3. 修改SCMS-Consummer-Feign工程的yml文件
添加:
feign:
hystrix:
enabled: true
3.4. 测试
启动Eureka集群
启动一个没有加熔断机制的Provider
启动Feign Consummer
先测试正常访问,然后关掉Provider后再访问
4. 服务监控
4.1. 新建Maven模块
4.2. 编辑pom.xml
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-hystrix
org.springframework.cloud
spring-cloud-starter-hystrix-dashboard
4.3. 创建yml文件
server:
port: 9001
4.4. 主程序
@SpringBootApplication
@EnableHystrixDashboard
public class SpringCloudHytrixDashBord {
public static void main(String[] args) {
SpringApplication.run(SpringCloudHytrixDashBord.class, args);
}
}
yml 配置
server:
port: 9001
4.5. 给被监控的微服务添加依赖
org.springframework.boot
spring-boot-starter-actuator
注意:被监控的微服务也需要配置好熔断机制才可以。目前我们的工程中SCMS-Provider-Hystrix-8004满足这个要求。
4.6. 查看监控信息
4.6.1. 监控首页
http://localhost:9001/hystrix
4.6.2. 直接查看监控数据
http://localhost:8004/hystrix.stream
8004是被监控的微服务端口
4.6.3. 图形化界面方式查看监控数据
Delay:该参数用来控制服务器上轮询监控信息的延迟时间,默认为2000毫秒,可以通过配置该属性来降低客户端的网络和CPU消耗。
Title:该参数对应了头部标题Hystrix Stream之后的内容,默认会使用具体监控实例的URL,可以通过配置该信息来展示更合适的标题。
4.6.4. 参数说明
4.6.5. 复杂监控效果示例
SpringCloud Zuul
2.2. 编辑pom.xml
org.springframework.cloud
spring-cloud-starter-zuul
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-hystrix
org.springframework.cloud
spring-cloud-starter-config
org.springframework.boot
spring-boot-starter-jetty
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework
springloaded
org.springframework.boot
spring-boot-devtools
2.3. 编辑yml文件
server:
port: 9002
spring:
application:
name: scms-zuul-gateway //网关在eurka上注册的服务名;
eureka:
client:
service-url:
defaultZone: http://www.eureka7000.com:7000/eureka,http://www.eureka7001.com:7001/eureka,http://www.eureka7002.com:7002/eureka
2.4. 主程序
@SpringBootApplication
@EnableZuulProxy
public class SpringCloudZuulApp {
public static void main(String[] args) {
SpringApplication.run(SpringCloudZuulApp.class, args);
}
}
2.5. 初步测试
启动Eureka集群
启动SCMS-Provider-Hystrix-8004供访问测试
启动SCMS-Zuul-9002
查看Eureka上注册的服务
不用路由直接访问http://localhost:8004/dept/get/3
通过路由访问
http://localhost:9002/atguigu-scms-hystrix-dept/dept/get/3
3. 路由访问映射规则
3.1. 隐藏微服务名称
在Zuul工程的application.yml中配置:
zuul:
routes:
atguigu.serviceId: atguigu-scms-hystrix-dept (atguigu可以省略直接写serviceId)
atguigu.path: /atguigu-demo/**
访问方式http://localhost:9002/atguigu-demo/dept/get/2
3.2. 原真实服务名忽略
经过上面的配置后,既可以使用别名访问,又可以使用原服务名访问。
例如http://localhost:9003/atguigu-scms-hystrix-dept/dept/get/2
如果希望只能通过别名访问,可以做这样的配置:
zuul:
ignored-services: atguigu-scms-hystrix-dept
routes:
atguigu.serviceId: atguigu-scms-hystrix-dept
atguigu.path: /atguigu-demo/**
如果希望屏蔽所有微服务原名称可以使用“”
zuul:
ignored-services: ""
routes:
atguigu.serviceId: atguigu-scms-hystrix-dept
atguigu.path: /atguigu-demo/**
3.3. 统一设置公共前缀
zuul:
prefix: /good
ignored-services: “*”
routes:
atguigu.serviceId: atguigu-scms-hystrix-dept
atguigu.path: /atguigu-demo/**
设置后所有微服务名前面都需要再加上前缀才可以访问