前言
最近开始在研究微服务,特别是springcloudalibaba系列产品,对于刚入门的小白来说,我对于一些分布式和微服务的概念还不是很透彻,经过了两天的测试与踩坑,这里我将给小伙伴们分享一些对微服务的服务注册的概念,以及简单的整合使用两种通信技术进行服务通信的手段
(这篇文章,只是应对于入门选手的梳理认识教程,并不属于进阶教程,因为小编也是刚刚开始研究微服务和刚刚开始尝试写文章,如果哪里有什么疏漏不足或者值得改进的地方,欢迎评论区留言哦!)
回顾
相信搜索或者观看这篇文章的朋友已经对微服务架构和单体应用架构有了一定认识,这里我就不赘述了,先来给大家简单回忆一下什么是nacos
Nacos 是一个开源项目,它的全称是 "NA"me"CO"nf Service,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它由阿里巴巴开发,并于2018年开源。Nacos 设计用于现代微服务架构,旨在简化服务发现和配置管理的过程。
主要功能包括:
1. 服务发现:Nacos 支持基于 DNS 和基于 API 的服务发现机制。它允许应用程序注册自己的元数据(如主机名、端口、健康状态等),并允许其他服务查询这些信息来定位服务实例。
2. 动态配置管理:Nacos 提供了一个动态配置服务,允许应用程序在不重启的情况下刷新配置信息。这意味着,如果配置发生更改,应用程序可以立即响应这些更改而无需重新启动。
3. 服务管理:除了服务发现和配置管理之外,Nacos 还提供了一系列的服务管理功能,比如服务的健康检查、服务的权重调整、服务的流量控制等。
4. 分布式协调服务:Nacos 提供了分布式协调服务的功能,可以用来解决分布式系统中常见的问题,如命名冲突、集群管理等。
使用场景:
Nacos 可以应用于多种场景,尤其适合那些需要频繁更新配置、依赖复杂的服务间通信的分布式系统。例如,在微服务架构中,使用 Nacos 可以更容易地管理和协调各个服务间的交互。
技术栈兼容性:
Nacos 设计为与不同的编程语言和框架兼容,支持 Java、Go、Python、Node.js 等多种语言的客户端库,这使得它可以轻松集成到现有的技术栈中。
nacos中常见的一些名词简单解释
服务与服务实例:
nacos是一个服务注册与管理的平台,最直接的操作单元就是服务实例,一个服务,代表着微服务的一个服务模块,为了实现负载均衡与保证可靠性,一个服务总是由多个相同的服务实例构成,服务实例可以认为就是一个服务或者程序进程
可以理解为,一个服务集群有多个相同服务,一个服务有多个相同服务实例
服务相关属性认识:
服务名:该服务端名字,默认情况下,在spring中,是以application中的name值
服务分组名称:服务所属的组的名称
集群数目:该服务的集群的数目
实例数:该服务所拥有的服务实例数量
健康实例数:服务状态良好的服务实例的数量
元数据:对该服务实例的一些附加批注描述,这些信息可以帮助更好地描述和控制服务的行为(nacos自动处理,程序员获取元数据处理都有,此外元数据是可以自定义,也有自动生成的部分)。元数据可以是服务级别的,也可以是实例级别的,具体取决于其用途。
(元数据的高级使用与服务集群管理属于比较进阶点的应用,这篇文章不会细讲,后面单独讲)
命名空间:
命名空间是nacos里面最大的服务隔离,也是一直逻辑隔离,默认情况下,不同命名空间的服务是不能互相调用的,只有同一命名空间的服务才能被互相调用,一般情况下,不同命名空间用于区分不同的项目或者不同的开发阶段环境
服务分组:
是对命名空间的进一步更细腻的服务逻辑分隔,但是它对服务的隔离要求不是强制的,就是说,同一命名空间的不同服务分组的服务之间也是可以互相调用的,服务分组一般是业务逻辑分组,主要是用于项目开发中的便于管理与服务分类
配置管理:
nacos不仅是一个注册中心,也是一个配置管理中心,简单就是说,各个服务或者服务实例的部分公共配置可以不再写在服务本地,而是集中交给配置中心,各个本地服务可以从配置中心拉去配置,这样使得配置管理更集中化,更容易管理,也避免了很多重复造轮子的工作(简单的理解:配置就是springboot应用中yaml文件写那些东西)
配置中心这个dataId与group就像服务注册那个name和group一个道理,dataId不是代表一个文件名,他就是一个标识,这里有个坑,下面小编会说一下
实际演示
光说不练假把式,下面我们从代码和过程中继续研究一下nacos
服务启动:
nacos下载就不说了,这里小谈一下启动
刚下载的nacos,在bin目录下面包含这几个文件,其中cmd是windows中使用的,sh是linux中使用的。windows下在命令窗口输入:
当然这里只是单机启动模式,在测试与生产的时候使用,不具有可靠性,nacos还有许多,比如集群启动,嵌入启动,docker启动,这些以后的文章会讲到,这里只是入门教程(写这篇文章的时候,小编也不会其他启动的运用,哈哈哈!!)。启动后,就能见到上面介绍nacos的那个截图的页面(刚开始是没有数据的哈)
pom中:
接下来开始创建java服务实例:
在pom中需要导入:
因为nacos不是对应了服务注册与配置中心的功能嘛,这两个依赖就分别对应着
此外加入这个依赖:
这个依赖保证了spring项目在启动时先预加载好bootstrap.yaml文件,这里是为了通过这个文件在服务启动前预配置一些东西,比如拉去配置中心配置这种等等,bootstrap.yaml 配置文件与 application.yaml 一般是分开的,这样可以更好地分离不同层次的配置。例如,bootstrap.yaml 通常用于配置外部配置中心的信息,而 application.yaml 用于应用程序本身的配置。
配置上:
本地bootstrap.yaml:
spring:
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
file-extension: yaml # 配置文件扩展名
refresh-enabled: true # 启用配置刷新
enable-remote-sync-config: true # 启用远程同步配置
namespace: public # 命名空间
group: DEFAULT_GROUP # 配置分组
timeout: 5000 # 超时时间
discovery:
server-addr: "127.0.0.1:8848" # 但是好像默认会跟着config那里配置的中心地址,因为,对于nacos是一体的,下面两个也一样
namespace: public
group: DEFAULT_GROUP
application:
name: "test-provider"
本地application.yaml:(这里不是必须的,只是我为了演示下面的东西所以加了grpc与springweb)
server:
port: 8762
grpc:
server:
port: 9089
在配置中心,可以再加一些配置:
这里有个坑,就是dataId那个后缀,和下面选的配置格式,是没有关系的,这不是一个文件,后缀的说法只是名字上,dataId整个内容,必须是引用的服务名加上-模式(这里是dev开发模型,就加上-dev)加上.配置文件扩展名(这里是yaml就加上.yaml)(注意比对上面bootstrap.yaml的配置和这里nacos中心的配置)
基本配置完成后,不要忘记在配置主类上加入@EnableDiscoveryClient启动作为nacos服务发现(可以设置参数比如@EnableDiscoveryClient(autoRegister = false),应用在启动时不会自动将其自身注册到服务发现组件,一般用于需要自定义注册的情况)
autoRegister 参数只控制当前应用是否自动注册到服务发现组件中,而不影响它发现其他服务的能力。
package test.demo1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
启动后:
登录nacos控制台中心,可以看到:
点击详情:
可以看到刚刚配置中心的元数据,说明配置拉去是成功了的,为什么这里grpc会有两个,一个是我们加进去的元数据,一个是nacos整合grpc自带的,就是说配置了grpc服务端口,nacos就会自动注册进去的(后面会提)
接下来写一个一样的服务实例,由于是在本机上,所以,只改一下端口信息。
出现的服务列表图:
出现的详情:
(这里有点小问题哈,grpc,一是按道理现在测试的时候两个在一台机器上的grpc端口应该不一样,但是我们元数据是在配置中心共享了的,所以这里元数据在自定义这部分是一样的。另外下面这个没有系统自带的元数据,其实是我没有在另一个应用中配置grpc端口,写这个文章第一遍没注意,各位见谅哈~~~。但是,相信聪明的码友们也能充分从这里的小问题更多的理解出配置中心和相同服务不同服务实例这两个概念)
服务通信问题
其实,服务注册中心,并不直接提供服务通信的功能,他只是一个服务注册与发现平台,可以简单的理解为是对服务通信的一个监管,这点认识很重要哟,不然容易和后面我讲dubbo搞混。
这里我不讲dubbo,简单给大家看看,使用nacos服务中心的管理下,使用feign通信与grpc通信这两种方式与传统的区别。另外·,这里暂时不会讲他们的负载均衡哦(后面的文章会讲到的),这里主要是讲最基础的联通
先给大家简单的回顾梳理一下
feign通信:
Feign 是一个声明式的 Web 服务客户端,它使得编写 HTTP 客户端变得更加简单。Feign 的主要特点包括:
声明式 API:
使用注解来定义 HTTP 请求,无需手动构建请求。
支持多种 HTTP 方法(GET, POST, PUT, DELETE 等)。
集成 Spring Cloud:
可以与 Spring Cloud 生态系统无缝集成,例如 Eureka 服务发现、Ribbon 负载均衡等。
支持服务间的负载均衡和容错。
配置简单:
通过简单的注解和配置即可完成客户端的设置。
支持自定义编码器和解码器,便于处理复杂的请求和响应。
适合 RESTful 服务:
主要用于基于 HTTP/REST 的微服务间通信。
适用于大多数 Web 服务和微服务架构。
简单就是,他能让服务间通信像restful网络接口的方式来通信,其实基础使用挺简单,建议看看哟
grpc通信:
gRPC 是一种高性能、开源和通用的 RPC 框架,支持多种语言。它的主要特点包括:
高效序列化:
使用 Protocol Buffers 作为接口定义语言(IDL),生成高效的序列化和反序列化代码。
相比 JSON 和 XML,Protocol Buffers 更小、更快、更简洁。
多语言支持:
支持多种编程语言,如 Java, C++, Python, Go, Ruby, Node.js 等。
适合跨语言的服务间通信。
双向流:
支持四种类型的 RPC 调用:简单 RPC、服务器流 RPC、客户端流 RPC 和双向流 RPC。
适合需要实时通信和流数据传输的应用。
HTTP/2 协议:
基于 HTTP/2 协议,提供多路复用、头部压缩等特性,提高性能和效率。
服务定义:
使用 .proto 文件定义服务接口和消息类型,生成客户端和服务端代码。
代码生成减少了手动编写和维护代码的工作量。
这个有独特的通信风格,有一定学习成本(但多写写也简单的),但是很高效,而且也算是一种未来趋势
其实总结一点就是基本依赖和配置都是一样的,只是调用的时候,客户端不再需要具体网址端口来指定,可以通过服务名来发现和负载均衡(下面例子看不看无所谓,只是简单的演示这一句话的意思)!!!
代码演示
在依赖和配置上,都是与传统类似的,具体可以先去了解一下这两个通信,因为这里是讲在nacos服务中心中使用与传统使用区别,比如:
feign的(客户端):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
grpc的(客户端与服务端):
<!--客户端-->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>2.14.0.RELEASE</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
<!--服务端-->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.14.0.RELEASE</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
对于feign:
feign在使用上与传统的区别(我这里传统是指与非微服务架构下单纯的服务通信的传统,因为feign是springcloud中常用的方式,与很多其他注册中心都有搭配用法,我这里传统是对比没有注册中心时):
服务端:不存在什么不一样,都是restful接口方式
客户端:
package test.demo3.demos.dao;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "test-provider")
public interface FeignDao {
@GetMapping("/feign_test/{name}")
public String getNameHello(@PathVariable("name") String name);
}
传统调用:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(url = "http://localhost:8081")
public interface ExampleClient {
@GetMapping("/api/example")
String getExample(@RequestParam("param") String param);
}
哎哟,这里搞得这么神奇,说白了就是,传统需要指定url具体路径,但是在nacos注册中心下,无缝衔接feign,只需要写服务名(可以配置分组等等),然后,内部会自动负载均衡到相应服务实例,当然也可以指定url来确定实例
对于grpc:
所有与原来都一样,只需要在客户端的配置时不太一样
传统:
nacos下客户端:
说白了就是不用配置地址,但是client下面的名称,必须是与服务端服务名一样,还有一个小坑,注意认识yaml文件命名规范,这里因为服务端名要在这里客户端作为yaml属性,小编刚开始就是用的带下划线的服务端名,自然就会有问题
结语
这是小编第一次写博客,可能有些文章上或者准确度上的问题,如果码友们想吐槽或者想一起讨论的,欢迎大家评论区留言哦,注意,上面的内容有一定部分是小编自己理解上的简述,可能不会很严谨,但是主要是为了方便像小编一样的比较弱的微服务新手们更好的理解,但是,小编一直认为一切以官方文档为先,有能力的佬可以一切以源码为先