SpringCloud
热部署依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
一般集成流程:
1、导入依赖
2、编辑配置文件
3、开启这个功能 @EnableXXXX
4、配置类
一、Eureka(服务注册与发现)
1.1 集成注册中心
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
配置文件:
server:
port: 7001
#Eureka配置
eureka:
instance:
hostname: localhost #Eureka 服务端的实例名称
client:
register-with-eureka: false #表示是否向eureka注册中心注册自己
fetch-registry: false #fetch-registry 如果为 false,则表示自己是注册中心
service-url: # 监控页面地址~ (与eureka服务中心交互的地址)
#defaultZone : 重写默认的监控地址(不用默认的,用自己的),模拟默认地址格式
# 单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# 集群(关联):
defaultZone: http://localhost:7001/eureka/
# defaultZone: http://eureka7002:7002/eureka/,http://eureka7003:7003/eureka/
开启功能:
@EnableEurekaServer //EnableEurekaServer 服务端的启动类,可以接受别人注册进来
1.2 服务提供者集成Eureka
依赖:
<!--加入Eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--actuator 完善监控信息-->
<!--配置文件中定义info~,需要导入这个依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置文件:
#Eureka的配置,服务注册到哪里
eureka:
client:
service-url: #因为要到注册服务中心拿一样的数据,所以配置路径要和注册服务中心一样的数据
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
instance:
instance-id: springcloud-provider-dept-8001 #修改Eureka上的默认描述信息!
prefer-ip-address: true #显示服务的IP地址(鼠标放上提示的提示信息,例如 : localhost/127.0.0.1 => 192.168.11.107)
#监控服务默认配置,由 actuator 包提供
info: #路径信息点进去后,以json格式呈现
app.name: zhanggaohe-springcloud #项目名字
company.name: '张的SpringCloud初使用'
开启功能:
@EnableEurekaClient //CS架构 在服务启动后自动注册到Eureka中!
@EnableDiscoveryClient //服务发现~
@EnableDiscoveryClient和@EnableEurekaClient共同点就是:都是能够让注册中心能够发现,扫描到改服务。
不同点:
@EnableEurekaClient
只适用于Eureka作为注册中心,@EnableDiscoveryClient
可以是其他注册中心。@EnableDiscoveryClient基于spring-cloud-commons,并且在classpath中实现。
@EnableEurekaClient基于spring-cloud-netflix,只能为eureka作用。
就是如果选用的注册中心是eureka推荐@EnableEurekaClient,如果是其他的注册中心推荐使用@EnableDiscoveryClient,如果classpath中添加了eureka,则它们的作用是一样的。
获取配置信息~~配置类(Controller层):
//注册cloud的DiscoveryClient接口
//获取一些配置的信息,得到具体的微服务!
@Autowired
private DiscoveryClient client;
//注册进来的微服务~,获取一些消息~
/*需要在启动类上配置 ==服务发现注解== */
@GetMapping("/dept/discovery")
public Object discovery() {
//获取微服务列表的清单
List<String> services = client.getServices();
System.out.println("discovery=>services:"+services);
//得到一个具体的微服务信息,通过具体的微服务id,applicationName
List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
//循环遍历 instances 实例
for (ServiceInstance instance : instances) {
System.out.println(
instance.getHost()+"\t"+
instance.getPort()+"\t"+
instance.getUri()+"\t"+
instance.getServiceId()
);
}
return this.client;
}
1.3 消费者提供集成Eureka
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
配置文件:
#Eureka配置 == 负载均衡ribbon
eureka:
client:
register-with-eureka: false #不向Eureka注册自己
service-url:
defaultZone: http://localhost:7001/eureka/
# deafultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
开启功能:
@EnableEurekaClient //CS架构 在服务启动后自动注册到Eureka中!
二、Ribbon&Feign(负载均衡)
2.1 集成Ribbon
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
配置文件:
#Eureka配置 == 负载均衡ribbon
eureka:
client:
register-with-eureka: false #不向Eureka注册自己
service-url:
defaultZone: http://localhost:7001/eureka/
# deafultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
开启功能:
//在微服务启动的时候就能去加载我们自定义的Ribbon类
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = ZhangRule.class)
必须实现配置类:
@Configuration
public class ConfigBean { //@Configuration 相当于 spring application.xml
//IRule
//AvailabilityFilteringRule: 会先过滤掉,跳闸,访问故障的服务~,然后对剩下的进行轮询
//RoundRobinRule 轮询 ==默认==
//RandomRule 随机
//WeightedResponseTimeRule 权重
//RetryRule 重试 ,会先按照轮询获取服务~,如果获取服务失败,则会在指定时间内 重试
@Bean
@LoadBalanced //配置负载均衡,实现 RestTemplate (Ribbon)
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
根据服务注册IP进行查找/跳转 ~ Controller层:
//理解 消费者,不应该有service层
//RestTemplate 供我们直接调用就可以了! 注册到spring中
//RestTemplate 常用方法(url,实体:Map,class<T> responseType)
@Autowired
private RestTemplate restTemplate; //提供多种便捷访问远程http服务的方法,简称Restful服务模板
//地址敞常量前缀
// private static final String REST_URL_PREFIX = "http://localhost:8001/";
//使用Ribbon负载均衡,这里的地址应该是一个变量(即注册中心的id),通过服务名来访问
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
//查所有
@RequestMapping("/consumer/dept/list")
public List<Dept> deptList() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
}
自定义配置类:(注意不能与默认扫描的启动类同级,官方推荐在上一级定义,例: com.zhang.cloud => com.zhang 下创建)
@Configuration
public class ZhangRule {
//自己的组件放在外面
//自己定义的路由,负载均衡规则,不能与springboot同级,会直接被加载到
// 可以在主方法上,通过注解定义位置
@Bean
// public IRule myRule() {
// return new ZhangRandomRule(); //默认是轮询,现在用我们自己定义的~ ZhangRandomRule
// }
public IRule myRule() {
return new RoundRobinRule(); //自己定义的有些问题,服务器容易崩掉,这里采用自带 轮询 算法
}
}
不完善的自定义配置类 例:
public class ZhangRandomRule extends AbstractLoadBalancerRule {
//每个机器访问五次,然后换下一个服务
//total(指针/总数) , 默认 total=0,如果 total=5, 我们指向下一个节点
//index=0 , 默认 total=5,如果 index+1
private int total = 0; //被调用的次数
private int currentIndex = 0; //当前是谁在提供服务~
@SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
} else {
Server server = null;
while(server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers(); //获得还活着的服务
List<Server> allList = lb.getAllServers();//获取所有服务
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
// int index = this.chooseRandomInt(serverCount);//生成区间随机数
// server = upList.get(index);//从活着的服务中,随机获取一个~
//-================================================================
if (total < 5) {
server = upList.get(currentIndex);
total++;
}else {
total = 0;
currentIndex++;
if (currentIndex > upList.size()) {
currentIndex = 0;
}
server = upList.get(currentIndex);//从活着的服务中,获取指定的服务来进行操作
}
//-================================================================
if (server == null) {
Thread.yield();
} else {
if (server.isAlive()) {
return server;
}
server = null;
Thread.yield();
}
}
return server;
}
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
public Server choose(Object key) {
return this.choose(this.getLoadBalancer(), key);
}
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
2.2 集成Feign
依赖:(api模块与消费者模块都需要此依赖)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
配置文件:
#开启 feign.hystrix
feign:
hystrix:
enabled: true
开启功能:
@EnableFeignClients(basePackages = {"com.zhang.springcloud"})
@ComponentScan("com.zhang.springcloud.service") //扫描接口模块定义的Feign式的service
api模块定义的service
//社区版思想,主要面向接口编程,====默认集成了Ribbon
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
@Component(value = "FeignDeptClientService")
public interface FeignDeptClientService {
@GetMapping("dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@GetMapping("dept/list")
public List<Dept> queryAll();
@PostMapping("dept/add")
public boolean addDept(String dname);
}
消费者模块~Controller层
// 因为该接口中确实没有实现类,所以可以定义为空
// private DeptClientService service = null;
@Resource(name = "FeignDeptClientService")
public FeignDeptClientService service;
//查所有
@RequestMapping("/consumer/dept/list")
public List<Dept> deptList() {
return this.service.queryAll();
}
//根据id查询
@RequestMapping("/consumer/dept/get/{id}")
public Dept getDept(@PathVariable("id") Long id) {
return this.service.queryById(id);
}
//添加
@RequestMapping("/consumer/dept/add")
public boolean addDept(String dname) {
return this.service.addDept(dname);
}
三、Hystrix(服务熔断&降级)
3.1 集成服务熔断
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
配置文件:
集成Hystrix,没有必要的配置文件
开启功能:
@EnableCircuitBreaker //添加对熔断的支持--断路器
定义备选方案:(重要:@HystrixCommand(fallbackMethod = “getDeptHystrix”))
//提供Restful服务
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "getDeptHystrix") //这个注解配置非常重要,为dashboard扫描监控自动提供数据
public Dept getDept(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) {
throw new RuntimeException("id=>" + id + ",不存在该用户,或者信息无法找到~");
}
return dept;
}
//备选方案
public Dept getDeptHystrix(@PathVariable("id") Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>" + id + ",没有对应的信息,null--@Hystrix")
.setDb_source("no this database in MySql");
}
3.2 集成服务降级
配置服务降级(客户端):
修改api模块定义的 Service:
//在负载均衡上实现 降级处理
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientFallBackFactory.class)
实现降级处理机制配置类(ServiceImpl):
//降级~ FallbackFactory:降级接口
@Component
public class DeptClientFallBackFactory implements FallbackFactory {
@Override
public FeignDeptClientService create(Throwable throwable) {
return new FeignDeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname("没有对应信息,客户端实现了降级,这个服务已经被关闭")
.setDb_source("没有数据~");
}
@Override
public List<Dept> queryAll() {
return null;//尽量不要返回null
}
@Override
public boolean addDept(String dname) {
return false;
}
};
}
}
3.3 Dashboard集成监控页面
依赖:
<!--Hystrix服务熔断、降级、监控-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--Hystrix 实现监控的依赖 dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置文件:
server:
port: 9001
spring:
application:
name: springcloud-consumer-hystrix-dashboard
#不注册也不影响使用,忽略保存信息就好
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
instance:
instance-id: springcloud-consumer-hystrix-dashboard-9001
prefer-ip-address: true #隐藏默认路径,显示IP
#这个信息展示 由spring-boot-starter-actuator包提供
info:
app.name: zhang-springcloud
company.name: blog.zhangstudy.com
service.url: http://localhost:8001/dept/get/1 #随便一个测试路径
stream.url: http://localhost:8001/actuator/hystrix.stream
hystrix.url: http://localhost:9001/hystrix
开启功能:
@EnableHystrixDashboard //开启监控(服务端也要有监控信息的依赖 spring-boot-starter-actuator)
配置熔断监控页面~自定义配置类/启动类(服务端):
//增加一个 dashBoard bean
//监控信息的方法~ servlet
// ===可以写在包里,但放在@ComponentScan扫描范围之内
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream"); //添加监控路径(定义监控的页面,在这里自己定义,然后访问该界面)
return registrationBean;
}
四、Zull (路由网关)
依赖:
<!--zull 需要eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
配置文件:
server:
port: 9527
spring:
application:
name: springcloud-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
instance:
instance-id: zuul9527
prefer-ip-address: true #隐藏默认路径,显示IP
info:
app.name: zhang-springcloud
company.name: blog.zhangstudy.com
zuul:
routes:
mydept.serviceId: springcloud-provider-dept #原路径
#必须定义 原路径,否则路由处理器不知道要覆盖什么(即无效)
mydept.path: /** #路由路径(要 覆盖 原路径 的 路由路径) 例:/zhang/**
# ignored-services: springcloud-provider-dept #不能有这个路径访问了,ignored:忽略
ignored-services: "*" #隐藏全部的路径
prefix: /zhang #设置公共的路径前缀
开启功能:
@EnableZuulProxy //开启路由
五、config (分布式配置)
5.1 分布式配置服务端
依赖:
<!--configer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!--actuator 完善监控信息,configer依赖有默认扫描 /actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--web项目,必要-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
配置文件:
server:
port: 3344
spring:
application:
name: springcloud-config-server
#连接远程仓库
cloud:
config:
server:
git:
uri: https://gitee.com/zhang_gao_he/springcloud-configer.git #https,不是ssh
search-paths: cloud/springcloud
#通过 config-server 可以连接到git,访问其中的资源以及配置~
开启功能:
@EnableConfigServer //开启 configer 配置服务
5.2分布式配置客户端
依赖:
<!--configer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!--actuator 完善监控信息,configer依赖有默认扫描 /actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--web项目,必要-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
配置文件:
application.yml
#用户级别的类加载器
spring:
application:
name: springcloud-config-client-3355
bootstrap.yml
#系统级别的类加载器(优先级高) , 因为有可能会和远程冲突
spring:
cloud:
config:
name: application #需要从 git 上读取的资源名称,不要后缀
profile: client #环境
label: master #分支位置
uri: http://localhost:3344 #客户端连接服务器
开启功能:
客户端不需要启动注解,config服务端已经拿到对应配置
本文主要信息取自:狂神说