Eureka高可用搭建,Ribbon负载均衡,Actuator监控

 

首先我们先新建一个eureka-server的项目

这里要勾选Eureka Server这个组件

以上项目就初步创建好了,我们可以查看pom.xml文件,里面已经帮我们引入了eureka-server的相关依赖。

然后我们在项目的入口这加上一个注解@EnableEurekaServer

当然还有在properties文件里进行相关的配置,配置url之前,eureka内部有个多网卡绑定机制,所以先到C:\Windows\System32\drivers\etc\hosts文件中整两个主机名出来如下,保存好之后,手动ping一下,看是否设置成功

127.0.0.1    eureka1.com
127.0.0.1    eureka2.com

 我们需要建两个项目(两个eureka服务),一个是eureka1.com,一个是eureka2.com ,他们仅仅是properties文件不一样,下面是eureka1.com的配置文件,defaultZone是1向2注册,所以另一个项目相反就ok啦!(我都贴出来吧),这里的hostname在生产环境下配实际的ip地址就好啦。

server.port= 7001
#是否将自己注册到Eureka Server,默认为true,高可用的话我们就需要eureka直接互相注册信息,所以默认true
#eureka.client.register-with-eureka=true
#是否从Eureka Server获取注册信息,默认为true,高可用的话我们就需要eureka直接互相拉取信息,所以默认true
#eureka.client.fetch-registry=true
#设置服务注册中心的URL,用于client和server端的通信,默认是8761端口,eureka会像这里的url去注册
eureka.client.service-url.defaultZone=http://eureka2.com:7002/eureka/

#查找主机地址
eureka.instance.hostname=eureka1.com

spring.application.name=EurekaServer
server.port= 7002
#是否将自己注册到Eureka Server,默认为true,高可用的话我们就需要eureka直接互相注册信息,所以默认true
#eureka.client.register-with-eureka=true
#是否从Eureka Server获取注册信息,默认为true,高可用的话我们就需要eureka直接互相拉取信息,所以默认true
#eureka.client.fetch-registry=true
#设置服务注册中心的URL,用于client和server端的通信,默认是8761端口,eureka会像这里的url去注册
eureka.client.service-url.defaultZone=http://eureka1.com:7001/eureka/

#查找主机地址
eureka.instance.hostname=eureka2.com

spring.application.name=EurekaServer

然后这个项目就可以成功跑起来了,我们设置tomcat端口号为7001和7002,所以我们可以到这http://eureka1.com:7001/http://eureka2.com:7002/查看eureka的监控后台

到这就说明EurekaServer集群已经搭起来啦!!!接下来要搞个客户端

还是新建一个项目eurekaProvider,然后引入依赖,这里是引入eureka client!!!


在项目入口这加上@EnableEurekaClient,新版本是不需要加这个注解的

 项目建好后还是去修改properties文件

server.port=80

spring.application.name=provider

#这里的地址是provider去寻找服务的地址和端口
eureka.client.service-url.defaultZone=http://eureka1.com:7001/eureka/

然后我们写个测试服务的controller。

@RestController
public class testController {

    @GetMapping("/HelloWorld")
    public String HelloWorld(){
        return "HelloWorld-Provider";
    }

}

我的provider跑起来后就会把自己注册到eureka1.com中

接下来再新建一个eurekaClient作为consumer和provider一样,这样我们就相当于有两个微服务,然后都注册到eureka1.

那我们两个微服务怎么调用呢,我们就可以注入DiscoveryClient接口,从这个接口可以获取到eureka内的信息,这个接口如下,就几个方法,可以从getInstances中获取到某个服务,getServices()可以获取注册到eurekaServer的服务列表

public interface DiscoveryClient extends Ordered {
    int DEFAULT_ORDER = 0;

    String description();

    List<ServiceInstance> getInstances(String serviceId);

    List<String> getServices();

    default void probe() {
        this.getServices();
    }

    default int getOrder() {
        return 0;
    }
}
@RestController
public class testController {

    @Autowired
    DiscoveryClient discoveryClient;

    EurekaClient eurekaClient;

    @GetMapping("/getServices")
    public String getClient(){
        List<String> services =  discoveryClient.getServices();
        for (String server: services){
            System.out.println(server);
        }
        return "";
    }

}

当我们调用/getServices,打印了这两个服务

然后调用/ServiceInstance,根据getServices返回的serviceId,作为参数,

这里我们就获得了provider的相关信息,这样就可以对provider进行远程调用

以上就是通过eureka服务器来拉去其他微服务的相关ip地址和端口号还有服务的状态。

然后我们就可以通过ip地址和端口号拼接来对provider进行远程调用。

    @GetMapping("/ServiceInstance")
    public String getServiceInstance(){
        List<InstanceInfo> services =  eurekaClient.getInstancesByVipAddress("provider",false);
        if(services.size() > 0){
            InstanceInfo instanceInfo = services.get(0);
            //判断服务状态是否正常,不行是down
            if(instanceInfo.getStatus() == InstanceInfo.InstanceStatus.UP){
                //这里拼接好请求,调用provider的/HelloWorld
                String url = "http://"+instanceInfo.getHostName()+":"+instanceInfo.getPort()+"/HelloWorld";
                //用restTemplate去发起请求
                RestTemplate restTemplate =  new RestTemplate();
                String respon = restTemplate.getForObject(url, String.class);
                return respon;
            }
        }
        return "false";
    }

最后正确的返回了"HelloWorld-Provider",这就成功的使微服务直接能互相调用

Ribbon负载均衡

我们可以才需要调用其他微服务时,注入LoadBalancerClient对象,这是一个抽象接口,它可以自动的帮我们完成负载均衡并且过滤掉状态为down的服务

@Autowired
LoadBalancerClient loadBalancerClient;

@GetMapping("/LoadBalancedServiceInstance")
    public String getLoadBalancedServiceInstance(){

        //ribbon可以完成客户端的负载均衡,并且过滤掉down状态的服务
        ServiceInstance serviceInstance = loadBalancerClient.choose("provider");

        String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/HelloWorld";

        RestTemplate restTemplate =  new RestTemplate();

        String respon = restTemplate.getForObject(url, String.class);

        return respon;
    }

看下图就调用成功啦,代码实现也简单了很多。

eureka自我保护机制

eureka在高可用的特性下,会遇到某些节点暂时失效,所以它就有一个自我保护机制来保证宁愿保留健康和不健康的服务,也不会盲目注销任何健康的服务,所以客户端每分钟发送心跳的数量小于客户端总数的85%时就会触发自我保护机制(默认30秒发送一次心跳)。这样做是使eureka的可用性更加强,但是一致性是无法保证的。但是如果我们的服务确实出问题了,eurekaServer因为开启了自我保护机制,也不会去把有问题的服务剔除,eurekaServer是无法知道每个微服务是否可用的,它不会主动去发心跳询问客户端,检测客户端是否可用。那所以我们如果想要在微服务中catch到错误后,主动把这个服务down掉,那么我们可以用Actuator监控每一个微服务。

Actuator监控

首先我们需要引入Actuator的依赖用来上报服务的信息

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

这里就说明引入成功啦!

里面_links下面目前只有health节点相关内容,如果想要增加所有的相关信息节点,我们就需要在properties里配置加上,然后信息就好多了很多了吧。感兴趣的可以再去查一查每一个信息节点相关内容。

management.endpoints.web.exposure.include=*

里面有一个特殊的节点shutdown,默认是没开的要单独配置一下,这样就会多了shutdown的信息节点,只要发post请求这个节点里的url,就可以远程关闭这个微服务。

#可以远程关闭微服务
management.endpoint.shutdown.enabled=true

配好之后,我们就可以实现自定义上下线服务了,什么意思呢?就是eureka服务一直觉得某个微服务是可以调通的,所以状态为up,但是实际上,这个微服务已经不能用了,需要人为的去catch某些异常,然后人为主动地去上传微服务的真是状态。

我们先配置客户端的配置,将服务自己的健康状态传播到server

#可以上班服务的真是状态
eureka.client.healthcheck.enabled=true

我们写个service,实现HealthIndicator接口

@Service
public class HealthStatusService implements HealthIndicator {

    //当前服务状态
    private  Boolean status = true;

    public void setStatus(Boolean status) {
        this.status = status;
    }

    public String getStatus() {
        return status.toString();
    }

    @Override
    public Health health() {
        //当状态为true,上报状态up
        if (status){
            return new Health.Builder().up().build();
        }
        //当状态为false,上报状态up
        return new Health.Builder().down().build();
    }
}

 我们只有调下面这个接口,并传入状态,这样就可以手动上下线我们的服务啦!!!

@Autowired
HealthStatusService healthStatusService
 
@GetMapping("/health")
    public String health(@RequestParam("status") Boolean status){
        healthStatusService.setStatus(status);
        return healthStatusService.getStatus();
    }

 这样就可以穿不同参数的时候,让服务上下线了啊!!!

以上是spring-cloud相关的基础组件,有什么错误希望大佬们给我指点一下,谢谢

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值