springcloud各个组件使用demo
Eureka服务注册中心
创建三个eureka服务注册中心,分别为:
eureka-server1
spring:
application:
name: eureka-server1
server:
port: 8001
eureka:
client:
service-url:
defaultZone: http://localhost:8002/eureka/,http://localhost:8003/eureka/
fetch-registry: true
register-with-eureka: true
eureka-server2
server:
port: 8002
spring:
application:
name: eureka-server2
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka/,http://localhost:8003/eureka/
register-with-eureka: true
fetch-registry: true
eureka-server3
server:
port: 8003
spring:
application:
name: eureka-server3
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka/,http://localhost:8002/eureka/
fetch-registry: true
register-with-eureka: true
三个服务注册中心的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>
<artifactId>springboot-microservice-parent</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server3</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
其中父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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springboot-microservice-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-server1</module>
<module>eureka-server2</module>
<module>eureka-server3</module>
<module>goods</module>
<module>goods2</module>
<module>ribbon-client</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<!--根据springboot的版本指定springCloud的版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
eureka-server1、eureka-server2、eureka-server3入口代码相同,都如下:
入口类的类名不同,其他都相同:
EurekaServer1Application.java
EurekaServer2Application.java
EurekaServer3Application.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer1Application {
public static void main(String[] args) {
SpringApplication.run(EurekaServer1Application.class, args);
}
}
代码结构图
Eureka客户端
① goods微服务(扮演eureka客户端角色)
application.yaml
server:
port: 9001
spring:
application:
name: goods-server
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka/,http://localhost:8002/eureka/,http://localhost:8003/eureka/
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>
<artifactId>springboot-microservice-parent</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>goods</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
入口文件
GoodsApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class GoodsApplication {
public static void main(String[] args) {
SpringApplication.run(GoodsApplication.class, args);
}
}
测试控制器类: GetGoodsController.java
package com.example.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/goods")
public class GetGoodsController {
@Value("${server.port}")
private int port;
@RequestMapping("/getOne")
public String getOneGoods() {
return "返回一条数据"+String.valueOf(port);
}
}
②goods2微服务(扮演eureka客户端角色), 同goods微服务完全一样
goods2和goods的监听端口不同,其他都一样
goods2的
application.yaml
如下:server: port: 9002 spring: application: name: goods-server eureka: client: service-url: defaultZone: http://localhost:8001/eureka/,http://localhost:8002/eureka/,http://localhost:8003/eureka/
启动eureka-server1
eureka-server2
eureka-server3
服务端, 再启动goods
goods2
客户端后, 访问 http://localhost:8001, http://localhost:80012, http://localhost:8003 如下:
可以看到, 各个微服务都已经注册到注册中心了; 其中的微服务RIBBON-SERVER是后面要演示的负载均衡调用组件
负载均衡调用组件 Ribbon
pom.xml
一定要避开一个坑: Ribbon组件和Eureka-client不要同时引入
<?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>
<artifactId>springboot-microservice-parent</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ribbon-client</artifactId>
<dependencies>
<!-- eureka-client 已经集成了loadbalanced了,不需要在引入ribbon了,否则引起会冲突,但是启动的时候也不报这个冲突的错误,这里一定要避开这个坑!!!,否则后面调试让你头大,报错一直找不到微服务GOODS-SERVER实例 -->
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yaml
server:
port: 10001
spring:
application:
name: ribbon-server
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka/,http://localhost:8002/eureka/,http://localhost:8003/eureka/
微服务入口文件RibbonClientApplication.java
入口类上不要再标注@RibbonClient注解了
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
// @RibbonClient(name = "GOODS-SERVER") //eureka-client组件已经引入了loadbalance了, 不需要在导入ribbon组件了
public class RibbonClientApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonClientApplication.class, args);
}
}
配置文件MyRestTemplate.java
package com.example.config;
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 MyRestTemplate {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
控制器BalanceRequest.java
package com.example.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* 测试 ribbon负载均衡远程调用
*/
@RestController
@RequestMapping("/ribbon")
public class BalanceRequest {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;//根据类型,会导入我们自己定义的MyRestTemplate类
@RequestMapping("getGoods")
public String getGoods() {
//方式一:
// RestTemplate restTemplate = new RestTemplate();
// String forObject = restTemplate.getForObject("http://localhost:9001/goods/getOne", String.class);
// System.out.println(forObject);
// return forObject;
//方式二
//getServices()获取所有注册在注册中心的服务
// List<String> services = discoveryClient.getServices();
// for (String service : services) {
// System.out.println(service);
// }
//获取某个服务id下的所有信息
// List<ServiceInstance> instances = discoveryClient.getInstances("GOODS-SERVER");
// for (ServiceInstance instance : instances) {
// System.out.println(instance.getHost());
// System.out.println(instance.getPort());
// // System.out.println(instance.getMetadata());
// System.out.println(instance.isSecure());
// System.out.println(instance.getUri().toString());
// System.out.println(instance.getServiceId());
// System.out.println(instance.getScheme());
// }
// RestTemplate restTemplate = new RestTemplate();
// // String forObject = restTemplate.getForObject(instances.get(0).getUri() + "/goods/getOne", String.class);
// String forObject = restTemplate.getForObject(instances.get(1).getUri() + "/goods/getOne", String.class);
// return forObject;
//方式三: 坑!! 一直报错: loadBalancerClient.choose("goods-server")返回null, 原因就是同时导入了ribbon依赖,又有eureka-client依赖; eureka-client包中已经有了ribbon核心组件中的loadbalanced了,不需要再导入ribbon了
// System.out.println("********************");
// System.out.println(loadBalancerClient);
// System.out.println(loadBalancerClient.choose("goods-server"));
// System.out.println(loadBalancerClient.choose("GOODS-SERVER"));
// System.out.println("********************");
//
// ServiceInstance choose = loadBalancerClient.choose("GOODS-SERVER");
// ServiceInstance choose2 = loadBalancerClient.choose("goods-server");
//
// System.out.println("++++++++++++++++++++++");
// System.out.println(choose);
// System.out.println(choose2);
// System.out.println(choose.getUri().toString());
// System.out.println(choose.getHost());
// System.out.println(choose.getPort());
// System.out.println("++++++++++++++++++++++");
// ServiceInstance choose = loadBalancerClient.choose("GOODS-SERVER");
// RestTemplate restTemplate = new RestTemplate();
// String forObject = restTemplate.getForObject(choose.getUri() + "/goods/getOne", String.class);
// System.out.println(forObject);
// return forObject;
//方式四://如果不清楚eureka-client已经内置导入了loadbalance了,而再次导入Ribbon组件的话,将一直报错:找不到服务...: No instances available for GOODS-SERVER,坑!!!
String forObject = restTemplate.getForObject("http://goods-server/goods/getOne", String.class);
System.out.println(forObject);
return forObject;
}
}
代码接口图如下:
postman测试结果如下:
默认轮询的方式展示返回结果
第一次请求返回9001 | 再次请求返回9002 |
---|---|
![]() | ![]() |