eureka 服务注册发现demo

搭建服务提供方集群

将服务注册至eureka集群中,文中用到了http://euk1.com,是本地服务,需要修改hosts文件

127.0.0.1 euk1.com
127.0.0.1 euk2.com

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

在这里插入图片描述

配置文件

  • application.properties

    spring.profiles.active=provider1
    
    spring.application.name=provider
    
    eureka.client.service-url.defaultZone=http://euk1.com:7001/eureka/
    
    #自定义节点信息,可以根据节点信息来判断服务器,做个性化需求
    eureka.instance.metadata-map.info=provider
    
    #Actuator 开启哪些端点,为* 表示端点全部开启
    management.endpoints.web.exposure.include=*
    
    #Actuator 可以远程关闭服务节点,方便运维人员
    management.endpoint.shutdown.enabled=true
    
    # 每隔这个时间会主动心跳一次,默认值为30s,更新自己的状态。Eureka Server收到心跳后,会通知集群里的其它Eureka Server更新此实例的状态。
    eureka.instance.lease-renewal-interval-in-seconds = 5
    
    #服务剔除需要在Eureka Server端把自我保护关闭掉,注意是Server端关闭,不是client端
    #erueka.server.enable-self-preservation=false
    #设置服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除
    eureka.instance.lease-expiration-duration-in-seconds = 10
    
    #可以上报服务的真实健康状态
    eureka.client.healthcheck.enabled=true
    
    
  • application-provider1.properties

    server.port=81
    
  • application-provider2.properties

    server.port=82
    

MainController

随意写两个方法来测试服务是否注册成功

package com.ls.eureka.eurekaprovider;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.Map;

@RestController
public class MainController {
    @Value("${server.port}")
    String port;

    @GetMapping("/getHi")
    public String getHi() {

        return "Hi!,我的port:" + port;
    }

}

启动项目

使用 http://localhost:81/getHi,http://localhost:82/getHi能正常访问服务。
访问 eureka服务端 http://localhost:7001/ 或者 http://localhost:7002/ ,provider项目作为服务提供方已经注册在eureka了
在这里插入图片描述

Rest服务调用

可以使用Rest API 去获取注册在eureka的服务(https://github.com/Netflix/eureka/wiki/Eureka-REST-operations

注册到eureka的服务信息查看

http://localhost:7001/eureka/apps

get: {ip:port}/eureka/apps

在这里插入图片描述

注册到eureka的具体的服务查看

http://localhost:7002/eureka/apps/PROVIDER/WIN-2BA4UGIGEK3:provider:81

get: {ip:port}/eureka/apps/{appname}/{id}

在这里插入图片描述

服务续约 put:{ip:port}/eureka/apps/{appname}/{id}?lastDirtyTimestamp={}&status=up
更改服务状态 put:{ip:port}/eureka/apps/{appname}/{id}/status?lastDirtyTimestamp={}&value={UP/DOWN}
删除状态更新 delete:{ip:port}/eureka/apps/{appname}/{id}/status?lastDirtyTimestamp={}&value={UP/DOWN}
删除服务 delete: {ip:port}/eureka/apps/{appname}/{id}

Spring Boot Actuator:健康检查、审计、统计和监控

SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、环境变量、日志信息、线程信息等(这有一篇介绍文章spring boot actuator监控详细介绍一(超级详细)

由于server和client通过心跳保持 服务状态,而只有状态为UP的服务才能被访问。看eureka界面中的status。http://localhost:7001/eureka/status

比如心跳一直正常,服务一直UP,但是此服务DB连不上了,无法正常提供服务。
此时,我们需要将微服务的健康状态提交到server端。需要启动eureka的健康检查,这样微服务就会将自己的健康状态同步到server端。

开启手动控制

pom.xml

<!-- Spring Boot Actuator:健康检查、审计、统计和监控。用于上报节点信息 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.properties

## 可以上报服务的真实健康状态
eureka.client.healthcheck.enabled=true

#Actuator 开启哪些端点,为* 表示端点全部开启
management.endpoints.web.exposure.include=*

#Actuator 可以远程关闭服务节点,方便运维人员
management.endpoint.shutdown.enabled=true

改变健康状态的Service

@Service
public class HealthStatusService implements HealthIndicator {

    private Boolean status = true;

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

    @Override
    public Health health() {
        // TODO Auto-generated method stub
        if(status)
            return new Health.Builder().up().build();
        return new Health.Builder().down().build();
    }

    public String getStatus() {
        // TODO Auto-generated method stub
        return this.status.toString();
    }
}

测试用的Controller

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

测试修改服务状态

http://localhost:81/health?status=false

provider中看到日志

Saw local status change event StatusChangeEvent [timestamp=1605522480678, current=DOWN, previous=UP]

Eureka Server中看到日志

Registered instance PROVIDER/WIN-2BA4UGIGEK3:provider:81 with status DOWN (replication=true)

此时服务列表任然显示provider服务,不会将服务剔除,只会标注为服务下线

http://localhost:81/health?status=true 会将服务重新上线

安全配置

开启Eureka安全连接

application.properties

如果没有配置账号密码,则会再启动的时候输出一串随机密码,打印在控制台,
默认账号是user
Using generated security password: 178c5cf8-7f2a-4b38-a25b-6aed7a11c77d
开启之后,访问eureka服务就需要输入账号密码才行,且注册的时候需要将账号密码也加载链接上
如下:
eureka.client.service-url.defaultZone=http://ls:123@euk2.com:7002/eureka/

spring.security.user.name=ls
spring.security.user.password=123

pom.xml

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

关闭防止跨域攻击

spring.security带有防止跨域攻击的模块,需要手动关闭

javax.ws.rs.WebApplicationException: com.fasterxml.jackson.databind.exc.MismatchedInputException: Root name 'timestamp' does not match expected ('instance') for type [simple type, class com.netflix.appinfo.InstanceInfo]
手动关闭
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// TODO Auto-generated method stub
		http.csrf().disable();
		super.configure(http);
	}
}

在服务端增加配置类

服务使用方

从服务端获取可以使用的服务列表,进行调用

配置文件

server.port=83

spring.application.name=consumer

eureka.client.service-url.defaultZone=http://euk1.com:7001/eureka/

#自定义节点信息
eureka.instance.metadata-map.info=consumer

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

#可以上报服务的真实健康状态
#eureka.client.healthcheck.enabled=true

MainController

package com.ls.eureka;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;

@RestController
public class MainController {
    @Value("${server.port}")
    String port;

    @Autowired
    DiscoveryClient discoveryClient;

    @Autowired
    LoadBalancerClient loadBalancerClient;

    @GetMapping("/getHi")
    public String getHi() {

        return "Hi!,我的port:" + port;
    }

    /**
     * 获取服务列表
     * @return
     */
    @GetMapping("/getServices")
    public String getServices() {
        List<String> services = discoveryClient.getServices();
        return services.toString();
    }

    /**
     * 根据服务名称获取服务列表
     * @return
     */
    @GetMapping("/getInstances")
    public Object getInstances() {

        return discoveryClient.getInstances("provider");
    }

    /**
     * 根据服务名称获取服务列表,测试服务访问
     * @return
     */
    @GetMapping("/getInstancesList")
    public String getInstancesList() {
        //discoveryClient Spring cloud 的client只会返回Up状态下的实例
        List<ServiceInstance> instancesList = discoveryClient.getInstances("provider");
        System.out.println("instancesList.size:==========="+instancesList.size());
        for (ServiceInstance instance : instancesList) {
            System.out.println(instance.toString());
        }
        if(instancesList.size() > 0){
            ServiceInstance instance = instancesList.get(0);
            String url = instance.getUri().toString()+"/getHi";

            System.out.println(url);

            RestTemplate restTemplate = new RestTemplate();
            String respStr = restTemplate.getForObject(url, String.class);

            System.out.println(respStr);
            return respStr;
        }
        return "";
    }

    /**
     * 根据服务名称获取服务列表,使用Ribbon做负载均衡策略 测试服务访问
     * @return
     */
    @GetMapping("/getInstancesListByLb")
    public String getInstancesListByLb() {
        //discoveryClient Spring cloud 的client只会返回Up状态下的实例
        List<ServiceInstance> instancesList = discoveryClient.getInstances("provider");

        ServiceInstance instance = loadBalancerClient.choose("provider");
        String url = instance.getUri().toString()+"/getHi";

        System.out.println(url);

        RestTemplate restTemplate = new RestTemplate();
        String respStr = restTemplate.getForObject(url, String.class);

        System.out.println(respStr);
        return respStr;

    }
}

getInstancesListByLb

使用了Ribbon作为负载均衡,会根据负载策略将请求分发到不同的provider上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值