“Spring Cloud入门指南:微服务架构的起点”(二)

“Spring Cloud入门指南:微服务架构的起点”(二)

 Nacos服务注册中心

Nacos基本介绍

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

Nacos官网: Nacos 配置中心简介, Nacos 是什么 | Nacos 官网

微服务架构思想-

新项目 Nacos 服务注册中心/分布式配置中心

动态化--Nacos2.0

1.新产品特性

将gRPC应用到Nacos中,并支持多项功能的连接管理

支持负载均衡

Jraft支持命名模块的元数据操作

支持基本连接限制。

支持健康检查

支持升级和降级

2.增强功能

异步执行一些耗时的操作。

多语言SDK

公制

完全支持注册自定义实例

用户首次订阅服务时支持单推

通过阈值支持健康保护

3.重构

命名客户端重构网络代理

重构和调整v1 openAPI

NacosServer端环境搭建

服务注册中心 如何设计

  1. 服务注册中心 web页面 管理服务注册信息内容
  2. 服务注册中心Api接口 服务注册
  3. 提供jar 能够被客户端支持 实现服务注册。

NacosServer 服务注册中心 web页面和服务注册中心Api接口

Nacos 阿里巴巴推出 java语言

Nacos 2.0 发布,性能提升 10 倍 

本节课采用Nacos2.0分享。

Nacos 下载地址:Releases · alibaba/nacos · GitHub 

进入到:nacos-server-2.0.3\nacos\bin  startup.cmd 启动即可。

访问:127.0.0.1:8848/nacos

默认账户密码:nacos/nacos

服务的注册中心不需要外网访问---

Nacos2.0 启动常见错误
  1. 默认Nacos是集群方式启动,初学者建议先改成单机版本。

修改:D:\path\cloud\nacos\bin  startup.cmd  改成:set MODE="standalone"

在双击启动: startup.cmd

手动注册服务与发现

1.实现服务注册

发送post请求:

'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=boyatop-member&ip=20.18.7.10&port=8080'

2.实现服务发现

http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=boyatop-member

详细步骤操作:Nacos 快速开始 | Nacos 官网

注意:发送请求类型是为Post类型

一直刷新观察控制台,大概要等到30s才会把实例剔除(大概15s设置不健康)

该知识点设计服务续约问题

超纲内容

如何查看源码呢?

  1. spring架构体系
  2. 通过日志分析法
NacosClient环境搭建
Maven依赖

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>2.0.0.RELEASE</version>

</parent>

<dependencies>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>***.alibaba</groupId>

        <artifactId>fastjson</artifactId>

        <version>1.2.66</version>

    </dependency>

    <dependency>

        <groupId>org.apache.http***ponents</groupId>

        <artifactId>httpclient</artifactId>

        <version>4.5.5</version>

    </dependency>

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

    <version>0.2.2.RELEASE</version>

</dependency>

</dependencies>

配置文件

server:

  port: 8080

spring:

  application:

    name: boyatop-member  #服务名称 在 注册中心展示服务名称 --

  cloud:

    nacos:

      discovery:

        server-addr: 127.0.0.1:8848

启动项目

@SpringBootApplication

public class AppMember {

    public static void main(String[] args) {

        SpringApplication.run(AppMember.class);

    }

    /**

     * 会员 8080 8081

     * 订单 8070 8071

     */

}

启动客户端项目,查看该日志  服务注册成功。

查看nacos服务器端:

Resttemplate

RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpA***essor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。接下来我们就来看看这些操作方法的使用。

底层是基于HttpClient封装的。

整合Resttemplate

@Bean

public RestTemplate restTemplate() {

    return new RestTemplate();

}

@Autowired

private RestTemplate restTemplate;

    @RequestMapping("/orderToMember")

    public String orderToMember() {

        // HttpClient 工具类 实现RPC远程调用

//        String memberUrl = "http://192.168.75.1:9091/getMember";

        /**

         * 根据服务名称 从注册中心 获取 会员的接口地址

         * 服务提供 启动多个集群

         *

         */

        List<ServiceInstance> instances = discoveryClient.getInstances("boyatop-member");

        ServiceInstance serviceInstance = instances.get(0);

        // 会员服务的ip和端口

        String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";

        ResponseEntity<String> response = restTemplate.getForEntity(memberUrl, String.class);

        return "订单服务调用会员服务:" + response.getBody();

    }

本地负载均衡算法

消费者获取到注册中心多个地址,到底应该选择那个地址呢?

负载均衡算法:轮询、随机、权重等。

public interface LoadBalance {

    /**

     * 使用负载均衡算法 实现轮询机制

     * @param serviceId

     */

    ServiceInstance getInstances(String serviceId);

}

轮询算法

轮询算法实现思路:

例如在集合中 多个接口地址

[192.168.110.1:8080,192.168.110.2:8081]

0              1

第一次访问:1%2=1

第二次访问:2%2=0

第三次访问:3%2=1

第四次访问:4%2=0

[192.168.110.1:8080,192.168.110.2:8081,192.168.110.2:8082]

  0                 1               3

第一次访问:1%3=1

第二次访问:2%3=2

第三次访问:3%3=0

第四次访问:4%3=1

第五次访问:5%3=2

第六次访问:6%3=0

@***ponent

public class RoundLoadBalance implements LoadBalance {

    @Autowired

    private DiscoveryClient discoveryClient;

    private AtomicInteger atomi***ount = new AtomicInteger(-1);

    @Override

    public ServiceInstance getInstances(String serviceId) {

        List<ServiceInstance> instances = discoveryClient.getInstances("boyatop-member");

        if (instances == null || instances.size() == 0) {

            return null;

        }

        // 轮询算法实现

        int index = atomi***ount.incrementAndGet() % instances.size();

        return instances.get(index);

    }

}

随机算法

@***ponent

public class RandomLoadBalance implements LoadBalance {

    @Autowired

    private DiscoveryClient discoveryClient;

    public ServiceInstance getInstances(String serviceId) {

        List<ServiceInstance> instances = discoveryClient.getInstances("boyatop-member");

        if (instances == null || instances.size() == 0) {

            return null;

        }

        Random r = new Random();

        int index = r.nextInt(instances.size() );

        return instances.get(index);

    }

}

故障转移算法

    @RequestMapping("/orderToMember")

    public String orderToMember() {

        // HttpClient 工具类 实现RPC远程调用

// String memberUrl = "http://192.168.75.1:9091/getMember";

        /**

         * 根据服务名称 从注册中心 获取 会员的接口地址

         * 服务提供 启动多个集群

         */

//        List<ServiceInstance> instances = discoveryClient.getInstances("boyatop-member");

//        ServiceInstance serviceInstance = instances.get(0);

//        ServiceInstance serviceInstance = roundLoadBalance.getInstances("boyatop-member");

        // 会员服务的ip和端口

        List<ServiceInstance> instances = discoveryClient.getInstances("boyatop-member");

        for (int i = 0; i < instances.size(); i++) {

            ServiceInstance serviceInstance = instances.get(i);

            String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() +

 "/" + "getMember";

            try {

                ResponseEntity<String> response = restTemplate.getForEntity(memberUrl, String.class);

                if (response == null) {

                    continue;

                }

                return "订单服务调用会员服务:" + response.getBody();

            } catch (Exception e) {

                log.error("<e:{}>", e);

            }

        }

        return "fail";

    }

轮询算法

[192.168.110.1:8080,192.168.110.1:8081]

Index=0=192.168.110.1:8080

Index=1=192.168.110.1:8081

权重算法如何 比例:

1:1

第一次访问 192.168.110.1:8080

第二次访问 192.168.110.1:8081

轮询机制 默认权重1:1

2:1

[192.168.110.1:8080,192.168.110.1:8081]

权重比例 2:1

Index=0 192.168.110.1:8080 权重=2

Index=1 192.168.110.1:8081 权重=1

2(index=0):1(index=1)

第一次访问 192.168.110.1:8080

第二次访问 192.168.110.1:8080

第三次访问 192.168.110.1:8081

第四次访问 192.168.110.1:8080

第五次访问 192.168.110.1:8080

第六次访问 192.168.110.1:8081

Index=0 192.168.110.1:8080 权重=2

Index=1 192.168.110.1:8081 权重=1

2(index=0):1(index=1)

权重的底层实现逻辑

【192.168.110.1:8080,192.168.110.1:8080

192.168.110.1:8081】

第一次访问1%3=1  ===192.168.110.1:8080

第二次访问2%3=2  ===192.168.110.1:8081

第三次访问3%3=0  ===192.168.110.1:8080

第四次访问4%3=1  ===192.168.110.1:8080

第五次访问5%3=2  ===192.168.110.1:8081

第六次访问6%3=0  ===192.168.110.1:8080

第七次访问7%3=1  ===192.168.110.1:8080

第八次访问8%3=1  ===192.168.110.1:8081

@***ponent

public class WeightLoadBalance implements LoadBalance {

    @Autowired

    private DiscoveryClient discoveryClient;

    private AtomicInteger atomicInteger = new AtomicInteger(-1);

    @Override

    public ServiceInstance getInstances(String serviceId) {

        List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);

        if (instances == null) {

            return null;

        }

        ArrayList<ServiceInstance> weightInstances = new ArrayList<>();

        instances.forEach(serviceInstance -> {

            Map<String, String> metadata = serviceInstance.getMetadata();

            Double weight = Double.parseDouble(metadata.get("nacos.weight"));

            for (int i = 0; i < weight; i++) {

                weightInstances.add(serviceInstance);

            }

        });

        int index = atomicInteger.incrementAndGet() % weightInstances.size();// ==i++

        return weightInstances.get(index);

    }

}

转载请说明出处内容投诉
CSS教程网 » “Spring Cloud入门指南:微服务架构的起点”(二)

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买