微服务03:使用nacos添加服务
服务注册与调用入门provider(提供者)和consumer(使用者)向NacosServer提交注册,然后提供者provider会向消费者提供远端调用服务第一步:在我们创建的nacos项目中的01-sac项目中的sca-provider子项目中对其pom进行jar包的添加创建微服务项目:微服务01:架构_sayhitoloverOvO的博客-CSDN博客<?xml version="1.
provider(提供者)和consumer(使用者)向NacosServer提交注册,然后提供者provider会向消费者提供远端调用服务
服务注册
第一步:
在我们创建的nacos项目中的01-sac项目中的sca-provider子项目中对其pom进行jar包的添加
创建微服务项目:微服务01:架构_sayhitoloverOvO的博客-CSDN博客
<?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>01-sca</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca-provider</artifactId>
<dependencies>
<!--Web服务
因为在01-sca父类项目中,
spring boot和alibaba.cloud是被dependencyManagement(依赖配置管理)标签所围绕的,
所以子类在使用时仍需要重新添加jar包
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--服务的注册和发现(我们要讲服务注册到nacos)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
Q&A
问:我们在父类01-sca中已经添加过spring boot和alibaba.cloud了为什么此处还要重新添加。如果此处还需要Lombok服务,是否需要添加lombok服务?
答:因为在01-sca父类项目中,spring boot和alibaba.cloud是被dependencyManagement(依赖配置管理)标签所围绕的,所以子类在使用时仍需要重新添加jar包(但是可以不用指定版本了)
而Lombok服务已经被默认添加了,因为它在父类的pom中不被dependencyManagement所标记
第二步
修改并配置文件application.yml(或者application.properties)实现服务注册,
.yml文件
server:
port: 8081 #服务端口默认8080
spring:
application:
name: sca-provider #服务名,假如做服务注册,必须写
cloud:
nacos: #每5s向nacos server发送一次信息,标记该服务还存在
discovery: #服务的注册和发现
server-addr: localhost:8848 #nacos server
.properties文件:
server.port: 8081
spring.application.name=sca-provider
spring.cloud.nacos.discovery.server-addr=localhost:8848
注意:服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则。
第三步:
创建启动类,并定义处理请求的控制层对象和方法,关键代码如下:
@SpringBootApplication
public class ProciderApplication {
public static void main(String[] args) {
SpringApplication.run(ProciderApplication.class, args);
}
//创建一个内部类模拟执行任务
@RestController
public class ProciderController{
//@value用于动态读取配置文件中的数据
//要读取的数据写在¥{}的动态表达式中
//${}表达式中的:后面为表达式默认的数据
@Value("${server.port:8080}")
private String server;
//基于此方法实现一个祖父穿的回显
//echo,回显
//rest:一种软件架构的编码风格
//访问localhost:8081/provider/echo/necos
@GetMapping("provider/echo/{msg}")
public String doRestEcho1(@PathVariable("msg") String msg){
return server+": hello!sayhitolver"+msg;
}
}
}
第四步:
先启动nacos服务,微服务02:Nacos_sayhitoloverOvO的博客-CSDN博客
在启动启动类,检测是否服务注册成功,如图所示:
第五步:
打开浏览器,输入http://localhost:8081/provider/echo/(任意数据),然后进行访问。
nacos中对服务的监展示
服务在yml文件中对nacols进行了配置
spring:
application:
name: sca-provider #服务名
cloud:
nacos: #每5s向nacos server发送一次信息,标记该服务还存在
discovery: #服务的注册和发现
server-addr: localhost:8848 #nacos server
nacos收到服务的注册请求后,会在服务列表中创建服务:
其服务名就是项目中配置文件设定的名字,该名字不可重复
在该配置情况下,会每5s对nacos发送一个信息,标记该服务还在运行
如果超过15s没有消息被nacos接收到,就会被nacos标记为失联状态,表示该服务不可用
长期没有回联,那么就会被nacos删除服务,表示该服务已离线
调用入门
第一步:
在我们创建的nacos项目中的01-sac项目中的sca-consumer子项目中对其pom进行jar包的添加
第二步
编辑yml文件:
server:
port: 8090 #不写默认8080
spring:
application:
name: sca-consumer #假如做服务注册,必须写
cloud:
nacos: #每5s向nacos server发送一次信息,标记该服务还存在
discovery: #服务的注册和发现
server-addr: localhost:8848 #nacos server nacos服务的位置
第三步:
创建启动类,并定义处理请求的控制层对象和方法,关键代码如下:
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
//spring中不包含RestTemplate
//创建一个RestTemplate对象,并使用@Bean注解将此对象交由Spring管理
//后续我们会使用这个对象进行远端的调用服务
@Bean
public RestTemplate getrestTemplate(){return new RestTemplate();}
//创建一个内部类模拟执行任务
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
//从配置文件动态获取获取appName的数值
@Value("${spring.application.name:unkownserver}")
private String appName;
//使用对应访问的使用方式 一个A对应一个B
//http://localhost:8090/consumer/echo
@GetMapping("/consumer/echo")
public String doRestEcho() {
//调用服务提供方API(http://lip:port/path)
//1.定义要调用的API
String url = "http://localhost:8081/provider/echo/" + appName;
//2.谁去访问这个API
return getrestTemplate().getForObject(url, String.class);
}
//封装
//1)侠义:属性私有化,方法能公开就公开
//2)广义:一个系统有那些服务构成,一个服务有那些模块构成,
// 一个模块有哪些属性方法构成,
}
}
第四步:
启动浏览器访问消费者服务,通过消费者访问服务端服务
使用LoadBalancerClient,实现负载均衡的调用
消费端可以访问不同的服务端,减少服务端的并发压力
第一步:
修改sca-provider的配置文件端口,分别以8081,8082端口方式进行启动。
创建多个服务端服务,修改pom.xml文件的端口配置:
修改并发运行选项(假如没有找到这个选项我们需要通过搜索引擎基于组合查询的方法,去找到对应的解决方案,例如搜索 idea allow parallel run),如图所示:
修改 端口号,启动多个服务端服务
启动成功以后,访问nacos的服务列表,检测服务是否成功注册,如图所示:
第二步:
修改ConsumerController类,注入LoadBalancerClient对象,并添加doRestLoadBalancerClientEcho方法,然后进行服务访问.
@RestController
public class ConsumerController {
//负载均衡的远程服务调用
//之所以不需要为LoadBalancerClient 配置Bean,
//是因为Spring Boot/Cloud启动了Ribbon的入口自动配置类
//该配置类中含有LoadBalancerClient 对象,所以在spring启动时,
//jar包扫描时会扫描对应配置类,自动创建对应的bean对象实例
@Autowired
private LoadBalancerClient loadBalancerClient;
//负载均衡的使用方式 一个A对应多个B
//http://localhost:8090/consumer/echo
@GetMapping("/consumer/echo2")
public String doRestEcho2() {
//1.从注册中心获取服务实例
//2.使用RestTemplate进行服务实例调用
//使用loadBalancerClient(负载均衡).choose()方法,从服务中心获取服务实例对象
ServiceInstance instance = loadBalancerClient.choose("sca-provider");
//使用RestTemplate进行服务实例调用
String ip = instance.getHost(); //获取该服务的ip地址
int port = instance.getPort(); //获取该服务的port
//String url = "http://"+ip+":"+port+"/provider/echo/"+appName;
//%s占位符,将后方的数值按顺序填充到%s的位置
String url = String.format( "http://%s:%s/provider/echo/%s"
,ip,port,appName);
return getrestTemplate().getForObject(url, String.class);
}
}
第三步:
启动sca-consumer项目模块,打开浏览器,输入如下网址进行反复服务访问:
使用@LoadBalanced来实现负载均衡
第一步:
创建一个负载均衡的RestTemplate
利用@LoadBalanced对构建RestTemplate的方法进行修饰
@LoadBalanced注解是属于Spring,而不是Ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解,Spring会为其设置LoadBalancerInterceptor的拦截器。
//spring中不包含RestTemplate
//创建一个RestTemplate对象,并使用@Bean注解将此对象交由Spring管理
//后续我们会使用这个对象进行远端的调用服务
//不包含负载均衡功能的RestTemplate
@Bean //bean的名称是getrestTemplate()
public RestTemplate getrestTemplate(){return new RestTemplate();}
//包含负载均衡功能的RestTemplate
@LoadBalanced
@Bean //bean的名称是LoadBalancerClientRestTemplate()
public RestTemplate LoadBalancerClientRestTemplate(){return new RestTemplate();}
在需要RestTemplate实现负载均衡调用的地方进行依赖注入.例如在ConsumerController类中添加loadBalancedRestTemplate属性
//包含负载均衡功能的RestTemplate
@Autowired
private RestTemplate getrestTemplate;
//包含负载均衡功能的RestTemplate
@Autowired
private RestTemplate LoadBalancerClientRestTemplate;
Q:怎么避免两个相同类型的bean发生冲突?
A:@Autowired会先根据类型匹配bean对象,如果类型相同,那么会匹配bean对象的名称检查是否相同。在该场景中两个bean类型相同,spring会根据接下来的对象名进行匹配确定最终的唯一结果,如果结果唯一,不会报错,结果不唯一,会报错。
@GetMapping("/consumer/echo3")
public String doRestEcho3() {
String url = String.format( "http://%s/provider/echo/%s"
,"sca-provider",appName);
return LoadBalancerClientRestTemplate.getForObject(url, String.class);
}
利用包含自动均衡特性的RestTemplate,获取对应的服务("sca-provider")的ip,port。填充到url种进行方法的处理。
RestTemplate在发送请求的时候会被LoadBalancerInterceptor拦截,它的作用就是用于RestTemplate的负载均衡,LoadBalancerInterceptor将负载均衡的核心逻辑交给了loadBalancer,核心代码如下所示(了解):
更多推荐
所有评论(0)