nacos实现服务注册中心与配置中心
作者:互联网
一、nacos简介
Nacos(DynamicNaming and Configuration Service)是一个应用于服务注册与发现、配置管理的平台,代替了原来SpringCloud系列中的Eureka+Config+Bus。它孵化于阿里巴巴,成长于十年双十一的洪峰考验,沉淀了简单易用、稳定可靠、性能卓越的核心竞争力。
官网地址: https://nacos.io/zh-cn/docs/quick-start.html
常见注册中心:Zookeeper(雅虎Apache),Eureka(Netfix),Nacos(Alibaba),Consul(Google)
二、nacos服务搭建
1 下载与安装
浏览器输入网址 https://github.com/alibaba/nacos/releases
选择对应版本下载,我使用的版本是1.4.1,然后解压
2 初始化配置
解压后的文件找到/conf/nacos-mysql.sql文件,创建nacos_config数据库(数据库名可自己指定,编码方式utf8mb4),把nacos-mysql.sql脚本导入该库中,脚本执行成功后会创建如下表
说明:在执行此文件时,要求mysql的版本大于5.7版本(MariaDB最好10.5.11),否则会出现如下错误:
打开/conf/application.properties文件,配置你导入nacos-mysql.sql数据库的配置信息
### If use MySQL as datasource:
spring.datasource.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=1234
3 服务启动与访问
进入解压文件的bin目录,windows环境下执行命令 startup.cmd -m standalone
其中-m代表启动模式,standalone代表着单机模式运行,非集群模式
启动成功后,访问Nacos服务,浏览器输入 http://localhost:8848/nacos
默认账号密码为nacos/nacos 登录
三、服务注册与发现入门
需求说明:创建两个项目Module分别为服务提供者和服务消费者,两者都要注册到NacosServer中(这个server本质上就是一个web服务,端口默认为8848),然后服务提供者可以为服务消费者提供远端调用服务(例如支付服务为服务提供方,订单服务为服务消费方),如图所示:
1 创建Maven父工程
创建maven module父工程,命名为00-review-msa,该工程的作用就是来管理子模块中所需要的共性核心依赖
pom.xml文件内容如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhanlijuan</groupId>
<artifactId>00-review-msa</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<spring.cloud-version>Hoxton.SR8</spring.cloud-version>
<spring.cloud.alibaba-version>2.2.5.RELEASE</spring.cloud.alibaba-version>
</properties>
<!--依赖版本管理-->
<dependencyManagement>
<dependencies>
<!--spring cloud 依赖,此依赖需要springboot的支持,此依赖中定义了spring cloud微服务规范-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<!-- import表示此工程下的子工程可以直接引用这个依赖中的版本-->
<scope>import</scope>
<!--当scope为import时,这里的类型必须为pom类型-->
<type>pom</type>
</dependency>
<!--spring cloud alibaba 依赖,此依赖依赖于spring cloud,当前依赖中是基于微服务规范做了具体实现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba-version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
</project>
注意:其中的版本可参考如下网址(涉及到一个兼容性问题,不能随意指定其版本):
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
说明:父工程资源初始化完成以后,将src目录删除,因为父工程只负责依赖管理.
2 生产者服务创建及注册
在00-review-msa父工程下创建子工程msa-provider,添加项目依赖
<dependencies>
<!--web服务-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--服务的注册和发现(我们要将服务注册到nacos)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
修改配置文件application.yml 实现服务注册
server:
port: 8081
spring:
application:
#服务名,后续会在注册中心里呈现这个名字 服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则
name: msa-provider
cloud:
nacos: #服务的注册与发现
server-addr: localhost:8848
定义处理请求的控制层对象和方法
@RestController
public class TestController {
@Value("${server.port}")
private String port;
@GetMapping(value = "/provider/test/{msg}")
public String doEcho(@PathVariable String msg) {
return port + "say:Hello Nacos Discovery " + msg;
}
}
启动启动类,然后刷新nacos服务,检测是否服务注册成功
打开浏览器,输入 http://localhost:8081/provider/test/msa
,然后进行访问。
3 消费者服务发现及调用
在00-review-msa父工程下创建子工程msa-consumer,添加项目依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--服务注册和发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
修改配置文件application.yml
server:
port: 8090
spring:
application:
name: msa-comsumer
cloud:
nacos:
discovery:
server-addr: localhost:8848 #从哪里去查找服务
构建远程过程调用对象,基于此对象访问远程服务,服务消费方通过RestTemplate 调用服务提供方的服务的
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
编写测试类,测试服务消费
@RestController
public class TestController {
@Value("${spring.application.name}")
private String appName;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/test")
public String test() {
String url = "http://localhost:8081/provider/echo/" + appName;
System.out.println("request url:" + url);
return restTemplate.getForObject(url, String.class);
}
}
启动消费者服务,在nacos中注册成功
浏览器输入 http://localhost:8090/consumer/test
出现如下效果
四、nacos实现负载均衡
1 @LoadBalancerClient
修改TestController类,注入LoadBalancerClient对象,添加testLoadBalancerClient方法
/**
* 负载均衡客户端对象,基于此对象可以从注册中心获取服务实例
*/
@Autowired
private LoadBalancerClient loadBalancerClient;
/**
* 基于RestTemplate进行远程服务调用,但是在调用之前基于loadBalancerClient对象去从nacos注册中心基于服务名查找服务实例(可能有多个)
* 此时会在本地按照一定算法去选择服务实例,然后进行服务调用
*/
@GetMapping("/consumer/testLoadBalancerClient")
public String doRestEcho02() {
//基于服务名(nacos中服务列表中的名字)查找服务实例
ServiceInstance serviceInstance = loadBalancerClient.choose("msa-provider");
//构建远程调用的url
String url = String.format("http://%s:%s/provider/echo/%s", serviceInstance.getHost(), serviceInstance.getPort(), appName);
System.out.println("request url:" + url);
return restTemplate.getForObject(url, String.class);
}
msa-provider 服务启动两个,端口分别为8081,8082,启动msa-consumer服务,检查服务是否注册成功
浏览器访问 http://localhost:8090/consumer/testLoadBalancerClient
反复刷新,你会发现msa-provider的两个服务都可以处理msa-consumer的请求
总结:这里多个实例并发提供服务的方式为负载均衡,这里的负载均衡实现默认是因为Nacos集成了Ribbon来实现的,Ribbon配合RestTemplate,可以非常容易的实现服务之间的访问。Ribbon是Spring Cloud核心组件之一,它提供的最重要的功能就是客户端的负载均衡(客户端可以采用一定算法,例如轮询访问,访问服务端实例信息),这个功能可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡方式的服务调用。
2 @LoadBalanced
描述RestTemplate对象,用于告诉Spring框架,在使用RestTempalte进行服务调用时,这个调用过程会被一个拦截器LoadBalancerInterceptor进行拦截LoadBalancerInterceptor将负载均衡的核心逻辑交给了loadBalancer,然后在拦截器内部,启动RestTemplate的负载均衡。
RestTemplateConfig类添加代码
@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate() {
return new RestTemplate();
}
修改TestController类
@Autowired
private RestTemplate loadBalancedRestTemplate;
/**
* 基于具备了负载均衡特性的RestTemplate进行远程服务调用,实现的功能与方式 loadBalancerClient 相同,只是代码编写上做了简化,
* 此效率会稍微弱于方式loadBalancerClient,因为底层会对请求进行拦截,拦截到以后基于loadBalancerClient获取服务实例,然后进行调用
*/
@GetMapping("/consumer/loadBalancedRestTemplate")
public String doRestEcho04() {
String url=String.format("http://%s/provider/echo/%s","msa-provider",appName);
System.out.println("request url:" + url);
return loadBalancedRestTemplate.getForObject(url, String.class);
}
五、基于Feign的远程服务调用
1 Feign简介
Feign 是一种声明式Web服务客户端,底层封装了对Rest技术(拼接url,拼接参数)的应用,通过Feign可以简化服务消费方对远程服务提供方法的调用实现,最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由社区进行维护,更名为 OpenFeign。
2 Feign入门案例
在服务消费方,添加项目依赖(SpringCloud团队基于OpenFeign研发了starter)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
启动类上添加@EnableFeignClients注解
定义Http请求API,基于此API借助OpenFeign访问远端服务
/**
* 基于@FeignClient定义远程服务调用接口,这个接口不需要我们自己写实现类,底层会在服务启动时会帮我们创建实现(代理对象),在实现类内部进行远程服务调用
* 其中:
* name 属性的值为nacos中的服务名,
* contextId 为一个上下文id,作为远程调用服务的唯一标识,一般就写当前接口名,用于区分服务调用,
* 因为将来一个服务提供方会提供很多资源调用,假如服务消费方,基于同一个服务提供方,写了很多接口此时假如没有指定contextId,服务启动就会失败
*/
@FeignClient(name = "msa-provider", contextId = "remoteProviderService")//msa-provider为nacos中的服务名
public interface RemoteProviderService {
@RequestMapping("/provider/echo/{msg}")//前提是远端服务msa-provider有这个请求地址
String echoMsg(@PathVariable String msg);
}
创建FeignConsumerController中并添加feign访问
@RestController
@RequestMapping("consumer")
public class FeignConsumerController {
@Autowired
private RemoteProviderService remoteProviderService;
/**
* 基于feign方式的服务调用
*/
@GetMapping("feign/echo/{msg}")
public String doFeignEcho(@PathVariable String msg) {
//基于feign方式进行远端服务调用(前提是服务必须存在)
return remoteProviderService.echoMsg(msg);
}
}
重启服务,浏览器访问 http://localhost:8090/consumer/feign/echo/hello
测试
3 远程服务异常处理
定义FallbackFactory接口的实现
/**
* 基于此对象处理RemoteProviderService接口调用出现的异常问题
*/
@Component
public class ProviderFallbackFactory implements FallbackFactory<RemoteProviderService> {
/**
* 此方法会在RemoteProviderService接口服务调用时,出现了异常后执行
*/
@Override
public RemoteProviderService create(Throwable throwable) {
return (msg) -> "服务维护中,请稍后重试";
}
}
在Feign访问接口中应用FallbackFactory对象
在application.yml中添加配置,启动feign方式调用时的服务中断处理机制.
#启用feign方式服务调用的异常处理机制
feign:
hystrix:
enabled: true
重启msa-comsumer服务,停止msa-provider服务,浏览器输入 http://localhost:8090/consumer/feign/echo/dddd
测试
4 Feign调用过程分析
Feign应用过程分析(底层逻辑先了解):
1)通过 @EnableFeignCleints 注解告诉springcloud,启动 Feign Starter 组件。
2) Feign Starter 在项目启动过程中注册全局配置,扫描包下所有@FeignClient注解描述的接口,然后由系统底层创建接口实现类(JDK代理类),并构建类的对象,然后交给spring管理(注册 IOC 容器)。
3) 接口被调用时被动态代理类逻辑拦截,将 @FeignClient 请求信息通过编码器生成 Request对象,基于此对象进行远程过程调用。
4) 请求对象经Ribbon进行负载均衡,挑选出一个健康的 Server 实例(instance)。
5) 通过 Client 携带 Request 调用远端服务返回请求响应。
6) 通过解码器生成 Response 返回客户端,将信息流解析成为接口返回数据。
六、nacos实现配置中心
市场上主流配置中心有Apollo(携程开源),nacos(阿里开源),Spring Cloud Config(Spring Cloud 全家桶成员)这里选择nacos,此组件不仅提供了注册中心,还具备配置中心的功能,动态管理发布配置,无需重启服务,更好保证服务的可用。
1 nacos配置快速入门
在msa-provider服务的pom文件添加依赖
<!--添加nacos配置中心依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
将项目中的application.yml的名字修改为bootstrap.yml配置文件(启动优先级最高)
spring:
application:
#服务名,后续会在注册中心里呈现这个名字 服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则
name: msa-provider
cloud:
nacos:
discovery: #服务的注册与发现
server-addr: localhost:8848
config: #服务的配置
server-addr: localhost:8848
group: DEFAULT_GROUP
file-extension: yml
打开nacos配置中心,新建配置
其中Data ID的值要与bootstrap.yml中定义的spring.application.name的值相同(服务名-假如有多个服务一般会创建多个配置实例,不同服务对应不同的配置实例)。
在TestController中添加注解**@RefreshScope**实现动态发布,添加一个获取日志级别的方法
/**
* @RefreshScope的作用是在配置中心的相关配置发生变化以后,能够及时看到更新(底层是通过重新创建Controller对象的方式,对属性进行了重新初始化)
*/
@RefreshScope //动态刷新配置
@RestController
@Slf4j
public class TestController {
@Value("${logging.level.com.zhanlijuan:error}")
private String logLevel;
@GetMapping("/provider/doGetLogLevel")
public String doGetLogLevel() {
log.trace("==log.trace==");//跟踪
log.debug("==log.debug==");//调试
log.info("==log.info==");//常规信息
log.warn("==log.warn==");//警告
log.error("==log.error==");//错误信息
return "log level is " + logLevel;
}
}
浏览器输入 http://localhost:8082/provider/doGetLogLevel
然后nacos修改日志级别在继续测试,验证是否动态更新
2 nacos配置管理模型
Nacos 配置管理模型由三部分构成,如图所示:
2.1 命名空间设计
Nacos中的命名空间一般用于配置隔离,这种命名空间的定义一般会按照环境(开发,生产等环境)进行设计和实现.我们默认创建的配置都存储到了public命名空间
需求:自定义命令空间,测试环境,从配置中读取信息
创建命名空间beta
命名空间成功创建以后,会在如下列表进行呈现。
在指定命名空间下添加配置,也可以直接取配置列表中克隆,例如:
克隆成功以后,我们会发现在指定的命名空间中有了我们克隆的配置
修改beta命名空间中Data Id的msa-provider的配置
在bootstrap.yml文件中增加命名空间namespace的配置
重启服务,测试能否获取到beta里面的配置的日志级别
2.2 分组设计及实现
当我们在指定命名空间下,按环境或服务做好了配置以后,有时还需要基于服务做分组配置,例如,一个服务在不同时间节点(节假日,活动等)切换不同的配置,可以在新建配置时指定分组名称
修改boostrap.yml配置类,在其内部指定我们刚刚创建的分组
在NacosConfigController类中添加属性和方法用于获取和输出DEV_GROUP_51配置中设置的线程数
@Value("${server.tomcat.threads.max:200}")
private Integer maxThread;
@RequestMapping("/provider/doGetMaxThread")
public String doGetMaxThread(){
return "server.threads.max is "+maxThread;
}
重启服务测试
2.3 共享配置设计及读取
当同一个namespace的多个配置文件中都有相同配置时,可以对这些配置进行提取,然后存储到nacos配置中心的一个或多个指定配置文件,哪个微服务需要,就在服务的配置中设置读取即可。
在nacos中创建一个共享配置文件
在指定的微服务配置文件(bootstrap.yml)中设置对共享配置文件的读取
spring:
application:
#服务名,后续会在注册中心里呈现这个名字 服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则
name: msa-provider
cloud:
nacos:
discovery: #服务的注册与发现
server-addr: localhost:8848
config: #服务的配置
server-addr: localhost:8848
#group: DEFAULT_GROUP 默认的分组
file-extension: yml
#namespace: cad30c4b-105c-4f0b-9ec1-a63a9e9a9837 #命名空间namespace不写默认是public 用于环境的隔离
group: DEFAULT_GROUP_11
shared-configs[0]: #共享配置
data-id: app-public-beta.yml
group: DEFAULT_GROUP
refresh: true #默认false
NacosConfigController 类添加业务逻辑代码验证
@Value("${page.pageSize:10}")
private Integer pageSize;
@GetMapping("/provider/doGetPageSize")
public String doGetPageSize() {
//return String.format()
return "page size is " + pageSize;
}
启动服务进行访问测试
标签:调用,服务,String,中心,nacos,注册,provider,msa 来源: https://blog.csdn.net/zhanlijuan2015/article/details/119273050