微服务服务调用

1.在IDEA中运行Nacos(001拓展)

1.1编辑配置信息

 选择shell script(shell脚本)

script path(脚本路径)--- nacos目录下bin目录下的startup.cmd命令文件 

CMD文件的专业名称叫链接器配置文件,是存放链接器的配置信息的,我们简称为命令文件

script options(脚本选项)需要执行的命令

 

点击运行启动nacos

服务注册中心 nacos启动成功

测试nacos  http://localhost:8848/nacos

关闭nacos ctrl+c  需要等一会才能关闭

 2.服务之间的调用

 2.1提供方服务(sca-provider)注册

2.1.1.添加nacos服务的注册和发现依赖

 根据官网提供:Nacos Spring 快速开始icon-default.png?t=N7T8https://nacos.io/zh-cn/docs/quick-start-spring.html

  <dependencies>
    <!-- web服务依赖 -->
        <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>

2.1.2.创建并修改配置文件application.yml(或者application.properties),实现服务注册

 

server:
  port: 8082  #服务端口
spring:
  application:
    name: sca-provider #服务名 不能重复 map集合k-value(value可以是一个集合)中的k    错误代码503服务不可用 检查nacos
  cloud:
    nacos: #服务
      discovery: #服务的注册和发现
        server-addr: localhost:8848 #nacos server

2.1.3创建启动类,并定义处理请求的控制层对象和方法:

package com.cy;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
    @RestController
    public class  providerController{
        //动态赋值xml文件里的信息。配置默认值8080以防null时报错
        @Value("${server.port:8080}")
        private String server;
 /*     echo:回显的意思
        rest:一种软件架构编码风格
        访问:http://localhost:8081/provider/echo/nacos         */
        @GetMapping("/provider/echo/{msg}")
        //兼容java8以下的版本 必须注明@PathVariable("msg")与请求路径的msg相同 变量则可以自定义
        public String doRestEcho1(@PathVariable("msg") String msg1){
            return server +"hello"+msg1;
        }
    }
}

 控制层代码可以写在控制层里,但这里这是简单的一个入门案例我就直接写在启动类里了。

2.1.4测试提供方服务

注意:先启动Nacos在启动启动类,要不会报错

测试   http://localhost:8082/provider/echo/msa

 证明我们的提供方服务创建成功

2.2消费方(sca-consumer)服务注册

 2.2.1.添加依赖和提供方一样

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

2.2.2.创建并修改配置文件application.yml(或者application.properties),实现服务注册

 

server:
  port: 8090 #默认8090
spring:
  application:
    name: sca-consumer #假如做服务注册,必须写
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos

2.2.3.创建消费方启动类并写入

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);
        }
    }
}

注意:先启动Nacos在启动启动类,要不会报错,可以看到现在消费方服务和提供方服务均已经启动。

 测试消费方调用提供方

2.3负载均衡方法

如果一个提供方只能抗住10w的并发量,而消费方有100w的并发请求来调用提供方,这时则需要用到负载均衡的方法。所以至少得运行十个提供方

2.3.1 编辑ConsumerApplication启动类

      思路  1.从注册中心获取服务实例   2.基于restTemplate进行服务实例调用

package com.cy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

//服务消费方启动类
//当客户端向服务方发起请求时,服务消费方调用服务提供方的API进而获取服务提供方的数据
//例如我们访问一个订单模块数据;例如我的订单
//订单模块中还要呈现商品信息(成为提供方)  我调用consumer调用provider
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    /*
    构建RestTemplate对象,并将此对象交给spring管理,
     * 后续我们会通过此对象进行远程服务调用
     */
    @Bean//也是交给spring容器去管理 跨进程使用该对象
    //第三方整合用@Bean
    //spring中有缓存 加了bean只需调用一次。不加就调用一次new一次对象
    public RestTemplate restTemplate(){
        return  new RestTemplate();
    }
    
    @RestController
    public class ConsumerController{
        @Autowired//负载均衡客户端对象 调用
        private LoadBalancerClient loadBalancerClient;

        @Autowired
        private RestTemplate restTemplate;

        @Value("${spring.application.name}")
        private String appName;

    @GetMapping("/consumer/doRestEcho1")
    public String doRestEcho1(){
        //调用服务提供方API(不只是类和接口也包含请求路径)
        //
        String url="http://localhost:8081/provider/echo/"+appName;
        return restTemplate.getForObject(url,String.class);
    }
    //负载均衡方式调用
    @GetMapping("/consumer/doRestEcho2")
    public String doRestEcho2(){
        //1.从注册中心获取服务实例
        //2.基于restTemplate进行服务实例调用
        //服务实例instance
        ServiceInstance instance = loadBalancerClient.choose("sca-provider");
        String ip = instance.getHost();
        int port = instance.getPort();
      //  String url = "http://"+ip+":"+port+"/provider/echo/"+appName;
        //格式化
        String url = String.format("http://%s:%s/provider/echo/%s", ip,port,appName);
        //服务调用 基于服务名去查找实例
        return restTemplate.getForObject(url,String.class);
    }

    }

}

2.3.2 启动两个服务器

然后修改配置文件里的端口号。

 

 此时已经开启了两个提供方服务器

 测试:如果可以像我这样说明服务器已经在负载均衡了(默认为负载均衡中的轮询策略

 

注意:

服务启动时会向nacos发送心跳包 五秒一次 ,十五秒没收到就标识你为 非健康状态  

三十秒左右收不到心跳包 就确认你已经下线 就把你删掉服务,所以当我们关闭启动类时服务还暂存在Nacos中。

 

2.4代码优化

package com.cy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 服务消费方对象的启动类
 * 业务描述:
 * 当客户端(浏览器,手机app)向服务消费方发起请求时,
 * 服务消费方调用服务提供方的api,进而获取服务提供方
 * 的数据。
 * 例如:
 * 我们访问一个订单模块数据(例如我的订单),订单模块中
 * 还要呈现商品信息。
 */
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    /**
     * 构建RestTemplate对象,并将此对象交给spring管理,
     * 后续我们会通过此对象进行远程服务调用
     * @return
     */
    @Bean
    //@Bean("rt")
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    @Bean
    @LoadBalanced
    public RestTemplate loadBalancerRestTemplate(){
        return new RestTemplate();
    }

    @RestController
    public class ConsumerController{
        /**
         * 负载均衡客户端对象
         */
      @Autowired
      private LoadBalancerClient loadBalancerClient;

      @Autowired
      private RestTemplate restTemplate;

      @Autowired
      private RestTemplate loadBalancerRestTemplate;

      @Value("${spring.application.name}")
      private String appName;

      //http://ip:port/consumer/doRestEcho1
      @GetMapping("/consumer/doRestEcho1")
      public String doRestEcho1(){
        System.out.println("==doRestEcho1()==");
        //调用服务提供方API(http://ip:port/path)
        //1.定义要调用的API
        String url=
        "http://localhost:8081/provider/echo/"+appName;
        //2.谁去访问这个API? restTemplate;
        return restTemplate
                .getForObject(url,
                        String.class);
      }
        /**
         * 负载均衡方式调用
         * @return
         */
        @GetMapping("/consumer/doRestEcho2")
        public String doRestEcho2 (){
            //1.从注册中心获取服务实例
            ServiceInstance instance =
                    loadBalancerClient
                    .choose("sca-provider");
            //2.基于RestTemplate进行服务实例调用
            String ip=instance.getHost();//ip
            int port=instance.getPort();//port
            //String url= "http://"+ip+":"+port+"/provider/echo/"+appName;
            String url=String.format(
                    "http://%s:%s/provider/echo/%s",
                     ip,port,appName);
            return restTemplate.getForObject(
                    url, String.class);
        }
        @GetMapping("/consumer/doRestEcho3")
        public String doRestEcho3(){
            //定义url
            String url=
            String.format("http://sca-provider/provider/echo/%s", appName);
            //服务调用
            return loadBalancerRestTemplate.getForObject(
                    url, String.class);
        }
    }
}

//browser->provider
//browser->consumer
//browser-(url)->consumer-(url)->provider

2.5 代码优化部分

 

3.面试分析 

为什么要将服务注册到nacos?(为了更好的查找这些服务)
在Nacos中服务提供者是如何向Nacos注册中心(Registry)续约的?(5秒心跳)
对于Nacos服务来讲它是如何判定服务实例的状态?(检测心跳包,15,30)
服务启动时如何找到服务启动注册配置类?(NacosNamingService)
服务消费方是如何调用服务提供方的服务的?(RestTemplate)
 

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值