springcloud
该文章的springboot版本是1.5.9.RELEASE,
springcloud版本是1.3.1.RELEASE
服务调用
不使用注册中心的调用方式
首先新建两个boot项目,一个做服务提供方,一个做服务的消费方,
服务提供端:
@GetMapping("/getAll")
@ResponseBody
public List<User> ByUserAll(){
return iUserService.ByUserAll();
}
@RequestMapping(value = "getId/{id}",method = RequestMethod.GET)
@ResponseBody
public User ByUserId(@PathVariable(name = "id") int id){
return iUserService.ByUserId(id);
}
服务消费端
@Configuration
public class Config{ //为客户端提供的一个更高包装的rest模板
@Bean
@Primary //注意,必须使用该注解,不然报找不到服务
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
消费调用提供方服务:
@Autowired
private RestTemplate restTemplate; #注入模板
private final static String PROVIDE_HTTP="http://localhost:8001";
@RequestMapping("/user/{id}")
public User getUser(@PathVariable(name = "id")int id){
return restTemplate.getForObject(PROVIDE_HTTP+"/admin/getId/"+id,User.class);
}
@RequestMapping("/users")
public List<User> getUserAll(){
return restTemplate.getForObject(PROVIDE_HTTP+"/admin/getAll",List.class);
}
这是一种普通的服务调用,不通过注册中心
其中user在公共模块,引入就可以了,
使用注册中心 eureka
主要负责实现微服务架构中的服务治理功能,是一个基于 REST 的服务。 eureka 包含两个组件, eureka Server和 eureka Client。服务节点的信息可以在界面中直观的看到。 eureka client 是一个java客户端,用于简化eureka server的交互。客户端同时也具备一个内置,使用轮询(roubd-robin)负载算法的负载均衡器,在启动后,会向eureka server发送心跳(默认周期30秒),如果eureks server在多个心跳周期内没有接收到某个节点的心跳,eureka server将会从服务注册表中把该服务移除(默认90秒)。----- Eureka的自我保护机制:当注册进Eureka的微服务,在规定的时间内,没有被访问,Eureka不会删除该微服务实例,而是会保存,也就是进入了自我保护 当该微服务重新获得心跳,eureka接收到了心跳,则会退出自我保护新建一个boot服务,作为eureka的服务端
<!--eureka-server服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
注意:坐标依赖带了一个server
在boot的启动类上加上注解:
@EnableEurekaServer //设置为Eureka的服务端
配置yml文件
----------------------------------------
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称 ,这里的是配置的一个本地的域名ip映射
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#单机
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
# defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #这是配置集群,使用逗号隔开
修改消息提供方
添加依赖:
<!-- 将微服务provider侧注册进eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
yml文件添加eureka配置
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://localhost:7001/eureka/ #Eureka的地址
注意,这里的localhost可以是eureka7001.com,因为上面的eureka配置了域名,所以也可以用
spring:
application:
name: microservicecloud-dept #对外暴露的微服务名称
启动类加上注解:@EnableEurekaClient //设置为Eureka的客户端
eureka启动以后,再把服务提供方启动,此时,我们访问eureka的服务 则可有发现,有注册了的服务,就是服务提供方
此时后面的蓝色一串是可以点击的,但是如果不做配置的,那么点击的话,有可能会报错,所以我们可以去做一些配置
如服务提供方:
添加依赖
<!-- actuator监控信息完善 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后在yml文件中加入配置信息:
info:
app.name: microservicecloud-dept
company.name: com.sz
build.artifactId: $project.artifactId$
build.version: $project.version$
这是属于自身服务描述,自定义
此时再点击就不会报错了
此时服务提供方已经改好了,eureka也配好了,但是服务消费方依然无法通过eureka来调用服务,但是如果是不通过eureka调用依然是可以的。 现在我们来配置一下通过eureka来访问微服务 首先新建springboot工程
除了一些基本的spring,web依赖这里就不说了
添加一些其他的依赖
-----------------------------
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
yml文件
------------------
eureka:
client:
register-with-eureka: false //不注册到eureka上
service-url:
defaultZone: http://localhost:7001/eureka/ #eureka的地址
然后在公共模块添加一个接口,之前的user类也在这里
然后提供一个方法:注意,该方法和服务提供方的方法要一样,路径要一样,且参数也要一样,返回值一样,方法名不要求
@GetMapping("/admin/getAll")
@ResponseBody
public List<User> ByUserAll();
然后在接口上加上注解来定义客户端:
@FeignClient(value = "microservicecloud-dept")
value是我们需要访问的服务提供者对外暴露的名称,也就是在eureka上的服务名称
-----------------------------------
我们还可以提取一个路径出来,如:
@FeignClient(value = "microservicecloud-dept",path = "/admin")
方法上的路径就去掉一个/admin
这样子也是可以的
最后,就是需要在我们的服务消费方的启动类上加上@EnableFeignClients(basePackages =“指向客户端所在的包名”)注解表示启用feign客户端
现在看起来已经写的差不多了,可以使用了,但是很遗憾,依然不能用,不出意外的话依然是报500,但是如果是通过RestTemplate的方式直接通过ip来调用的话那就另说了, 现在还需要做的是:虽然服务提供方已经注册到了eureka上,但是他依然不能被其他的消费端通过eureka来发现服务,还需要一个注解加到服务提供方·的启动类上 ---@EnableDiscoveryClient 服务发现 此时启动注册中心,服务端,消费端就可以使用了。 注意:消费端现在是去调我们刚创建的接口里的方法,接口就通过依赖注入的方式来获取就可以了
使用注册中心,并且使用RestTemplate调用服务
其实和不使用eureka的方式很像 新建一个boot工程
坐标
-----------------------
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
yml
-----------------------
eureka:
client:
register-with-eureka: false #禁止自己注册服务,虽然是Eureka的客户端,但是不可见,默认为true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
启动类
-----------------------
加上注解@EnableEurekaClient
直接写接口
-----------------------
private final static String PROVIDE_HTTP="http://microservicecloud-dept";
//此时是通过注册在服务注册中心的微服务提供方的微服务名称访问,不需要带端口号
//注意该microservicecloud-dept是服务提供方在eureka上暴露的服务名称
@Autowired
private RestTemplate restTemplate; //注入模板
定义接口
@RequestMapping("/user/{id}")
public User getUser(@PathVariable(name = "id")int id){
return restTemplate.getForObject(PROVIDE_HTTP+"/admin/getId/"+id,User.class);
}
@RequestMapping("/users")
public List<User> getUserAll(){
return restTemplate.getForObject(PROVIDE_HTTP+"/admin/getAll",List.class);
}
注意:restTemplate 需要加上注解@LoadBalanced 否则会报找不到服务
则这样就可以调用成功了,
eureka和服务提供者不需要做什么改变
负载均衡
Ribbon 是基于Netflix Ribbon实现的一套客户端的负载均衡工具。提供了一系列完善的配置项如连接超时,重试等,就是在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则,如简单轮询,随机连接去。 之前我们的Resttemplate是没有负载均衡的能力首先在创建RestTemplate的类上添加一个注解@LoadBalanced
使之有负载均衡的能力
@Configuration
public class Config{ //为客户端提供的一个更高包装的rest模板
@Bean
@Primary //注意,必须使用该注解,不然报找不到服务,根据版本而定
@LoadBalanced //拥有负载均衡的能力
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
要想看到效果,就需要有两个及以上的服务提供者才能体现出来,而且他们的接口路径也要一样,最主要的就是他们对外暴露的服务名称要一致,
默认的负载均衡是以轮询的方式进行
Ribbon的轮询规则(7钟)
RoundRobinRule 轮询
RandomRule 随机
AvailabilityFilteringRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务 然后对于剩余的服务列表按照轮询策略进行访问
WeightedResponseTimeRule
根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,
刚启动是如果统计信息不足,则使用 轮询 策略,等统计信息足够时,会切换到该种策略
RetryRule
先按照 轮询 策略 获取服务,如果获取失败则在指定时间内进行重试,获取可用的服务,如果持续不能获取到该服务,则在某个下次轮询时自动跳过该服务
BastAvailableRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
ZonAvoidanceRule
默认规则,复合判断server所在区域的性能和server的可用性选择服务器
修改负载均衡策略
默认是轮询,可修改
在服务的消费端的配置类里面配置一个IRule类,需要使用什么策略,就去new一个什么样的类
@Bean
public IRule getIrule(){
return new RandomRule();
}
这里是new 了一个随机的一个类,表示按照随机的策略,需要注意的是需要写在配置类里面
自定义策略
我们查看其它的策略实现是,都会发现这些都是继承了一个抽象类AbstractLoadBalancerRule 并且发现他们的策略都写在了choose方法上
public Server choose(ILoadBalancer lb, Object key){...}
只要这里面的一段我们自己定义,就可以实现自定义的策略了,
如:我定义了
int total=0; 表示调用次数
int index=0; 表示服务的索引
它的服务是从参数获取的
List<Server> upList = lb.getReachableServers();
只要操作这个集合,我们就可以实现自己的策略,
根据自己的某种规则将去调用服务,通过uplist.get(int index)调用
然后在赋值给server
那么定义好了如何使用呢,和rubbon自带的策略一样,一样需要在配置类中将其创建出来,
但是需要注意,不能同时配置多个策略
eureka集群
为什么使用集群,在生产环境中必须搭建一个集群来保证高可用之前的单机版eureka的配置
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
这里的7001指的是直接的地址,当配置集群环境时,这里就要写上其他的注册中心的地址
如
defaultZone: http://eureka7001.com:7001/eureka/
改成
defaultZone: http://eureka7002.com:7002/eureka/
有多个注册中心则以逗号隔开
而7002的注册中心也是,他的defaultZone属性值:
defaultZone: http://eureka7001.com:7001/eureka/ #多个逗号隔开
服务提供者和服务消费者都需要改一下配置
之前的配置是defaultZone: http://localhost:7001/eureka/
如今多了个注册中心,我们需要把它加上,通逗号隔开就可以了
检测一下:
启动两个注册中心,然后启动服务提供者,然后访问7001,7002端口,看是否注册成功
Hystrix
是 Netflix 针对微服务分布式系统采用的熔断保护中间件,相当于电路中的保险丝。坐标
-----------------------------------
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
--------------------------------
启动类上加上添加@EnableHystrix注解
配置文件:
---------------------------------------
feign:
hystrix:
enabled: true 开启熔断
---------------------------
然后在请求的接口上使用该注解
@HystrixCommand(fallbackMethod = "ByUserId2s")
fallbackMethod 所指的是回退的方法
注意,该注解既可以在服务提供方的接口上出现,
也可以在服务消费方的客户端接口上出现(这里指的是调用服务提供者的接口)
当配置了改注解:
如果服务提供方没有启动服务,那么将会熔断处理,进入到ByUserId2s方法里。
如果服务消费方自己抛出异常,那么也会被熔断。
服务提供方需要熔断的话,需要抛异常,除非服务提供方还调用了其他的服务,而那个服务已经宕机了,那么就会熔断,依次类推
注意:不管是消费方还是提供方,如果要想熔断有效,都需要·在启动类上加@EnableHystrix注解
Feign整合Hystrix
上面的熔断我们发现一点问题,就是每一个方法都需要做熔断的处理的话,那么就都得配置一个方法,那么,这样的处理方式肯定是不合理的, 现在还有一种方式就是Feign整合Hystrix首先,我们上面谈及的公共模块,里面是有user类的,还有的就是我们通过feign来进行服务调用的一个接口ServiceFeign,这都是我们上面说过了的,以及有代码示范的,忘记的可以温习一下,
主要,ServiceFeign现在的方法就是一些普通的方法,只是一些做服务调用的,没有做过熔断处理,那么,接下来,该如何处理呢?
1. 首先定义一个回退类DeptClientServiceFallbackFactory,它实现了一个接口FallbackFactor<ServiceFeign> 它的泛型就是我们的客户端ServiceFeign
2. 实现了以后,有一个方法我们需要覆写,那就是
3. @Override
public ServiceFeign create(Throwable throwable) {
.....;
}
注意,该方法里面是new了一个匿名对象ServiceFeign ,
它的所有方法在这里将在这里被覆写
回到我们的ServiceFeign
客户端接口,需要做一些修改
之前的注解是
@FeignClient(value = "microservicecloud-dept",path = "/admin")
现在改为
@FeignClient(value = "microservicecloud-dept",path = "/admin",fallbackFactory = DeptClientServiceFallbackFactory.class)
也就是需要指定这个方法回退的类
最后还需要
feign:
hystrix:
enabled: true 开启熔断
这是feign整合hystrix时需要开启
Hystrix Dashboard监控(仪表盘)
新建项目 hystrix-dashboard,
坐标
------------------------
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
yml
------------------
management:
endpoints:
web:
exposure:
include: hystrix.stream
#允许显示/actuator/hystrix.stream信息
启动类
-------------------
@EnableHystrixDashboard
然后访问一下
ip:端口/hystrix.stream
就可以看到一个刺猬的头像页面了,此时监控还起不到作用。
启动一个服务提供方
然后访问一下服务提供者
访问地址:ip:端口/hystrix.stream 跟上面的一样,但是却报404
那是由于被监控的一方需要在启动类上加 @EnableHystrix 注解
此时在访问地址就不会404了,但是又有新的问题了,页面上显示的是ping:
是空的, 那是因为我们没有设置监控的方法,其实设置也很简单,我们之前也用过了,
其实就是该注解 @HystrixCommand
只要是使用了改注解的接口方法,只要被访问,ping:就会出现json字符串
该注解就是拿来做熔断处理的,记得把回退方法补上,不要漏了,这里就不展示了.
注意:上面的两个路径其实都是一样的,就是端口不一样,一个是服务监控的,她会显示一个刺猬,而被监控的服务访问改地址显示的就是一堆的ping:
然后这样的信息不太好看,因为都是json字符串,
但是Hystrix Dashboard提供了一个视图,仪表盘
注意:
上面说的是使用了@HystrixCommand注解的接口,可以被监控到,
但是,在消费端使用了Feign整合hystrix的方式也可以被监控到
简单点就是使用了@FeignClient(value = "服务名称",回退类.class)
这些我们上面已经使用过了,这里就不过多介绍了,一些注解和配置记得加否则会报错或者失效
这样,也会出现小刺猬和ping: 数据
也就是说两种方式的熔断都可以被监控到