入门微服务spring-cloud(第一章)

15 篇文章 0 订阅



该文章的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提供了一个视图,仪表盘

在这里插入图片描述

最上面的一行就是写我们服务提供方的地址 ip:端口/hystrix.stream。 左边是监控的间隔,右边是标题,可随便填写,然后点击按钮。此时你会发现依然没有图片,除非你去访问了你监控的那个接口路径,就会有图形出现

注意:

上面说的是使用了@HystrixCommand注解的接口,可以被监控到,
但是,在消费端使用了Feign整合hystrix的方式也可以被监控到

简单点就是使用了@FeignClient(value = "服务名称",回退类.class)
这些我们上面已经使用过了,这里就不过多介绍了,一些注解和配置记得加否则会报错或者失效

这样,也会出现小刺猬和ping: 数据

也就是说两种方式的熔断都可以被监控到

集群监控(Turbine)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值