SpringCloud从入门到精通——Nacos服务注册中心

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 SpringCloud从入门到精通——Nacos服务注册中心,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

Nacos服务注册中心

1. Nacos基本介绍

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

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

*由阿里巴巴推出,Java语言编写
Nacos官网: https://nacos.io/zh-cn/docs/what-is-nacos.html

1.1 什么是 Nacos

服务(Service)是 Nacos 世界的一等公民。Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理:
Kubernetes Service
gRPC & Dubbo RPC Service
Spring Cloud RESTful Service

Nacos 的关键特性包括:
服务发现和服务健康监测

Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDK、OpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODO 或HTTP&API查找和发现服务。

Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测2种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。

动态配置服务
动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。
动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。
配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
Nacos 提供了一个简洁易用的UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。

动态 DNS 服务
动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。
Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP:PORT 列表.

服务及其元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。

2. NacosServer端环境搭建

服务注册中心 如何设计

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

Nacos 下载地址:https://github.com/alibaba/nacos/releases

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

访问:127.0.0.1:8848/nacos
默认账户密码:nacos/nacos

2.1 Nacos2.0启动常见错误

  1. 默认Nacos是集群方式启动,初学者建议先改成单机版本。
    修改:D:\path\cloud\nacos\bin startup.cmd 改成:set MODE=“standalone”
    在双击启动: startup.cmd

3. 手动注册服务与发现

1.实现服务注册
发送post请求:
‘http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=mayikt-member&ip=20.18.7.10&port=8080’

2.实现服务发现
http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=mayikt-member

详细步骤操作:https://nacos.io/zh-cn/docs/quick-start.html

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

一直刷新观察控制台,大概要等到30s才会把实例剔除(大概15s设置不健康)
该知识点设计服务续约问题

4. NacosClient环境搭建

4.1 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>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.66</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</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>

4.2 配置文件

server:
  port: 8080
spring:
  application:
    name: demo-member  #服务名称 在 注册中心展示服务名称 --
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # nacos服务注册中心Server端 地址

4.3 接口

package com.demo.service;

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

/**
 * @Author: JYC
 * @Title: MemberService
 * @Description: TODO
 * @Date: 2022/4/21 13:57
 */
@RestController
public class MemberService {
    @Value("${server.port}")
    private String serverPort;
    /**
     * 会员服务提供接口
     * @return
     */
    @RequestMapping("/getMember")
    public String getMember() {
        return "我是会员服务接口...端口:" + serverPort;
    }
}

4.4 启动项目

package com.demo.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @Author: JYC
 * @Title: com.demo.service.AppMember
 * @Description: TODO
 * @Date: 2022/4/21 13:59
 */
@SpringBootApplication
public class AppMember {
    public static void main(String[] args) {
        SpringApplication.run(AppMember.class);
    }
}


5. NacosClient实现服务发现

5.1 Maven依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>0.2.2.RELEASE</version>
        </dependency>
    </dependencies>

5.2 配置文件

server:
  port: 8070
spring:
  application:
    name: demo-order   #服务名称 在注册中心展示服务名称
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # nacos服务注册中心Server端 地址

5.3 接口

package com.demo.service;

import com.demo.utils.HttpClientUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @Author: JYC
 * @Title: OrderToMemberService
 * @Description: TODO
 * @Date: 2022/4/21 14:04
 */
@RestController
public class OrderToMemberService {
    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 订单服务,调用 会员服务接口
     */
    @RequestMapping("/orderToMember")
    public String OrderToMember() {
        // HttpClient 工具类 实现RPC远程调用
//        String memberUrl = "http://192.168.66.1:8080/getMember";
        /**
         * 根据服务名称,从注册中心获取会员的接口地址
         */
        List<ServiceInstance> instances = discoveryClient.getInstances("demo-member");
        ServiceInstance serviceInstance = instances.get(0);
        // 会员服务的ip和端口
        String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
        return "订单服务调用会员服务:" + HttpClientUtils.doGet(memberUrl, null);
    }
}

5.4 工具类

package com.demo.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: JYC
 * @Title: OrderToMemberService
 * @Description: TODO
 * @Date: 2022/4/21 14:04
 */

public class HttpClientUtils {

    private static final CloseableHttpClient httpClient;
    public static final String CHARSET = "UTF-8";
    private static final Log log = LogFactory.getLog(HttpClientUtils.class);

    // 采用静态代码块,初始化超时时间配置,再根据配置生成默认httpClient对象
    static {
        RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
        httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
    }

    public static String doGet(String url, Map<String, String> params) {
        return doGet(url, params, CHARSET);
    }


    public static String doPost(String url, Map<String, String> params) throws IOException {
        return doPost(url, params, CHARSET);
    }

    /**
     * HTTP Get 获取内容
     *
     * @param url     请求的url地址 ?之前的地址
     * @param params  请求的参数
     * @param charset 编码格式
     * @return 页面内容
     */
    public static String doGet(String url, Map<String, String> params, String charset) {
        try {
            if (params != null && !params.isEmpty()) {
                List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    String value = entry.getValue();
                    if (value != null) {
                        pairs.add(new BasicNameValuePair(entry.getKey(), value));
                    }
                }
                // 将请求参数和url进行拼接
                url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
            }
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                httpGet.abort();
                throw new RuntimeException("HttpClient,error status code :" + statusCode);
            }
            HttpEntity entity = response.getEntity();
            String result = null;
            if (entity != null) {
                result = EntityUtils.toString(entity, "utf-8");
            }
            EntityUtils.consume(entity);
            response.close();
            return result;
        } catch (Exception e) {
            log.error("请求服务器端出错:" + e);
            return null;
        }

    }

    /**
     * HTTP Post 获取内容
     *
     * @param url     请求的url地址 ?之前的地址
     * @param params  请求的参数
     * @param charset 编码格式
     * @return 页面内容
     * @throws IOException
     */
    public static String doPost(String url, Map<String, String> params, String charset)
            throws IOException {
        List<NameValuePair> pairs = null;
        if (params != null && !params.isEmpty()) {
            pairs = new ArrayList<NameValuePair>(params.size());
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String value = entry.getValue();
                if (value != null) {
                    pairs.add(new BasicNameValuePair(entry.getKey(), value));
                }
            }
        }
        HttpPost httpPost = new HttpPost(url);
        if (pairs != null && pairs.size() > 0) {
            httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
        }
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                httpPost.abort();
                throw new RuntimeException("HttpClient,error status code :" + statusCode);
            }
            HttpEntity entity = response.getEntity();
            String result = null;
            if (entity != null) {
                result = EntityUtils.toString(entity, "utf-8");
            }
            EntityUtils.consume(entity);
            return result;
        } catch (ParseException e) {
            log.error("请求服务器端出错:" + e);
            return null;
        } finally {
            if (response != null)
                response.close();
        }
    }
}

5.5 启动类

package com.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @Author: JYC
 * @Title: AppOrder
 * @Description: TODO
 * @Date: 2022/4/21 14:10
 */
@SpringBootApplication
public class AppOrder {
    public static void main(String[] args) {
        SpringApplication.run(AppOrder.class);
    }
}

5.3 启动项目

在这里插入图片描述

5.4 接口测试

在Nacos的服务管理界面中看到刚刚启动的两个服务,表示两个服务均启动成功。
在这里插入图片描述
访问接口:http://127.0.0.1:8070/orderToMember
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/131269.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!