SpringCloud笔记02 Ribbon负载均衡
coconutnut

https://blog.csdn.net/ThinkWon/article/details/103729080

user-service模块

  1. 创建user-service模块
  2. pom.xml添加依赖
  3. 配置application.yml
  4. 实体类和响应类
  5. 控制器
  6. Service接口和实现类

ribbon-service模块

  1. 创建ribbon-service模块
  2. pom.xml添加依赖
  3. 配置application.yml
  4. @LoadBalanced注解赋予RestTemplate负载均衡的能力
  5. 实体类和响应类
  6. 控制器

负载均衡功能演示

  1. 开启服务

8001开一个Server(上次的模块)

8201、8202各开一个Service

这次是同样的配置文件,2个端口各开一个,改Active profiles

上次是不同的配置文件,开在不同的端口,用Override parameters

8301开Ribbon Service

  1. 调用接口进行测试

8201

8202

DEBUG:运行后没有注册

启动几个服务后

但是浏览器中查看

发现又忘记加@EnableDiscoveryClient了

重启

还是没有注册上

尝试1

https://blog.csdn.net/yangyongming_888/article/details/83859092

说是依赖带starter和不带starter

但是看了下三个pom.xml中都是带starter的

再比较一下依赖

源码-eureka-server

1
2
3
4
 <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

项目-eureka-server

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

源码-ribbon-service

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

项目-ribbon-service

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

源码-user-service

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

项目-user-service

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

一样,看来不是这个问题

尝试2

关闭server,直接启动service,发现也启动了,并没有报错

但是上次的client如果在没开service的时候启动会报

1
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused (Connection refused)

所以也许根本就没有连上服务器?

难道是yml没有生效?

1
mvn -X clean install

没用

https://segmentfault.com/q/1010000012008825

有说是yml的缩进问题

看了一下上次可以注册的服务的yml

这次的

发现注册的true是白色的

提示

确实有问题

把pom.xml中spring-cloud-starter-netflix-eureka-client的依赖注释的,依然能启动

https://ask.csdn.net/questions/719186

有说加版本号的

没用

想想和上次创建的区别,上次是在创建模块的时候通过Spring Initializer选择了Eureka Discovery Client的依赖

试试创建一个user-service2,创建的时候选上Eureka Discovery Client

把application.yml的内容复制过去,可以解析

它的依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

user-service的依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

没差啊

那难道是依赖没有导入

看下Maven

???

难道真是没有版本号

而且为什么前面的模块也都是红的,那是怎么运行成功的 迷惑

点进去看一下

也许只是部分冲突所以还能运行?

总之先加个版本号

加了之后还是unknown

重启也是

发现右下角在下载

下完之后变成了Maven中变成了2.2.2.RELEASE

激动地搓搓手

成功!

注册上了

给ribbon-service也加个版本

加在properties里似乎不管用,暂时都加在dependency里好了

DEBUG:调用接口调试的问题

出现Whitelabel Error Page

报错是

1
2
3
4
5
2020-04-09 21:37:37.483 ERROR 3503 --- [nio-8301-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.cloud.netflix.ribbon.RestClientRibbonConfiguration] with root cause

java.lang.ClassNotFoundException: com.netflix.niws.client.http.RestClient
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_241]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_241]

找不到com.netflix.niws.client.http.RestClient

看一下依赖

似乎有很多冲突

https://stackoverflow.com/questions/50675895/java-lang-classnotfoundexception-com-netflix-discovery-eurekaclientconfig

You should select only Eureka Server using spring Initializr while creating eureka server project.

试一下重新创建

就没有冲突了

运行

1
java.lang.ClassNotFoundException: com.netflix.niws.client.http.RestClient

怎么还是找不到???

把ribbon的依赖挪到前面来优先找呢?

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

还是不行

再翻一下报错发现是getUser函数的问题

在里面打印一下路径

1
2
3
4
5
@GetMapping("/{id}")
public Result getUser(@PathVariable Long id) {
System.out.println("【getUser中】userServiceUrl:"+userServiceUrl);
return restTemplate.getForObject(userServiceUrl + "/user/{1}", Result.class, id);
}

输出如下

1
【getUser中】userServiceUrl:http://user-service

没有localhost?

浏览器访问一下

找不到 user-service 的服务器 IP 地址

上次好像注册过ip来着

但是注册是hostname

这里应该是要通过服务名称访问2个Service,似乎不一样

试试直接用localhost加端口访问

单个节点的服务没有问题

那应该就是在注册服务名称到ip的转换上出了问题

https://bbs.csdn.net/topics/392414113

1
2
@Autowired
private RestTemplate restTemplate;

改成

1
2
@Autowired
private RestOperations restTemplate;

不行

https://www.liangzl.com/get-article-detail-174951.html

对比了一下这个教程,也没找到问题

网页上的错误信息是

1
2
There was an unexpected error (type=Internal Server Error, status=500).
Failed to process import candidates for configuration class [org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.cloud.netflix.ribbon.RestClientRibbonConfiguration

似乎是注释的问题

很久很久以后

试试源码能不能跑

漫长的下载依赖

第二天

运行源码

没有问题

而且Maven一个都没红

对比一下依赖版本

源码eureka-server

项目eureka-server

spring-cloud-starter-netflix-eureka-server版本不一样

diff一下pom文件

1
2
3
4
5
6
7
8
9
10
11
12
8c8
< <version>2.2.2.RELEASE</version>
---
> <version>2.2.6.RELEASE</version>
11c11
< <groupId>com.jourwon.springcloud</groupId>
---
> <groupId>com.coconutnut</groupId>
19c19
< <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
---
> <spring-cloud.version>Hoxton.SR3</spring-cloud.version>

一个是spring-boot-starter-parent的版本不一样

一个是spring-cloud的版本不一样

修改spring-cloud的版本,Maven的冲突就没有了

于是把其它pom的版本也改了

spring-boot-starter-parent的版本暂时没改,保持最新

启动

注册上了

又崩了

但是这次控制台没有Error了

错误信息变成了

1
2
There was an unexpected error (type=Internal Server Error, status=500).
No instances available for user-service

单独访问http://localhost:8201/user/1或者http://localhost:8202/user/1都是可以的

https://blog.csdn.net/choice_of_door/article/details/85467105

按照这个加了个依赖

(源码里并没有 但是可以正常运行,为什么呢?MARK (笔记03中解决))

1
2
3
4
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-eureka</artifactId>
</dependency>

成功了!

嗷!

问题总结

都是版本的坑

创建时用Spring Initializer加还是后期在pom.xml中加不重要

但最好和教程保持一致

至少检查右边Maven栏中没有红线

总结