step04day02微服务之负载均衡

1.微服务入门案例

        微服务是把许多单个服务和功能分为各个小单位组合起来,通过配置中心分配服务的调用,从而优化网络服务,也使得用户的服务更加便捷和安全。

1.1 项目结构图

说明:通过nacos注册中心,管理服务的三方

 1.2服务提供方

@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class,args);
    }
    @RestController
    public class ProviderController {
        @Value("${server.port:8080}")
        private String server;
        @GetMapping(value = "/provider/echo/{msg}")
        public String doEcho(@PathVariable String msg){
            return server+"say:Hello nacos Discovery"+msg;

        }
    }
}

1.3  服务消费方

@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    /**创建RestTemplate */
    @Bean
    @LoadBalanced
    public RestTemplate loadBalanceRestTemplate(){
        return new RestTemplate();
    }

    @RestController
    public class ConsumerController{

        @Autowired
        private RestTemplate loadBalanceRestTemplate;
        
        //负载均衡客户端对象(基于此对象可以从nacos中获取服务列表,并且基于一定的算法)
        //从列表中获取一个服务实例

        @Autowired
        public LoadBalancerClient loadBalancerClient;


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

        @GetMapping("/consumer/doRestEcho1/")
        public String doRestEcho1(){
             //调用谁?sca-provider中的一个Url
            String url1="http://localhost:8081/provider/echo/"+appName;
            String url2="http://localhost:8082/provider/echo/"+appName;
            String url3="http://localhost:8080/provider/echo/"+appName;
            String urls[]=new String[]{url1,url2,url3};
           //随机获取一个小于urls数组长度的整数
            int n=new Random().nextInt(3);
            System.out.println("n="+n);
            //如何调用?
            String result= restTemplate.getForObject(urls[n], String.class);
            //return server +"say Hello"+ msg;
            return result;
        }

    }
}

2 .服务消费方调用提供方

通过依赖注解的方式,服务方会调用启用的多个消费方中的一个,调用策略采用的时默认的轮询

关键代码:

 /**@Autowired 注解描述属性时,会告诉Spring框架,要优先按照属性类型进行对象的查找和注入
         * 假如此类对象存在多个,此时还会按照属性名进行查找和比对,有相同的直接注入DI
         * 没有的则出错 ,当然也可以在属性上添加@Qualifiler(”bean的名字“)指定要注入的对象*/
        @Autowired
        private RestTemplate loadBalanceRestTemplate;
        //负载均衡客户端对象(基于此对象可以从nacos中获取服务列表,并且基于一定的算法)
        //从列表中获取一个服务实例
        @Autowired
        public LoadBalancerClient loadBalancerClient;

2.1 手动写负载均衡

手写负载均衡的方式在于对多个服务地址封装进数组,选取数组中的一个元素进行调用

@GetMapping("/consumer/doRestEcho1/")
        public String doRestEcho1() {
            //调用谁?sca-provider中的一个Url
            String url1="http://localhost:8081/provider/echo/"+appName;
            String url2="http://localhost:8082/provider/echo/"+appName;
            String url3="http://localhost:8080/provider/echo/"+appName;
            String urls[]=new String[]{url1,url2,url3};
           //随机获取一个小于urls数组长度的整数
            int n=new Random().nextInt(3);
            System.out.println("n="+n);
            //如何调用?
            return result= restTemplate.getForObject(urls[n], String.class);
}

2.2   1.0升级版写法:RestTemplate+LoadbalancerClient

使用@LoadbalancerClient能动态拼接服务的端口号,以及服务方法名,组合形成网址中的参数

@GetMapping("/consumer/doRestEcho2/")
        public String doRestEcho2(){
            String serverId ="sca-provider";//这个名字要在nacos的服务列表中
            ServiceInstance choose =loadBalancerClient.choose(serverId);
            String ip=choose.getHost();
            int port =choose.getPort();
            //String url= "http://"+ip+":"+port+"/provider/echo/"+msg;
            String url =String.format("http://%s:%s/provider/echo/%s",ip,port,appName);
            return restTemplate.getForObject(url,String.class);
        }

2.3    1.1升级版写法RestTemplate+@LoadBalanced

@LoadBalanced简化了ip请求端口号和方法名,使对象拼接到网页之中

#修改配置的restTemplate
    @Bean
    @LoadBalanced
    public RestTemplate loadBalanceRestTemplate(){
        return new RestTemplate();
    }

#修改注解
@Autowired
        private RestTemplate loadBalanceRestTemplate;


@GetMapping("/consumer/doRestEcho3/")
        public String doRestEcho3(){
            String serverId ="sca-provider";
            String url =String.format("http://%s/provider/echo/%s",serverId,appName);
            return loadBalanceRestTemplate.getForObject(url,String.class);
        }

总结:消费方调用提供方运用了spring框架的思想,将其中的资源交给spring框架进行管理,运用bean注解的方式将资源交给sprin管理。

2.4  2.0升级版写法:@EnableFeignClients+@FeignClient

1.在消费方添加openfeign依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.在启动类添加@EnableFeginClients注解

@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {…}

3.创建一个接口文档,定义Http请求API,基于此API借助OpenFeign访问远端服务

@FeignClient(name="sca-provider")//sca-provider为服务提供者名称
interface RemoteProviderService{
    @GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
    public String echoMessage(@PathVariable("string") String string);
}

说明:,@FeignClient描述的接口底层会为其创建实现类。

4.创建FeignConsumerController中并添加feign访问


@RestController
@RequestMapping("/consumer/ ")
public class FeignConsumerController {
    @Autowired
    private RemoteProviderService remoteProviderService;
    /**基于feign方式的服务调用*/
    @GetMapping("/echo/{msg}")
    public String doFeignEcho(@PathVariable  String msg){
        //基于feign方式进行远端服务调用(前提是服务必须存在)
        return remoteProviderService.echoMessage(msg);
    }
}

5.启动消费者服务,在浏览器中直接通过feign客户端进行访问

3.负载均衡相关机制及知识点

3.1 并行运行多线程

 勾选允许多线程

 3.2 线程交给nacos管理

 3.3 心跳提交底层

public class TimerTests {
    public static void main(String[] args) {
        //通过timer对象可以启动一个定时任务
        Timer timer=new Timer();
        //基于timer对象启动并执行任务
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(System.currentTimeMillis());
            }
        },1000,1000);
    }
}

4.面试相关知识点

  • 在Nacos中服务提供者是如何向Nacos注册中心(Registry)续约的?(5秒心跳)
  • 对于Nacos服务来讲它是如何判定服务实例的状态?(检测心跳包,15,30)
  • 服务消费方是如何调用服务提供方的服务的?(RestTemplate)
  • @Bean注解的作用?(一般用于配置类内部,描述相关方法,用于告诉spring此方法的返回值要交给spring管理,bean的名字默认为方法名,假如需要指定名字可以@Bean(“bean的名字”),最多的应用场景是整合第三方的资源-对象)
  • @Autowired注解的作用?(此注解用于描述属性,构造方法,set方法等,用于告诉spring框架,按找一定的规则为属性进行DI操作,默认按属性,方法参数类型查找对应的对象,假如只找到一个,则直接注入,类型多个时还会按照属性名或方法参数名进行值的注入,假如名字也不同,就出报错.)
  • Ribbon 是什么?(Netflix公司提供的负载均衡客户端,一般应用于服务的消费方法)
  • Ribbon 可以解决什么问题? (基于负载均衡策略进行服务调用, 所有策略都会实现IRule接口)
  • Ribbon 内置的负载策略都有哪些?(8种,可以通过查看IRule接口的实现类进行分析)
  • @LoadBalanced的作用是什么?(描述RestTemplate对象,用于告诉Spring框架,在使用RestTempalte进行服务调用时,这个调用过程会被一个拦截器进行拦截,然后在拦截器内部,启动负载均衡策略。)
  • 我们可以自己定义负载均衡策略吗?(可以,基于IRule接口进行策略定义,也可以参考NacosRule进行实现)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值