欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

eureka-使用

程序员文章站 2022-03-19 15:59:26
Eureka 注册中心,模型是 AP从Eureka 运行的服务架构来看,各个节点之间是相互注册,进行信息的交互,不存在主节点,从节点的概念,这个架构模型就决定了,eureka 的 P(分区容错性)高可用,每个节点都可以对外提供服务,节点宕机不影响服务的正常使用Register: 服务注册服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 I......

目录

创建eureka服务

查看官方文档资料

springcloud 与 springboot 版本匹配

ribbon 负载均衡

优雅停服

安全认证

服务的三种调用方式

注意

第一种:

第二种

第三种

Ribbon 负载均衡器

配置方式

1. 全局的方式,配置Ribbon 的调用策略(优先级最高)

2. 修改配置文件,指定每个服务使用不同的调用策略 

负载策略

1. 轮询策略(默认) RoundRobinRule

2. 权重轮询策略 WeightedResponseTimeRule

3.随机策略 RandomRule

4.最少并发策略 BestAvailableRule

5.重试策略 RetryRule

6.可用性敏感策略 AvailabilityFilteringRule

7.区域敏感策略 ZoneAvoidanceRule

点对点直连

@FeignClient方式调用远程服务

1. 依赖

2.服务提供者

2.1 接口类

2.2实现接口

2.3 解决,@RequestMapping 被 SpringMVC 加载问题

3.服务消费者

源码地址


Eureka 注册中心,模型是 AP

从Eureka 运行的服务架构来看,各个节点之间是相互注册,进行信息的交互,不存在主节点,从节点的概念,这个架构模型就决定了,eureka 的 P(分区容错性)

高可用,每个节点都可以对外提供服务,节点宕机不影响服务的正常使用

 

eureka-使用

eureka-使用

 

Register: 服务注册
服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。

Renew: 服务续约
Eureka Client 会每隔 30 秒发送一次心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。 默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,会注销该实例,15分钟内如果超过85%的节点都失去连接,则说明是出现了网络阻塞的情况,Server 端默认会进入保护模式,不对没有心跳的服务进行移除。

Cancel: 服务下线
Eureka Client 在程序关闭时向 Eureka Server 发送取消请求(优雅下线,手动的进行服务的关闭)。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:

DiscoveryManager.getInstance().shutdownComponent();

GetRegisty: 获取注册列表信息
Eureka Client 从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与 Eureka Client 的缓存信息不同,Eureka Client 自动处理。

如果由于某种原因导致注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息。 Eureka Server 缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka Client 和 Eureka Server 可以使用 JSON/XML 格式进行通讯。在默认情况下 Eureka Client 使用压缩 JSON 格式来获取注册列表的信息。

Remote Call: 远程调用
当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡。

 

创建eureka服务

eureka-使用

eureka-使用

eureka-使用

eureka-使用

eureka-使用

查看官方文档资料

因为 eureka 是 neflix 公司的产品,springcloud 是将框架进行了整合

eureka-使用

eureka-使用

eureka-使用

官网地址:

https://docs.spring.io/spring-cloud-netflix/docs/2.2.5.RELEASE/reference/html/

eureka-使用

 

springcloud 与 springboot 版本匹配

eureka-使用

 

ribbon 负载均衡

集中式负载均衡

eureka-使用

进程内负载均衡 (ribbon 是进程内的负载均衡 )

eureka-使用

 

优雅停服

eureka-使用

eureka-使用

eureka-使用

使用 post 请求 访问 http://localhost:8761/actuator/shutdown 接口

 

安全认证

安全认证的 依赖,只需要在 eureka 服务上进行应用,

不需要在业务服务上面引用

eureka-使用

eureka-使用

 

服务的三种调用方式

注意

需要对 Product 的业务间的传输对象,进行无参,有参的构造函数, 否则会出现 异常

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.sys.yang.pojo.Product` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (PushbackInputStream); line: 1, column: 3] (through reference chain: java.util.ArrayList[0])
 

第一种:

启动类添加  RestTemplate

eureka-使用

服务类,注入 

eureka-使用

// 方式 1 进行远程调用
    private List<Product> selectProductListByDiscoveryClint() {
        StringBuffer sb = null;

        //获取服务列表
        List<String> servideIds = discoveryClient.getServices();
        if (CollectionUtils.isEmpty(servideIds)) {
            return null;
        }

        servideIds.forEach(s -> System.out.println(s.toString()));

        //根据服务名称获取服务
        List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
        if (CollectionUtils.isEmpty(instances)) {
            return null;
        }
        ServiceInstance serviceInstance = instances.get(0);
        sb = new StringBuffer();
        sb.append("http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/product/list");

        // ResponseEntity 封装了返回数据
        ResponseEntity<List<Product>> exchange = restTemplate.exchange(
                sb.toString(),
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Product>>() {
                }
        );

        return exchange.getBody();
    }

 

第二种

直接调用  selectProductListByLoadBalancerClint() 方法

/**
     * 方式 2 通过 Ribbon 负载均衡器, 轮询的方式
     */
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    public List<Product> selectProductListByLoadBalancerClint() {
        StringBuffer stringBuffer = null;

        ServiceInstance choose = loadBalancerClient.choose("service-provider");
        if (choose == null) {
            return null;
        }
        stringBuffer = new StringBuffer();
        stringBuffer.append("http://" + choose.getHost() + ":" + choose.getPort() + "/product/list");

        System.out.println(stringBuffer.toString());

        // ResponseEntity 封装了返回数据
        ResponseEntity<List<Product>> exchange = restTemplate.exchange(
                stringBuffer.toString(),
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Product>>() {
                }
        );

        return exchange.getBody();

    }

 

第三种

开启负载均衡器

直接调用,selectProductListByBalancerAnnotation() 方法

eureka-使用

/**
     * 第三种方式
     */
    private List<Product> selectProductListByBalancerAnnotation() {
        // ResponseEntity 封装了返回数据
        ResponseEntity<List<Product>> exchange = restTemplate.exchange(
                "http://service-provider/product/list",  // 直接使用 服务名称 进行远程调用
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Product>>() {
                }
        );

        return exchange.getBody();
    }

 

Ribbon 负载均衡器

服务的调用方式,选择第二种,或者第三种

配置方式

1. 全局的方式,配置Ribbon 的调用策略(优先级最高)

    /**
     * 全局配置,通过Bean 在启动类 进行注入
     * 随机策略 RandomRule
     */
    @Bean
    public RandomRule randomRule() {
        return new RandomRule();
    }

2. 修改配置文件,指定每个服务使用不同的调用策略 

# Ribbon 负载均衡策略
service-provider: # 指定策略的服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #轮询策略(默认)
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机策略

负载策略

1. 轮询策略(默认) RoundRobinRule

和上面第二种调用方式一样

 

2. 权重轮询策略 WeightedResponseTimeRule

响应时间越长,权重越低

 

3.随机策略 RandomRule

 

4.最少并发策略 BestAvailableRule

 

5.重试策略 RetryRule

 

6.可用性敏感策略 AvailabilityFilteringRule

1.过滤 Eureka 中一直处于连接失败的 provide 服务

2.过滤高并发的 provide

 

7.区域敏感策略 ZoneAvoidanceRule

 

点对点直连

        <!-- ribbon 点对点直连 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

不将该项目注册到 Eureka ,不从 Eureka 获取服务列表 

eureka-使用

 添加 ribbon 直连地址, 关闭 Eureka

# Ribbon 负载均衡策略
service-provider: # 指定策略的服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #轮询策略(默认)
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机策略
    listOfServers: http://localhost:7071,http://localhost:7072 # 指定ribbon 直连的地址

# 关闭 eureka 使用 ribbon 点对点直连
ribbon:
  eureka:
    enabled: false # false 关闭, true 开启

 

@FeignClient方式调用远程服务

1. 依赖

<!-- 添加 EnableFeignClients 的jar包 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- mybatis plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatisplus-spring-boot-starter</artifactId>
            <version>1.0.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- json -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.44</version>
        </dependency>

        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>

2.服务提供者

2.1 接口类

/**
 * @author yangLongFei 2020-12-26-19:35
 */
@RequestMapping("/userApi")
public interface UserServiceApi {

    @GetMapping("/userAdd/{user}")
    boolean insertUser(@PathVariable("user") String user);
}

2.2实现接口

/**
 * @author yangLongFei 2020-12-26-19:37
 */
@RestController
public class UserServiceApiImpl implements UserServiceApi {

    @Autowired
    private UserServiceImpl userService;

    @Override
    public boolean insertUser(String user) {
        boolean b = userService.insertUser(JSON.parseObject(user,User.class));
        return b;
    }


}

2.3 解决,@RequestMapping 被 SpringMVC 加载问题

不添该配置类:启动的时候会报错:

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'com.sys.yang.remote.product.ProductServiceClint' method 
com.sys.yang.remote.product.ProductServiceClint#selectProductList()
to {GET /productApi/list}: There is already 'productServiceApiImpl' bean method
com.sys.yang.api.impl.ProductServiceApiImpl#selectProductList() mapped.

/**
 * 解决,@RequestMapping 被 SpringMVC 加载问题
 * @author yangLongFei 2020-12-26-17:11
 */
@Configuration
@ConditionalOnClass({Feign.class})
public class FeignConfiguration {

    @Bean
    public WebMvcRegistrations feignWebRegistrations() {
        return new WebMvcRegistrations() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new FeignRequestMappingHandlerMapping();
            }
        };
    }

    private static class FeignRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
        @Override
        protected boolean isHandler(@NonNull Class<?> beanType) {
            return super.isHandler(beanType) &&
                    !AnnotatedElementUtils.hasAnnotation(beanType, FeignClient.class);
        }
    }
}

 

3.服务消费者

将服务提供者项目打成jar包

服务消费者,将jar 包通过 pom 进行引入

直接继承,服务提供者对外提供的api接口类

使用的时候,直接使用 @Autowired 进行注入

/**
 * @author yangLongFei 2020-12-26-20:38
 */
@FeignClient(value = "${yang.provide.name}")
public interface UserServiceClint extends UserServiceApi {
}
    @Autowired
    private UserServiceClint userServiceClint;

 

源码地址

https://github.com/YANG-sty/study

 

 

本文地址:https://blog.csdn.net/yang_zzu/article/details/111665495