NACOS+RestTemplate+DiscoveryClient实现服务的注册与发现
-
- 开发环境
- 更多干货
- 需求
- 分析
- 使用
-
- User-service
-
- 目录结构
- pom.xml 依赖
- application.propertice配置文件
- 编写HelloController 类
- 编写UserServiceApplication 启动类
- Order-service
-
- 目录结构
- pom.xml 依赖
- application.yml配置文件
- 编写HelloController 类
- 编写UserServiceApplication 启动类
- 测试
开发环境
基于:IntelliJ IDEA
、Maven构建工具
、JDK1.8
、SpringBoot 2.3.4
、SpringCloud H或R
编写。
官人如需使用 IDEA 请阅读教程:IntelliJ IDEA
官人如需使用 Maven 请阅读教程:Maven 构建工具的下载与安装
更多干货
请参考:《穿越 Java 之 语法基础篇》 系列文章
请参考:《穿越 Java 之 Web基础篇 》系列文章
请参考:《穿越 Java 之 开发必备框架篇 》 系列文章
请阅读:《穿越 Java 之 SpringBoot》系列文章
请阅读:《穿越 Java 之 SpringCloud》 系列文章
需求
实现 user 服务 对 order 服务 进行远程调用 使用NACOS+RestTemplate+DiscoveryClient实现服务的注册与发现)。
分析
-
在springcloud 要考虑的是:user要想调用order 必须要知道 它的一个IP 端口 路径进行调用.
-
但是存在一个问题就是 假如还有其他的模块 就会再维护一份url地址 ,干很多重复的工作。如下图:
-
所以在微服务的场景下我们要先去考虑
服务的注册与发现
,如下图:
-
接下来就是选择 NACOS 进行服务的注册
-
NACOS 他自己做的服务注册的业务代码。我们需要做的事是
-
引入依赖
-
准备环境 即需要一个 nacos 服务环境, 我们需要下载并启动。
-
GitHup下载地址:https://github.com/alibaba/nacos
-
通过源码进行启动:将文件路径copy 然后在idea ->file -> open打开文件即可。还可以使用cmd打开二进制文件。
-
然后进行启动访问:http://localhost:8848/nacos
即可查看nacos的图形化界面:默认用户名和密码是nacos。可以查看有多少个服务注册到nacos上了。
使用
User-service
目录结构
pom.xml 依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version><relativePath/> </parent><groupId>com.example</groupId><artifactId>user-service</artifactId><version>0.0.1-SNAPSHOT</version><name>user-service</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--为项目 整合nacos-client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies>
<!--为项目整合spring cloud--><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.SR3</version><type>pom</type><scope>import</scope></dependency><!--为项目整合spring cloud alibaba--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>0.9.0.RELEASE</version><type>pom</type><scope>import</scope></dependency><!--为项目整合spring cloud netflix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-netflix-dependencies</artifactId><version>2.1.3.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
application.propertice配置文件
#端口
server.port=8090
#服务的名称
spring.application.name=user-service
#告诉我们的项目 nacos的地址是什么,方便注册
spring.cloud.nacos.discovery.server-addr=localhost:8848
编写HelloController 类
- @Slf4j --> 日志的输出
- DiscoveryClient --> spring cloud 提供的一个工具类可以用来做服务的发现。
- RestTemplate -->可以访问远程Http服务
package com.example.userservice.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.util.List;import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;@RestController
@Slf4j
public class HelloController {
@GetMapping("/hello")public String hello(){
return "Hello Spring Cloud";}@Autowiredprivate RestTemplate restTemplate;@Autowired//spring cloud 提供的一个工具类可以用来做服务的发现。DiscoveryClient在spring cloud Commons包下,此包下有很多实现.private DiscoveryClient discoveryClient;@GetMapping("/test1")public String test1(){
//分析1:没有url地址就需要写下面这种硬编码的过程
// restTemplate.getForObject("http://localhost:8085/order/query")//分析2:根据服务的名称,获得一个集合list ,这个list就是关于这个服务url相关的内容。
// List<ServiceInstance> instances = discoveryClient.getInstances("order-service");
// return instances;//分析3:通过 RestTemplate DiscoveryClient来实现服务的发现和调用 找到第一个uri
// List<ServiceInstance> instances = discoveryClient.getInstances("order-service");
// String uri= instances.stream().map(instance ->
// instance.getUri().toString() + "/order/query").findFirst().orElseThrow(()->new IllegalStateException("找不到对应实例"));
// log.info("获取到的URL地址是:"+uri);
// return this.restTemplate.getForObject(url,String.class);// 通过 RestTemplate DiscoveryClient来实现服务的发现和调用 +使用手动实现负载均衡List<ServiceInstance> instances = discoveryClient.getInstances("order-service");//将其转换成一个list集合//先把所有的URI获取到,然后筛选出一个来。List<String> uris = instances.stream().map(instance ->instance.getUri().toString() + "/order/query").collect(Collectors.toList());//拿到uris后 手动实现负载均衡。int index = ThreadLocalRandom.current().nextInt(uris.size());//随机获取一个下标String uri = uris.get(index);//得到具体的uri.log.info("获取到的URL地址是:"+uri);return this.restTemplate.getForObject(uri,String.class);}
}
编写UserServiceApplication 启动类
- 注册了一个Bean -->RestTemplate
package com.example.userservice;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);}@Beanpublic RestTemplate restTemplate(){
return new RestTemplate();}
}
Order-service
目录结构
pom.xml 依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version><relativePath/> </parent><groupId>com.example</groupId><artifactId>user-service</artifactId><version>0.0.1-SNAPSHOT</version><name>user-service</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--为项目 整合nacos-client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies>
<!--为项目整合spring cloud--><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.SR3</version><type>pom</type><scope>import</scope></dependency><!--为项目整合spring cloud alibaba--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>0.9.0.RELEASE</version><type>pom</type><scope>import</scope></dependency><!--为项目整合spring cloud netflix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-netflix-dependencies</artifactId><version>2.1.3.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
application.yml配置文件
server:port: 8096
#告诉我们的项目 nacos的地址是什么,方便注册localhost:8848
spring:cloud:nacos:discovery:server-addr: localhost:8848application:name: order-service
编写HelloController 类
package com.example.orderservice.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(path = {
"/order"},method = {
RequestMethod.GET})
@Slf4j
public class DemoController {
@GetMapping("/query")public String demo(){
log.info("我被访问了!");return "已查询出数据";}
}
编写UserServiceApplication 启动类
package com.example.orderservice;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);}
}
测试
- 首先开启通过不同端口三个order服务1个user服务,以我的为例开启了8094,95,96的order服务和一个8090的用户服务。
- 访问:http://192.168.148.1:8848/nacos/
- 进入nacos界面可以看到注册进去的服务。
- 最后访问http://localhost:8090/test1测试调用
- 每个端口访问的次数不同