服务注册与调用入门(重点)
Nacos入门必知
官网 :home
Nocas文档:https://nacos.io/zh-cn/docs/what-is-nacos.html
Nocas下载:https://github.com/alibaba/nacos/releases
Nacos的基本了解
1.模式
1.1单机模式 1.2集群模式
2.作用:
- 服务发现和服务健康监测
- 动态配置服务
- 动态DNS服务
- 服务及其元数据管理
业务描述
创建两个项目Module分别为服务提供者和服务消费者,两者都要注册到NacosServer中(这个server本质上就是一个web服务,端口默认为8848),然后服务提供者可以为服务消费者提供远端调用服务(例如支付服务为服务提供方,订单服务为服务消费方),如图所示:
生产者服务创建及注册
第一步:创建服务提供者工程(module名为sca-provider),继承parent工程(01-sca),其pom.xml里添加依赖:1.Web服务依赖 2.服务的注册和发现(我们要讲服务注册到nacos)
第二步:创建并修改配置文件application.yml(或者application.properties),实现服务注册。
注意:服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则。
server:
port: 8081
spring:
application:
name: sca-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
第三步:创建启动类,并定义处理请求的控制层对象和方法
package com.cy;
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
/**定义Controller对象(这个对象在spring mvc中给他的定义是handler),
* 基于此对象处理客户端的请求*/
@RestController
public class ProviderController{
//@Value默认读取项目配置文件中配置的内容
//8080为没有读到server.port的值时,给定的默认值
@Value("${server.port:8080}")
private String server;
//http://localhost:8081/provider/echo/tedu
@GetMapping("/provider/echo/{msg}")
public String doRestEcho1(@PathVariable String msg){
return server+" say hello "+msg;
}
}
}
第四步:启动启动类,然后刷先nacos服务,检测是否服务注册成功
第五步:打开浏览器,输入http://localhost:8081/provider/echo/msa,然后进行访问。
消费者服务发现及调用
第一步:创建服务消费者(module名为sca-consumer),继承parent工程(01-sca),添加依赖
第二步:修改配置文件application.yml,关键代码如下:
server:
port: 8090
spring:
application:
name: sca-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848 #从哪里去查找服务
第三步:创建启动类并实现服务消费,关键代码如下:
package com.cy;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
@RestController
public class ConsumerController{
@Value("${spring.application.name}")
private String appName;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/doRestEcho1")
public String doRestEcho01(){
String url = "http://localhost:8081/provider/echo/"+appName;
System.out.println("request url:"+url);
return restTemplate.getForObject(url, String.class);
}
}
}
第五步:启动消费者服务,并在浏览器输入http://localhost:8090/consumer/doRestEcho1地址进行访问,假如访问成功会出现,如图所示效果:
小节面试分析
为什么要将服务注册到nacos?(为了更好的查找这些服务)
在Nacos中服务提供者是如何向Nacos注册中心(Registry)续约的?(5秒心跳)
对于Nacos服务来讲它是如何判定服务实例的状态?(检测心跳包,15,30)
服务启动时如何找到服务启动注册配置类?(NacosNamingService)
服务消费方是如何调用服务提供方的服务的?(RestTemplate)
服务负载均衡设计及实现(重点)
一个服务实例可以处理请求是有限的,假如服务实例的并发访问比较大,我们会启动多个服务实例,让这些服务实例采用一定策略均衡(轮询,权重,随机,hash等)的处理并发请求,在Nacos中服务的负载均衡(Nacos客户端负载均衡)是如何应用的?
第一步:修改ConsumerController类,注入LoadBalancerClient对象,并添加doRestLoadBalancerClientEcho方法,然后进行服务访问.
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/consumer/doRestEcho02")
public String doRestEcho02(){
ServiceInstance serviceInstance = loadBalancerClient.choose("sca-provider");
String url = String.format("http://%s:%s/provider/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName);
System.out.println("request url:"+url);
return restTemplate.getForObject(url, String.class);
}
}
第二步:修改sca-provider的配置文件端口,分别以8081,8082端口方式进行启动。
启动成功以后,访问nacos的服务列表,检测服务是否成功注册,如图所示:
这里多个实例并发提供服务的方式为负载均衡,这里的负载均衡实现默认是因为Nacos集成了Ribbon来实现的,Ribbon配合RestTemplate,可以非常容易的实现服务之间的访问。Ribbon是Spring Cloud核心组件之一,它提供的最重要的功能就是客户端的负载均衡(客户端可以采用一定算法,例如轮询访问,访问服务端实例信息),这个功能可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡方式的服务调用。
@LoadBalanced(简单来说负载均衡时添加这个注解)
当使用RestTemplate进行远程服务调用时,假如需要负载均衡,可以在RestTemplate对象构建时,使用@LoadBalanced(性能上不如手写)对构建RestTemplate的方法进行修饰,例如在ConsumerApplication中构建RestTemplate对象:
@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate(){
return new RestTemplate();
}
在需要RestTemplate实现负载均衡调用的地方进行依赖注入.例如在ConsumerController类中添加loadBalancedRestTemplate属
@Autowired
private RestTemplate loadBalancedRestTemplate;
接下来,可以在对应的服务端调用方的方法内,基于RestTemplate借助服务名进行服务调用。RestTemplate在发送请求的时候会被LoadBalancerInterceptor拦截,它的作用就是用于RestTemplate的负载均衡,LoadBalancerInterceptor将负载均衡的核心逻辑交给了loadBalancer
@LoadBalanced注解是属于Spring,而不是Ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解,Spring会为其设置LoadBalancerInterceptor的拦截器。