SpringCloud
SpringCloud引言
单体all in on --> 微服务模块化(代码没变化~)
Spring(IOC AOP) -- 简化开发
SpringBoot -- 自动装配 (专注于快速、方便开发单个微服务)
SpringCloud -- 解耦合 (关注全局的微服务协调治理框架,他将单体微服务整合并管理)
微服务:单体(单一)应用-->模块化拆分若干服务,每个服务围绕具体业务构建,服务之间相互协调,互相配置,独立部署
核心就是将传统的一站式应用,根据业务拆分一个个服务(独立处理,独立数据库),彻底解耦合
Spring Cloud Netflix 组件(五大神兽)
通用使用步骤:
1.导入依赖
2.编写配置文件 yml|properties
3.开启功能
4.编写配置类
一、Eureka 服务注册与发现
1、Eureka(服务注册中心)
基于Rest服务,用于定位服务
(1)Eureka自我保护机制--不推荐关闭自我保护机制
微服务不能用,eureka不会立即清理,依旧会保存该微服务的信息
默认90内未接收到微服务实例的心跳
(2)设计理念
宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例
(3)对比zookeeper
分布式数据库:Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性),三者不能同时成立
Zookeeper:C一致性+P容错性;Eureka:A可用性+P容错性
Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪
(4)代码实战
(1)配置服务注册中心 ---->> Eureka Server
a 导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
b 配置yaml
server:
port: 7001
#Eureka 配置
eureka:
instance:
hostname: eureka7001.com #Eureka服务端实例名称
client:
register-with-eureka: false #表示自己就是注册中心,不用注册自己
fetch-registry: false #表示自己就是注册中心,不用去注册中心获取其他服务的地址
service-url:
#单机配置
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#集群配置,除当前注册中心外,配置其他注册中心,共同组建集群!
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
# server:
# enable-self-preservation: false #禁用自我保护机制[不推荐]
开启服务(主启动类)
@EnableEurekaServer //服务端启动类,可以接受别人注册
(二)服务注册 ---->> Server Provider
新建module [springcloud-api] 准备实体类 Dept
查看代码
@Data
@NoArgsConstructor
@Accessors(chain = true) //链式写法
public class Dept implements Serializable {// dept 实体类 orm 类表关系映射
private Long deptno;
private String dname;
//这个数据库存在哪个数据库的字段~,微服务,一个服务对应一个微服务,同一信息可能存在不同的数据库
private String db_source;
public Dept(String dname) {
this.dname = dname;
}
/*
链式写法:
Depte dept = new Dept();
dept.setDeptNo(11);
dept.set..;
new Dept().setDeptNo(11).setDname('333').setDb_source('001');
*/
}
新建服务module [springcloud-provider-dept-8001]
a 导入pom依赖
查看代码
<!--我们需要拿到实体类,所以要配置api module-->
<dependency>
<groupId>com.nercita</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--Eureka 客户端配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</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>
<!--SpringBoot 启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--test-->
<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>
<!--jetty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!--热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springCloud的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--SpringBoot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
b 编写yaml配置
查看代码
server:
port: 8001
#mybatis配置
mybatis:
type-aliases-package: com.nercita.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
#spring配置
spring:
application:
name: springcloud-provider-dept #三个服务名称一致,实例不同
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/bcp?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: root
#Eureka配置 :服务注册到哪里
eureka:
client:
service-url:
#注册到单机服务器
# defaultZone: http://localhost:7001/eureka/
#注册到集群服务器,将服务注册到这里
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider-dept8001
#配置info 可以看到微服务备注 -- json字符串响应
info:
app.name: nercita-springcloud
company.name: nercita.com
c 完善服务请求接口和对应mybatis接口以及对应的 Mapper.xml 文件配置
查看代码
//提供Restful服务
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@Autowired
private DiscoveryClient client;
//只允许post方式提交,默认浏览器请求属于get请求
@PostMapping("/deptAdd")
public boolean addDept(Dept dept){
return deptService.addDept(dept);
}
@GetMapping("/deptGetById/{id}")
public Dept queryById(@PathVariable("id") Long id){
Dept dept = deptService.queryDeptById(id);
if(dept == null){
throw new RuntimeException("id=>"+id+",不存在该用户或信息无法找到");
}
return dept;
}
@GetMapping("/deptGetAll")
public List<Dept> queryAll(){
return deptService.queryAll();
}
//注册进来的微服务,获取一些消息 -- 联合开发
@GetMapping("/deptDiscovery")
public Object discovery(){
List<String> services = client.getServices();
System.out.println("discover=>service:"+services);
//得到具体一个微服务信息 -- applicationName
List<ServiceInstance> instances = client.getInstances("springcloud-provider-dept");
for (ServiceInstance instance : instances) {
System.out.println(
instance.getHost()+"\t"+ //springcloud-provider-dept8001
instance.getInstanceId()+"\t"+ //springcloud-provider-dept8001
instance.getUri()+"\t"+ //http://windows10.microdone.cn:8001
instance.getServiceId() //SPRINGCLOUD-PROVIDER-DEPT
);
}
return this.client;
}
}
(三)服务消费 ---->> Service Consumer
新建module [springcloud-consumer-dept-80]
a 导入依赖
<!--消费者不需要连接数据库,需要实体类+web-->
<dependencies>
<dependency>
<groupId>com.nercita</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--1.导入ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--1.导入Eureka依赖 客户端配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
</dependencies>
b 编写yaml配置
server:
port: 80
#Eureka配置
eureka:
client:
#不向eureka中注册自己
register-with-eureka: false
service-url:
#集群注册服务,从这里取服务
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
c 开启功能(主启动类)
@EnableEurekaClient //3.开启服务
d 编写请求Controller(通过ip:port请求注册中心的服务)
查看代码
//消费者不应该有service
@Controller
public class DeptConsumerController {
/*
springboot支持:restful -- RestTemplate ..供我们直接调用就可以了!注册到Spring中
三个参数: url,实体 map,responseType
restTemplate :提供多种便捷访问远程http服务的方法,简单的RestFul服务模板(spring提供)
*/
@Autowired
private RestTemplate restTemplate;
/*
注意:使用ribbon负载均衡是,访问的ip地址应该是一个变量,通过服务名来访问serviceId
*/
private static final String REST_URL_PREFIX="http://localhost:8001";
// private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT";
@RequestMapping("/consumergetDeptById/{id}")
@ResponseBody
public Dept getDept(@PathVariable("id") Long id){
return restTemplate.getForObject(REST_URL_PREFIX+"/deptGetById/"+id,Dept.class);
}
@RequestMapping("/consumergetAllDept")
@ResponseBody
public List<Dept> getAllDept(){
return restTemplate.getForObject(REST_URL_PREFIX+"/deptGetAll",List.class);
}
@RequestMapping("/consumerAddDept")
@ResponseBody
public boolean addDept(Dept dept){
return restTemplate.postForObject(REST_URL_PREFIX+"/deptAdd",dept,Boolean.class);
}
}
二、Ribbon|Feign 负载均衡 (基于客户端配置)
目的:将用户请求平摊分配多个服务上,达到系统的高可用
1、请求url
ribbon负载均衡:访问的ip地址应该是一个变量,通过服务名来访问serviceId 【服务名代替ip+端口号】
客户端可以直接调用,不用关心ip地址和端口号:即localhost:80/consumergetDeptById/1
即yml配置文件:
spring:
application:
name: springcloud-provider-dept #三个服务名称一致,实例不同
代码配置: private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT"
客户端可以直接调用,不用关心ip地址和端口号
2、负载均衡策略
(1)调用负载均衡策略
IRule
AbstractLoadBalancerRule
RetryRule 重试
RandomRule 随机
RoundRobinRule 轮询 (默认)
WeightedResponseTimeRule 权重
ClientConfigEnabledRoundRobinRule
PredicateBasedRule
AvailabilityFilteringRule 过滤掉故障的服务,对剩下的进行轮询
(2)自定义负载均衡策略
自定义规则
@Configuration
public class MyRule extends AbstractLoadBalancerRule {
private int total=0;//被调用次数
private int currentIndex=0;//当前服务位置
public MyRule() {
}
/*
每个服务访问5次换下一个服务
默认total=0,total=5指向下一个服务节点
默认index=0,total=5 index++;
*/
// @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 = (Server)upList.get(index);//从或者的服务中随机获取一个
//自定义算法
if(total<5){
server = (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) {
}
}
a 依赖导入
<!--1.导入ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
b JavaConfig 注册bean
实现方式一
@Configuration // @Configuration -- spring applicationContext.xml
public class ConfigBean {
/*
IRule
AbstractLoadBalancerRule
RetryRule 重试
RandomRule 随机
RoundRobinRule 轮询 (默认)
WeightedResponseTimeRule 权重
ClientConfigEnabledRoundRobinRule
PredicateBasedRule
AvailabilityFilteringRule 过滤掉故障的服务,对剩下的进行轮询
*/
@Bean
//配置负载均衡 实现RestTemplate
@LoadBalanced //Ribbon
//springboot支持:restful -- RestTemplate ..供我们直接调用就可以了!注册到Spring中
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
//切换负载均衡策略,这个与自定义的配置文件MyRuleConfig只能开启一个
@Bean
public IRule RandomRule(){ //名字可以自定义
return new MyRule();//自定义实现,或者换成其他自带负载均衡策略
}
}
b2 开启服务来注册bean
主启动类:
@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRuleConfig.class)
javaConfig注册bean:
@Configuration
public class MyRuleConfig {
@Bean
public IRule myRule(){
return new MyRule();
}
}
3、区别对比Nginx
(1)Nginx是常见负载均衡软件;Ribbon是客户端负载均衡工具
(2)Nginx是集中式负载均衡LB;Ribbon是进程式负载均衡LB,负载均衡逻辑集成到消费方,消费方从服务注册中心获知哪些地址可用,从中选取负载均衡合适服务器
4、区别对比Feign
Feign 是在 Ribbon 的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建 http 请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写客户端变得非常容易。
Ribbon 是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。它可以 在客户端 配置 RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟 http 请求,
(1)启动类使用的注解不同,Ribbon 用的是@RibbonClient,Feign 用的是@EnableFeignClients。
(2)服务的指定位置不同,Ribbon 是在@RibbonClient 注解上声明规则类,Feign 则是在定义抽象方法的接口中使用@FeignClient 声明。
#主启动类上添加注解
@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRuleConfig.class)
#业务层接口上添加注解
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
(3)调用方式不同,Ribbon 需要自己构建 http 请求,模拟 http 请求然后使用 RestTemplate 发送给其他服务,步骤相当繁琐。Feign把RestTemplate封装起来,加了一层效率变低,可读性提高。
5、Feign代码
(1)导入依赖
<!--1.导入feign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
(2)配置yml
server:
port: 80
#Eureka配置
eureka:
client:
#不向eureka中注册自己
register-with-eureka: false
service-url:
#集群注册服务
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
#开启服务降级feign.hystrix
feign:
hystrix:
enabled: true
(3)开启服务(主启动类)
@EnableFeignClients(basePackages = {"com.nercita.springcloud"})
(4)配置业务接口
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@PostMapping("/deptAdd")
public boolean addDept(Dept dept);
@GetMapping("/deptGetById/{id}")
public Dept queryDeptById(@PathVariable("id") Long id);
@GetMapping("/deptGetAll")
public List<Dept> queryAll();
}
(5)controller请求并调用service方法
三、Hystrix 熔断、降级、流监控
1、分布式系统面临的问题(1)及解决方案(2)(3)
服务熔断和服务降级就可以视为解决服务雪崩的手段之一
(1)服务雪崩
原因:多个微服务之间调用的时候,假设A调用B和C,BC调用其他(这一条调用链叫扇出)。 如果扇出链路行某个微服务调用响应时间过长或不可用,为微服务A的调用就会扎不会有越来越多的系统资源,引起系统崩溃。
解决方案:限流,限制并发的请求访问量,超过阈值则拒绝或等待;
(2)服务熔断 Hystrix(回调方法)
服务端操作:对应雪崩效应的一种微服务链路保护机制(相当于捕获异常)
熔断目的:依赖的下游服务故障触发熔断,避免引发本系统崩溃;系统自动执行和恢复
a 导入依赖
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
b 开启熔断服务 (主启动类)
@EnableCircuitBreaker //3.开启对熔断的支持
c 请求添加回调方法
@HystrixCommand(fallbackMethod = "hystrixQueryById") //失败后常识调用
//提供Restful服务
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@HystrixCommand(fallbackMethod = "hystrixQueryById") //失败后常识调用
@GetMapping("/deptGetById/{id}")
public Dept queryById(@PathVariable("id") Long id){
Dept dept = deptService.queryDeptById(id);
if(dept == null){
throw new RuntimeException("id=>"+id+",不存在该用户或信息无法找到");
}
return dept;
}
//备选方法
public Dept hystrixQueryById(@PathVariable("id") Long id){
return new Dept()
.setDeptno(id)
.setDname("id=>"+id+"没有对应的信息,null--@Hystrix")
.setDb_source("no this database in mysql");
}
}
//滑动窗口的大小,默认为20
circuitBreaker.requestVolumeThreshold
//过多长时间,熔断器再次检测是否开启,默认为5000,即5s钟
circuitBreaker.sleepWindowInMilliseconds
//错误率,默认50%
circuitBreaker.errorThresholdPercentage
5s内,每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。
这些属于框架层级的实现,我们只要实现对应接口就好!
(3)服务降级(回调类)
客户端操作:从整体网站请求负载考虑,当某个服务熔断或关闭之后,服务将不再被调用。客户端可以准备一个自己的失败回调函数FallbackFactory,返回一个默认的缺省值。(相当于404时,返回一个自定义页面)
降级目的:服务分优先级,牺牲非核心服务(不可用),保证核心服务稳定;从整体负荷考虑;
#开启服务降级feign.hystrix
feign:
hystrix:
enabled: true
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
注意事项:
1、回调函数要继承FallbackFactory类,可以来自于其他组件
2、接口要保持一致
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
定义与其他组件的接口
/*
这里要与consumer-dept-feign接口保持一致
*/
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@PostMapping("/deptAdd")
public boolean addDept(Dept dept);
@GetMapping("/deptGetById/{id}")
public Dept queryDeptById(@PathVariable("id") Long id);
@GetMapping("/deptGetAll")
public List<Dept> queryAll();
}
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
客户端的接口
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@PostMapping("/deptAdd")
public boolean addDept(Dept dept);
@GetMapping("/deptGetById/{id}")
public Dept queryDeptById(@PathVariable("id") Long id);
@GetMapping("/deptGetAll")
public List<Dept> queryAll();
}
@Component
定义在其他组件的回调函数方法
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService(){
@Override
public boolean addDept(Dept dept) {
return false;
}
@Override
public Dept queryDeptById(Long id) {
return new Dept().setDeptno(id)
.setDname("id=>>"+id+",没有对应信息,客户端提供降级的信息,这个服务已经关闭")
.setDb_source("没有数据");
}
@Override
public List<Dept> queryAll() {
return null;
}
};
}
}
总结:
a 熔断必会触发降级,所以熔断也是降级一种。区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理。
2、流监控 hystrix.dashboard
(1)新建module[springcloud-consumer-dashboard]
(2)导入pom依赖
查看代码
<!--消费者不需要连接数据库,需要实体类+web-->
<dependencies>
<!--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>
<dependency>
<groupId>com.nercita</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--1.导入ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--1.导入Eureka依赖 客户端配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
</dependencies>
服务端项目配置pom依赖
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
(3)配置yml端口号
server:
port: 9001
(4)开启服务(主启动类)
@EnableHystrixDashboard //3.开启服务
服务端项目主启动类配置,注册ServletRegistrationBean对象
@SpringBootApplication
@EnableEurekaClient //3.开启功能:启动Eureka客户端服务
@EnableDiscoveryClient //3.开启服务发现
@EnableCircuitBreaker //3.开启对熔断的支持
public class DeptProvider_hystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_hystrix_8001.class,args);
}
//增加一个servlet
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
(5)访问:localhost:9001/hystrix
四、Zuul 路由网关 9527
,
1、什么是Zuul?
目的:隐藏真实地址
(1)提供代理、路由、过滤三大功能
路由:负责将外部请求转发到uti的微服务实例上,是实现外部访问统一入口的基础。
过滤:负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。
(2)从注册中发现服务
Zuul和Eureka整合后,自身也注册为Eureka服务治理下的应用,同时从Eureka中获取其他微服务的消息。
即:微服务的访问都是通过Zuul跳转后获得。
2、代码实现
(1)导入pom依赖
<!--zuul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
(2)配置yml文件
spring:
application:
name: springcloud-zuul
zuul:
routes:
mydept.serviceId: springcloud-provider-dept
mydept.path: /mydept/** #未实现
# ignored-services: springcloud-provider-dept #不能访问的路径
# prefix: /sc #配置统一前置
(3)开启服务(主启动类)
@EnableZuulProxy
五、Config 分布式配置
1、git基础使用
(1)下载、使用
个人git主页:gitee.com
下载:git bash here
快捷键:
ctrl+ins 复制
shift+ins 粘贴
(2)配置权限
生成秘钥:ssh-keygen -t rsa -C "1289775791@qq.com"
复制:用户/administrator/.ssh/id_rsa.pub,复制到git公钥
(3)提交上传
常用的提交命令:
git add . 把当前修改的全部提交到暂存区
git status
git commit -m "first commit" #提交本地
git push origin master #需配置个人公钥,提交git
2、代码项目配置
(1)新建Module【springcloud-config-server3344、springcloud-config-client3355、springcloud-config-eureka7001】
(2)分别导入pom依赖
springcloud-config-server3344
<dependencies>
<!--springcloud-config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
springcloud-config-client3355
<dependencies>
<!--springcloud-config-client starter-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
springcloud-config-eureka7001
<dependencies>
<!--springcloud-config-client starter-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<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>
(3)分别配置yml
springcloud-config-server3344
server:
port: 3344
spring:
application:
name: springcloud-config-server
#连接远程仓库
cloud:
config:
server:
git:
uri: https://gitee.com/zzldbl/springcloud-config.git #是http不是git
springcloud-config-client3355
#用户级别的配置 -->配置名字
spring:
application:
name: springcloud-config-client-3355
bootstarp
#系统级别的配置 -->配置读谁
spring:
cloud:
config:
uri: http://localhost:3344
name: config-client #需要从git上读取的资源名称,不需要后缀
profile: test
label: master
springcloud-config-eureka7001
#用户级别的配置 -->配置名字
spring:
application:
name: springcloud-config-eureka-7001
bootstarp
#系统级别的配置 -->配置读谁
spring:
cloud:
config:
name: config-eureka #需要从git上读取的资源名称,不需要后缀
uri: http://localhost:3344 #指向服务器
profile: dev #环境
label: master
(4)开启eureka和service服务,并启动客户端(均为主启动类)
springcloud-config-server3344
@EnableConfigServer
springcloud-config-client3355
springcloud-config-eureka7001
@EnableEurekaServer //服务端启动类,可以接受别人注册
(5)获取git上配置文件的内容并输出
@RestController
public class ConfigClientController {
/*
客户端通过服务器获取git服务器的 config-client.yml 配置
客户端可以选择环境 bootstrap.yml --> profiles:dev/test
*/
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defaultZone}")
private String eurekaService;
@Value("${server.port}")
private String port;
@RequestMapping("/config")
public String getConfig(){
String str = "applicationName:"+applicationName+",eurekaServer:"+eurekaService+",port:"+port;
return str;
}
}