目录
1、背景
入职demo升级…
- 要求:
- 使用nacos作为注册中心,将 生产者微服务 和 消费者微服务 注册到 注册中心
- 消费者 能够使用服务名调用 提供者 的接口
- 启动多个 生产者 实例,观察
ribbon
负载均衡效果
- 技术栈:
nacos
和ribbon
- 目的:
- 了解注册中心的作用
- 了解通过服务名调用微服务接口的方式(使用
ribbon
实现) - 了解负载均衡的效果(可以通过在提供者接口实现中打印日志来观察是哪个实例被调用了)
2、在原项目中更新
(1)生产者
a. 添加nacos依赖
- 子工程
pom.xml
<!-- 启动 Nacos 配置管理服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<!-- 启用 Nacos 的服务注册发现功能(将服务注册到nacos上) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
b. 配置Nacos server地址和服务名
application.yml
server:
port: 10003
spring:
datasource:
driver-class=name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/provider?characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: root
schema: classpath:db/schema-mysql.sql
data: classpath:db/data-mysql.sql
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
discovery:
server-addr: 127.0.0.1:8848 # 配置Nacos Server地址
application:
name: provider-service-prl #项目的服务名
或:
c. 启动类添加注解
@EnableDiscoveryClient
:开启服务注册发现功能
(2)消费者
配置服务消费者,从而服务消费者可以通过 Nacos 的服务注册发现功能从 Nacos server 上获取到它要调用的服务
a. 添加nacos依赖
- 子工程
pom.xml
<!-- 启动 Nacos 配置管理服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<!-- 启用 Nacos 的服务注册发现功能(将服务注册到nacos上) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
b. 配置nacos地址与服务名
application.yml
server:
port: 10004
spring:
application:
name: service-consumer-prl
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
discovery:
server-addr: 127.0.0.1:8848
c. 启动类添加注解
@EnableDiscoveryClient
:开启服务注册发现功能
- 注意:restTemplate添加了@LoadBalanced来开启负载均衡后,只能通过内网访问
d. 更改控制层中的生产者路径
- 现在消费者所有的访问必须以应用名访问,也就是生产者注册在Nacos中的服务名
- 踩坑:当使用带有负载均衡的restTemplate时,要使用服务名进行访问服务,否则报错:
java.lang.IllegalStateException: No instances available for localhost
at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:75) ~[spring-cloud-netflix-core-1.3.1.RELEASE.jar:1.3.1.RELEASE]
at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:55) ~[spring-cloud-commons-1.2.2.RELEASE.jar:1.2.2.RELEASE]
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:86) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:70) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:659) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
3、测试结果
-
打开nacos,在cmd中使用
startup.cmd -m standalone
启动nacos (standalone代表着单机模式运行,非集群模式)
-
先启动生产者,再启动消费者
-
此时注册中心(访问本地nacos:
localhost:8848/nacos
)上可以查看到注册的服务,用户名和密码都是 nacos
-
开始通过postman调用消费者微服务接口进行用户的增删改查
- 生产者
- 消费者
- 生产者
4、查看ribbon负载均衡效果
- (1)开启多个 生产者 实例
- 方式一:命令行启动方式(多个启动可以在控制台指定端口进行启动)
java -jar yourapp.jar --server.port=8080
-
方式二:在IDEA中复制启动配置,修改端口启动。
- 修改配置文件的端口号,使得可以在控制台复制多个应用,按指定端口启动,避免端口冲突问题
- 修改配置文件的端口号,使得可以在控制台复制多个应用,按指定端口启动,避免端口冲突问题
-
(2)将生产者应用启动3次,此时可看到nacos上有3个生产者实例
-
(3)日志参数打印:
LoggerFactory
- 导入slf4j日志包
- 获得 slf4j 日志对象,并打印日志
- 导入slf4j日志包
-
(4)开始访问 消费者 ,访问多次,可以看到 生产者实例是有负载均衡效果的
-
(5)能观察到多个提供者实例轮流被调用
5、遇到问题
- springboot与springcloud版本不一致,导致找不到类,需要更改生产者和消费者中的父工程pom.xml文件的版本
- 解决:
- 结论:注意nacos和spring boot的版本配套关系,配套不上的话,应用会起不来
- 解决:
- .yml文件在项目启动后无法识别到,编码不一致问题,需要更改IDEA编码为utf-8,更改pom.xml里设置的编码为utf-8
- 启动应用时遇到端口被占用问题
- 解决:
netstat -ano |findstr "被占用的端口号
—找到占用此端口的进程PID
tasklist |findstr "进程PID
—找到此PID对应的应用程序名
- 解决:
6、感悟
- 注册中心作为一个管理服务的平台,为项目保管地址,根据服务名找到地址。
- 消费者可以通过服务名调用微服务接口,当地址更改时,或者项目需要用到集群时,我们只需知道注册中心的服务名即可,ribbon会提供负载均衡的效果。
- ribbon的负载均衡是一个算法,实现了从地址列表中获取一个地址进行服务调用。
- springcloud中提供了负载均衡器:Ribbon
- ribbon提供了轮询(默认)和随机两种负载均衡算法
- ribbon是客户端的负载均衡,会把地址都缓存到本机再利用算法选择地址;nginx是服务端的负载均衡