Spring Cloud Alibaba Nacos 服务发现

1.Nacos 简介

发音: /nɑ:kəʊs/
全称:Name and Config Service,nacos 是其首字母的拼写。
Nacos 的核心功能 = 服务注册 + 动态配置
可以理解为 Nacos = SpringCloud Eureka + SpringCloud Config

2.什么是服务发现

服务消费者怎么找到服务提供者的机制就是服务发现。

3.实现服务发现机制需要解决很多的问题

健康检查:
问题:服务实例故障了,无法主动注销自己的信息怎么办?
方案:通过心跳机制进行健康检查,注册中心删除无心跳的实例信息

本地缓存:
问题:每次服务调用之前都查询注册中心,性能差、不可靠,怎么办?
方案:本地缓存、定时更新(定时查询服务列表、服务注册中心主动推送)

数据同步:
问题:注册中心集群中各个节点的数据如何同步?
方案:强一致性,例如 ZooKeeper。弱一致性,例如 Eureka。

4.Nacos 特征与优势

 

 

 

 

 5.Nacos环境搭建

官网文档:https://nacos.io/zh-cn/docs/quick-start.html

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

Spring Boot 2.3.x:https://github.com/alibaba/nacos/releases/tag/1.4.1

 

windows安装方式

选择 nacos-server-1.4.1.zip 进行下载

解压进入到 C:\Software\nacos-server-1.4.1\bin 目录

双击 startup.cmd 一闪而过代表失败,注意Java环境是否安装和配置。

浏览器访问:http://127.0.0.1:8848/nacos

用户名和密码都是nacos

服务注册(linux)

curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'

服务发现(linux)

curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'

使用 Postman

File => Import => Raw test

粘贴curl命令

6.服务提供者和消费者整合Nacos

6.1 provider(服务提供者)

6.1.1 加依赖

<dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

6.1.2 加注解

package com.example.serviceprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
// 加注解(开启服务发现)
@EnableDiscoveryClient
public class ServiceProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }

}

6.1.3 改配置

server:
  port: 8081
spring:
  application:
    name: service-provider
# 添加 nacos 地址 cloud: nacos: discovery: server
-addr: localhost:8848 namespace: 23ffbc32-5bde-4451-9683-c346220fa282 group: g1 cluster-name: beijing

6.1.4 创建测试接口

package com.example.serviceprovider;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("hello")
    public String hello(@RequestParam String name){
        return "hello " + name;
    }
}

6.2 consumer(消费者)

6.2.1 加依赖

<dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

6.2.2 加注解

package com.example.serviceprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
// 加注解(开启服务发现)
@EnableDiscoveryClient
public class ServiceConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }

}

6.2.3 改配置

server:
  port: 8082
spring:
  application:
    name: service-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

6.2.4  配置 RestTemplate

package com.example.serviceprovider;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConsumerConfig {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

6.2.5 发起服务调用

package com.example.serviceprovider;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.URI;


@RestController
public class TestController {
    // 引入 RestTemplate
    @Autowired
    RestTemplate restTemplate;

    // 引入 LoadBalancerClient
    @Autowired
    LoadBalancerClient loadBalancerClient;

    @GetMapping("hello")
    public String hello(@RequestParam String name) {
        String result = "";

        // 根据服务名获取服务实例
        ServiceInstance serviceInstance = loadBalancerClient.choose("service-provider");

        // 发起调用
        URI uri = serviceInstance.getUri();
        result = restTemplate.getForObject(uri + "/hello?name=test", String.class);

        // 返回结果
        return result;
    }
}

 7.Nacos 服务领域模型

 

 

namespace :命名空间ID

group:组

cluster-name:集群

Nacos 三层数据模型:NameSpace, Group, Service

Nacos 服务领域模型:NameSpace, Group, Service,Cluster, Instance
8.负载均衡与权重

负载均衡的类型 

服务端负载均衡:如nginx 根据负载均衡策略选择某个实例转发请求

客服端负载均衡:根据自己实现的负载均衡策略选择

8.1 provider(服务提供者),使用配置的服务端口号

package com.example.serviceprovider;

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

@RestController
public class TestController {
    @Value("${server.port}")
    Integer port;

    @GetMapping("hello")
    public String hello(@RequestParam String name){
        return "hello " + name + " " + port;
    }
}

8.2 consumer(消费者),使用负载均衡注解

package com.example.serviceprovider;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConsumerConfig {
    // 使用负载均衡注解
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

服务调用

package com.example.serviceprovider;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class TestLBController {
    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/testlb")
    public String testlb(@RequestParam String name){
        String  result = "";
result = restTemplate.getForObject("http://service-provider/hello?name=" + name, String.class); return result; } }

负载均衡策略

 

 

  SpringBoot 配置文件修改负载均衡策略

package com.example.serviceprovider;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConsumerConfig {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

   // 负载均衡策略
    @Bean
    public IRule iRule(){
return new RandomRule();
  } }

8.3 自定义基于权重的负载均衡策略的方法

 

 

 服务消费者中实现基于权重的负载均衡策略

package com.example.serviceprovider;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.beans.factory.annotation.Autowired;

public class NacosWeightRule extends AbstractLoadBalancerRule {
    // 引入 NacosDiscoveryProperties
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    // 重写 choose 方法
    @Override
    public Server choose(Object o) {
        // 获取服务提供者的名字
        // 拿到 nacos 的命名服务对象
        // 通过 nacos 的命名服务根据权重获取实例
        // 封装 server 对象,返回

        BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
        String name = loadBalancer.getName();
NamingService namingService
= nacosDiscoveryProperties.namingServiceInstance(); try { Instance instance = namingService.selectOneHealthyInstance(name); return new NacosServer(instance); }catch (Exception e){ e.printStackTrace(); } return null; } @Override public void initWithNiwsConfig(IClientConfig iClientConfig) { } }

Nacos配置修改权重配置

@Configuration
public class ConsumerConfig {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    public IRule iRule(){
       //根据权重的负载均衡策略
        return new NacosWeightRule();
    }

}

9.Nacos集群部署

 

9.1 创建数据库和表

使用sql脚本创建数据库

nacos-server => conf  => nacos-mysql.sql

 

9.2 配置MySQL连接

nacos-server => conf  =>  application.properties

# 表明用MySQL作为后端存储
spring.datasource.platform=mysql
# 有几个数据库实例
db.num=1
# 第1个实例的地址
db.url.0=jdbc:mysql://[mysqlIP]/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout
=3000&autoReconnect=true
db.user=[数据库用户名]
db.password=[数据库密码]

 

9.3 配置集群节点IP端口

nacos-server => conf  =>  application.properties

 

# nacos01
server.port=8841


# nacos02
server.port=8842


# nacos03
server.port=8843

 

nacos-server => conf  =>  cluster.conf.example 复制一份 去掉后缀example ,每个集群实例配置,相同配置文件。

server 127.0.0.1:8841;
server 127.0.0.1:8842;
server 127.0.0.1:8843;

启动各个nacos 

9.4 配置Nginx

nginx.conf 配置文件 include servers/* 意思是加载servers文件夹下所以配置文件,所以进入到servers文件夹 创建 nocos.conf 配置文件,以下是nocos.conf 内容

upstream nacos {
 server 127.0.0.1:8841;
 server 127.0.0.1:8842;
 server 127.0.0.1:8843;
}
server { listen
9090; server_name localhost; location /nacos/ { proxy_pass http://nacos; } }

 

posted @ 2021-02-17 21:50  Goosander  阅读(1343)  评论(0编辑  收藏  举报