zoukankan      html  css  js  c++  java
  • 【SpringCloud】 Re01

    简单理解

    接口跨服务调用 说白了 就是原来只是调用一个接口就能得到资源,现在是调用两个或者更多接口,这些接口来自不同的服务

    (从前端的角度来看依然只是调用这个接口,只是这个接口背后又去调用其他的接口了)

    没有SpringCloud提供的东西也能做到,例如使用最底层的HttpClient,是Java桌面端 和 安卓的一些通信的解决办法,同样使用于JavaWeb

    RestTemplate的使用

    1、首先任何组件都需要注册到SpringBoot中

    package cn.itcast.order;
    
    import cn.itcast.feign.clients.UserClient;
    import cn.itcast.feign.config.DefaultFeignConfiguration;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    @EnableFeignClients(clients = UserClient.class,defaultConfiguration = DefaultFeignConfiguration.class)
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
        /**
         * 创建RestTemplate并注入Spring容器
         */
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
       /* @Bean
        public IRule randomRule() {
            return new RandomRule();
        }*/
    }

    通常来说这种注册的实例,都会被集中管理到配置类编写

    第二步是调用

    package cn.itcast.order.service;
    
    import cn.itcast.feign.clients.UserClient;
    import cn.itcast.feign.pojo.User;
    import cn.itcast.order.mapper.OrderMapper;
    import cn.itcast.order.pojo.Order;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    @Service
    public class OrderService {
    
        @Autowired
        private OrderMapper orderMapper;
    
        @Autowired
        private UserClient userClient;
    
        @Autowired
        private RestTemplate restTemplate;
    
    //    public Order queryOrderById(Long orderId) {
    //        // 1.查询订单
    //        Order order = orderMapper.findById(orderId);
    //        // 2.用Feign远程调用
    //        User user = userClient.findById(order.getUserId());
    //        // 3.封装user到Order
    //        order.setUser(user);
    //        // 4.返回
    //        return order;
    //    }
    
    
    
        public Order queryOrderById(Long orderId) {
            // 1.查询订单
            Order order = orderMapper.findById(orderId);
            // 2.利用RestTemplate发起http请求,查询用户
            // 2.1.url路径
            String url = "http://userservice/user/" + order.getUserId();
            // 2.2.发送http请求,实现远程调用
            User user = restTemplate.getForObject(url, User.class);
            // 3.封装user到Order
            order.setUser(user);
            // 4.返回
            return order;
        }
    }

    提供者 & 消费者 概念

    提供者,这个服务提供给其他服务进行消费(所谓消费就是调用的意思,提供也可以是生产的意思)

    消费者,这个服务调用其他服务的接口

    对于真实的企业架构而言,会存在一个服务链,例如这样 A -> B -> C -> .... 这样

    所有提供者和消费者的概念是相对的,也可以说一个服务既可以是提供者,也可以是一个消费者

    Eureka 服务注册中心

    发现的问题:

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用RestTemplate发起http请求,查询用户
        // 2.1.url路径
        String url = "http://userservice/user/" + order.getUserId();
        // 2.2.发送http请求,实现远程调用
        User user = restTemplate.getForObject(url, User.class);
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }

    真实开发环境是有

    1测试环境DEV

    2生产环境PROD

    3预生产环境PREPROD

    等等

    而且一个服务还有可能架设服务集群,服务01服务02服务03...

    所以不能写死一个服务地址,在以前没有Eureka注册中心的时候,解决方案是配置文件 + 注释,要切换环境就找注释的环境换回来

    配置文件中记载所有的环境信息,但是这些信息只能让我们知道有哪些服务,并不知道服务的健康状态,

    所谓健康状态,就是不知道这个服务是否正常运行中的

    概念与作用

    Eureka本身也是一个服务,这个服务脱离业务需求功能,专门用于注册服务信息

    注册中心收集所有的服务信息,这些服务就可以通过Eureka来获取 业务需要的服务信息

    被注册的服务就是客户端,注册中心则是服务端

    Eureka同时还要检测服务是否正常,如何检测?就是向服务发送请求,如果服务正常响应 那就是正常的,反之则不正常

    代码片段(搭建注册中心):

    依赖:

            <!--eureka服务端-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>

    执行类配置Eureka注解:

    package cn.itcast.eureka;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @EnableEurekaServer
    @SpringBootApplication
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class, args);
        }
    }

    Eureka服务的application.yml配置信息

    eureka自身也需要注册进来,因为Eureka作为服务也可能是一个服务集群的存在

    server:
      port: 10086 # 服务端口
    spring:
      application:
        name: eurekaserver # eureka的服务名称
    eureka:
      client:
        service-url:  # eureka的地址信息
          defaultZone: http://127.0.0.1:10086/eureka

    运行Eureka之后访问地址:

    http://localhost:10086/

     

    注册服务:

    将需要被注册的服务添加Eureka的注册组件,编写注册信息即可

    所有需要注册的服务都添加上Eureka注册组件

            <!--eureka客户端依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>

    在服务的application.yml中配置注册信息:

    spring:
        application:
            name: userservice
    eureka:
      client:
        service-url:  # eureka的地址信息
          defaultZone: http://127.0.0.1:10086/eureka

    一个服务启动多个实例的操作:

     

    发现服务

    被注册的服务都有服务的名称

    spring:
        application:
            name: userservice

    名称代表了 ip地址 + 端口

    所以在远程调用的时候就可以直接使用服务名称了

    String url = "http://userservice/user/" + order.getUserId();

    为了实现负载均衡,(在视频的案例中一个服务可以开启集群,他们的名字相同,但是IP和端口会不同)

    要保证请求的调用压力都平均的分摊到集群中去,就要解决这个负载均衡的问题

    在RestTemplate上注解@LoadBalanced

    package cn.itcast.order;
    
    import cn.itcast.feign.clients.UserClient;
    import cn.itcast.feign.config.DefaultFeignConfiguration;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    @EnableFeignClients(clients = UserClient.class,defaultConfiguration = DefaultFeignConfiguration.class)
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
        /**
         * 创建RestTemplate并注入Spring容器
         */
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
       /* @Bean
        public IRule randomRule() {
            return new RandomRule();
        }*/
    }

    Ribbon 负载均衡组件

    实现流程

     

    均衡规则:

    1、轮巡调度 RoundRobin

    2、重试? Retry

    3、随机访问 RandomRule

    ZoneAvoidance规则

    https://blog.csdn.net/chengqiuming/article/details/81290016

     

     配置均衡策略:

    使用Bean实例配置

    要使用什么策略,就返回对应的策略实例

    package cn.itcast.order;
    
    import cn.itcast.feign.clients.UserClient;
    import cn.itcast.feign.config.DefaultFeignConfiguration;
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    @EnableFeignClients(clients = UserClient.class,defaultConfiguration = DefaultFeignConfiguration.class)
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
        /**
         * 创建RestTemplate并注入Spring容器
         */
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
        @Bean
        public IRule randomRule() {
            return new RandomRule();
        }
    }

    第二种配置方式使用application.yml配置

    userservice:
      ribbon:
        NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule  # 负载均衡规则

    Ribbon饥饿加载配置:

    Ribbon默认是进行懒加载的,也就是第一次调用会非常慢,以后调用才会正常速度

    在订单服务中指定用户服务饥饿加载

    也就是消费者中指定提供者配置

    ribbon:
      eager-load:
        enabled: true # 开启饥饿加载
        clients: # 指定饥饿加载的服务名称
          - userservice

    所以饥渴加载的意义在于降低首次访问的耗时,在服务启动的时候准备就绪

  • 相关阅读:
    Spring AOP功能
    EasyUI组件treegrid构建树形组织机构
    EasyUI树形表格显示Json数据
    Java 操作Redis
    Linux安装Redis、后台运行、系统自启动
    SpringBoot-Helloworld
    中小后台系统UI框架--EasyUI
    Spring注解--实现applicationContext.xml效果
    Mybatis XML映射文件
    python初学者必看学习路线图!!!
  • 原文地址:https://www.cnblogs.com/mindzone/p/15312185.html
Copyright © 2011-2022 走看看