【SpringCloud】02 搭建springcloud微服务项目,服务治理组件nacos,负载均衡ribbon,远程调用Openfeign

news2024/12/25 9:18:17

文章目录

  • 搭建springcloud微服务项目
    • 1. 微服务父工程
    • 2. 创建子模块-shop-common
    • 3. 创建子模块--shop-product
    • 4. 创建子模块--shop-order
  • 服务治理组件
    • 1. 如何使用nacos
    • 2. 微服务客户端连接到nacos注册中心
    • 3. 消费端如何通过nacos调用提供者
  • 负载均衡
    • 1. 自己控制负载均衡
    • 2. ribbon完成负载均衡
      • 2.1 如何使用ribbon
      • 2.2 自定义负载均衡策略
  • 远程调用组件-Openfeign
    • 1. 概述
    • 2. 如何使用openfeign组件

搭建springcloud微服务项目

技术栈:

  1. springcloud-alibaba
  2. mybatis-plus 持久性框架
  3. mysql数据库5.7以上
  4. springboot来搭建每个微服务。

1. 微服务父工程

在这里插入图片描述
把其他的全删掉,只保留一个pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.aaa</groupId>
    <artifactId>qy156-shop-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>qy156-shop-parent</name>
    <description>Demo project for Spring Boot</description>
    <!--定义版本号-->
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF- 8</project.reporting.outputEncoding>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
    </properties>
    <!--jar得管理 它只负责jar得管理不负责下载-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2. 创建子模块-shop-common

把其他模块公共得代码放入到该模块。- - -实体 工具类

在这里插入图片描述

  <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.0</version>
        </dependency>
    </dependencies>

定义相关得实体类

@Data
@TableName(value = "shop_order")
public class Order {
    //订单id
    @TableId
    private Long oid;
    //用户id
    private Integer uid;
    //用户名
    private String username;
    //商品id---购买时99---->活动结束后199
    private Long pid;
    //商品得名称
    private String pname;
    //商品得价格
    private Double pprice;
    //购买得数量
    private Integer number;
}

@Data
@TableName("shop_product")
public class Product {
    @TableId
    private Long pid;
    private String pname;
    private Double pprice;
    private Integer stock;
}

3. 创建子模块–shop-product

关于商品表操作的接口
在这里插入图片描述

	<dependencies>
          <!--引入公共模块-->
        <dependency>
            <groupId>com.aaa</groupId>
            <artifactId>shop-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <!--引入springboot-starter-web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

配置文件

# 定义端口号 [8001~8009 未来方便搭建集群]
server:
  port: 8001

#数据源得信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=Asia/Shanghai
    username: root
    password: root

# mybatis打印日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

dao接口

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起
 * @create: 2022-11-17 16:22
 **/
public interface ProductDao extends BaseMapper<Product> {
}

service代码

@Service
public class ProductService implements IProductService {
    
    @Autowired
    private ProductDao productDao;
    @Override
    public Product findById(Long pid) {
        return productDao.selectById(pid);
    }
}

controller

@RestController
@RequestMapping("product")
public class ProductController {

    @Autowired
    private IProductService productService;

    @GetMapping("/getById/{pid}")
    public Product getById(@PathVariable Long pid){
         return productService.findById(pid);
    }
}

主启动类

@SpringBootApplication
@MapperScan(basePackages = "com.aaa.product.dao")
public class ProductApp {
    public static void main(String[] args) {
        SpringApplication.run(ProductApp.class,args);
    }
}

在这里插入图片描述

4. 创建子模块–shop-order

关于订单表得所有操作接口
在这里插入图片描述

	<dependencies>
        <!--引入公共模块-->
        <dependency>
            <groupId>com.aaa</groupId>
            <artifactId>shop-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <!--引入springboot-starter-web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

配置

#端口号---[9001~9009]集群模式
server:
  port: 9001

#数据源得信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=Asia/Shanghai
    username: root
    password: root
# sql显示在控制台
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

dao接口

package com.aaa.order.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起
 * @create: 2022-11-18 14:34
 **/
public interface OrderDao extends BaseMapper<OrderDao> {

}

service代码

@Service
public class OrderService implements IOrderService {

    @Autowired
    private OrderDao orderDao;
    @Override
    public int save(Order order) {
        return orderDao.insert(order);
    }
}

配置类中注入restTemplate

@SpringBootApplication
public class AppOrder {
    public static void main(String[] args) {
        SpringApplication.run(AppOrder.class, args);
    }

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

controller代码

package com.aaa.order.controller;

import com.aaa.entity.Order;
import com.aaa.entity.Product;
import com.aaa.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起2
 * @create: 2022-11-17 16:33
 **/
@RestController
@RequestMapping("/order")
public class OrderController {


    //必须创建并交于spring容器管理。这样才能被注入到相应的类属性上
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IOrderService orderService;

    @GetMapping("/saveOrder")
    public String saveOrder(Long pid,Integer num){

        Order order=new Order();
        //用户得信息可以从登录后获取--Session  redis  jwt
        order.setUid(1);
        order.setUsername("张成");
        //为订单对象设置商品得信息
        order.setPid(pid);
       //需要远程调用商品微服务中的指定接口[注意:凡是关于商品的操作都有商品微服务来执行。]
        //远程调用的方式:第一种基于TCP协议的RPC远程调用   第二种基于http协议Restful风格的调用。
        //分布式架构:TCP协议的
        //微服务架构:http协议的。---在spring框架中封装了一个工具RestTemplate。 如果不是使用的spring框架。你需要自己封装HttpClient工具
        Product product = restTemplate.getForObject("http://localhost:8001/product/getById/"+pid, Product.class);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(num);


        orderService.save(order);

        return "下单成功";
    }
}

思考: 上面我们写远程调用代码 是否存在缺陷?


[1] 我们把商品微服务地址写死在自己代码中 硬编码—如果商品微服务地址发生改变。需要修改我们自己当前微服务的代码


[2] 如果商品微服务 搭建了集群模式。 订单微服务这边如何调用相应的商品微服务从而达到负载均衡的特性。

服务器治理组件。

eureka:当作服务治理组件。---->netflix公司的产品—停止更新维护


zookeeper: 服务治理组件。---->dubbo分布式框架配合


nacos: 服务治理组件。---->阿里巴巴的产品。

这里使用nacos

服务治理组件

在这里插入图片描述

1. 如何使用nacos

https://github.com/alibaba/nacos/releases

nacos1.3以后支持了集群模式。1.3以前不支持。

安装nacos服务端。
必须安装jdk并配置环境变量。而且不能把nacos放入中文目录

在这里插入图片描述
bin目录下startup.cmd启动nacos
在这里插入图片描述
访问nacos服务器
在这里插入图片描述
在这里插入图片描述

2. 微服务客户端连接到nacos注册中心

(1)引入依赖

<!--引入nacos的依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

(2)修改配置文件
在这里插入图片描述

测试:
在这里插入图片描述

3. 消费端如何通过nacos调用提供者

引入nacos依赖和配置nacos地址
修改控制层代码

package com.aaa.order.controller;

import com.aaa.entity.Order;
import com.aaa.entity.Product;
import com.aaa.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起2
 * @create: 2022-11-17 16:33
 **/
@RestController
@RequestMapping("/order")
public class OrderController {


    //必须创建并交于spring容器管理。这样才能被注入到相应的类属性上
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IOrderService orderService;

   	//在nacos中封装了一个类DiscoveryClient,该类可以获取注册中心中指定的清单列表。
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/saveOrder")
    public String saveOrder(Long pid,Integer num){
        Order order=new Order();
        //用户得信息可以从登录后获取--Session  redis  jwt
        order.setUid(1);
        order.setUsername("张成");
        //为订单对象设置商品得信息
        order.setPid(pid);
        
        //获取指定的实例
        List<ServiceInstance> instances = discoveryClient.getInstances("shop-product");
        ServiceInstance serviceInstance = instances.get(0);
//        String path = serviceInstance.getHost().toString();
//        System.out.println(path+"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//        Integer port = serviceInstance.getPort();
//        System.out.println(port+"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

        String uri = serviceInstance.getUri().toString();
//        System.out.println(uri+"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        Product product = restTemplate.getForObject(uri+"/product/getById/"+pid, Product.class);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(num);

        orderService.save(order);

        return "下单成功";
    }
}

如果后期 提供者的地址发生改变,也不影响消费者的代码。

思考: 上面使用从nacos拉取服务清单的模式是否存在问题?
没有实现负载均衡的问题。如果后期商品微服务在部署时 是一个集群。调用者应该把请求均摊到每个服务器上。

负载均衡

通俗的讲, 负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。

模拟搭建多个商品微服务。
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

1. 自己控制负载均衡

人为的完成订单微服务调用商品微服务负载均衡的特性。

package com.aaa.order.controller;

import com.aaa.entity.Order;
import com.aaa.entity.Product;
import com.aaa.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Random;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起2
 * @create: 2022-11-17 16:33
 **/
@RestController
@RequestMapping("/order")
public class OrderController {


    //必须创建并交于spring容器管理。这样才能被注入到相应的类属性上
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/saveOrder")
    public String saveOrder(Long pid,Integer num){
        Order order=new Order();
        //用户得信息可以从登录后获取--Session  redis  jwt
        order.setUid(1);
        order.setUsername("张成");
        //为订单对象设置商品得信息
        order.setPid(pid);
        //在nacos中封装了一个类DiscoveryClient,该类可以获取注册中心中指定的清单列表。
        //获取指定的实例
        List<ServiceInstance> instances = discoveryClient.getInstances("shop-product");

        //随机产生一个下标--0~size
        int index = new Random().nextInt(instances.size());
        ServiceInstance serviceInstance = instances.get(index);

        String uri = serviceInstance.getUri().toString();

        Product product = restTemplate.getForObject(uri+"/product/getById/"+pid, Product.class);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(num);

        orderService.save(order);

        return "下单成功";
    }
}

这两行是控制使用哪个微服务

//随机产生一个下标--0~size
int index = new Random().nextInt(instances.size());
ServiceInstance serviceInstance = instances.get(index);

如果想改变负载均衡的策略,例如想变成轮询策略,就需要来这里修改源代码,硬编码问题【开闭原则】

提供了ribbon组件—该组件可以完成负载均衡。

2. ribbon完成负载均衡

ribbon是 Netflix 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。在 SpringCloud 中,nacos一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从nacos中读取到的服务信息,在调用服务节点提供的服务时,会合理(策略)的进行负载。

在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的列表信息,并基于内置的负载均衡算法,请求服务。

Ribbon自动的从注册中心中获取服务提供者的 列表信息,并基于内置的负载均衡算法,请求服务

2.1 如何使用ribbon

不需要再引入任何依赖
在这里插入图片描述
只需要再RestTemplate获取的bean上添加一个LoadBalance注解
在这里插入图片描述

@LoadBalanced是告诉RestTemplate使用ribbon完成负载均衡。自动从注册中心拉取服务。使用内置的负载均衡策略完成服务的调用。

修改controller代码
在这里插入图片描述
测试发现默认使用的是轮询策略。ribbon是否可以改变为其他策略。而ribbon中提供了很多策略。

策路名策略描述实现说明
BestAvailableRule选择─个最小的并发请求的server逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
RandomRule随机选择一个server在index上随机。选择index对应位置的server
RoundRobinRule轮询方式轮询选择轮询index,选择index对应位置的server
AvailabilityFilteringRule过滤掉那些因为一直连接失败的被标记为circuittripped的后端server ,并过滤掉那些高并发的的后端server (active connections超过配置的阈值)使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRule根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。
RetryRule对选定的负载均衡策略机上重试机制。在一个配置时间段内当选择server不成功,则—直尝试使用subRule的方式选择一个可用的server
ZoneAvoidanceRule复合判断server所在区域的性能和server的可用性选择server使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前—个判断判定一个zone的运行性能是否可用,别除不可用的zone (的所有server) , AvailabilityPredicate用于过滤掉连接数过多的Server。

如何使用相应的策略:

shop-product:  # 这里使用服务的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #使用的的负载均衡策略

如果上面的策略不够用,你也可以自定义策略类。实现IRule接口完成自定义策略。
在这里插入图片描述
如果上面的策略不够用,你也可以自定义策略类。实现IRule接口完成自定义策略。

2.2 自定义负载均衡策略

不管任何一个负载均衡,都是IRule接口的子类。
在这里插入图片描述
我们自定义的规则类 也必须继承AbastractLoadBalancerRule类。

需求:
要求自定义的算法:依旧是轮询策略,但是每个服务器被调用5次后轮到下一个服务,即以前是每个服务被调用1次,现在是每个被调用5次 .

自定义规则类—模拟原来有的类。

package com.aaa.order.rule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancer;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起2
 * @create: 2022-11-19 14:42
 **/
public class MyRule extends AbstractLoadBalancerRule {
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
         //初始化方法 读取配置文件内容
    }

    //统计访问的次数
    private int total;
    //作为集群服务器下标
    private int index;
    @Override
    public Server choose(Object key) {
        //获取负载均衡选择器
        ILoadBalancer lb = getLoadBalancer();
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            //获取所有可用的服务器
            List<Server> upList = lb.getReachableServers();
            //获取所有的服务器。
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }

            //判断该服务访问的次数是否>5次
            if(total<5){
                 server=upList.get(index);
                 total++;
            }else{
                 total=0;
                 index++;
                 index=index%upList.size();
            }

            if (server == null) {
                Thread.yield();
                continue;
            }

            if (server.isAlive()) {
                return (server);
            }

            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }

        return server;
    }
}

(2)创建一个配置类,该类用于创建上面的bean对象

@Configuration
public class RuleConfig {

    @Bean
    public MyRule myRule(){
        return new MyRule();
    }
}

(3)ribbon使用上面自定义的规则
在这里插入图片描述

远程调用组件-Openfeign

我们上面服务与服务之间的调用,使用的为RestTemplate工具类,来完成相应的调用。但是RestTemplate这种模式不符合我们编程的习惯。

dao----service----controller:在service类中注入dao对象,然后调用dao中的方法,并传入相关的参数,以及接受相关的返回类型。

1. 概述

OpenFeign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。

Nacos很好的兼容了OpenFeign, Feign负载均衡默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。

2. 如何使用openfeign组件

(1)引入相关的依赖

<!--引入openfeign的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(2)创建feign接口

value:调用远程微服务的名称
@FeignClient(value = "shop-product")
public interface ProductFeign {
    @GetMapping("/product/getById/{pid}")
    public Product getById(@PathVariable Long pid);
}

(3)开启feign注解的驱动
在这里插入图片描述
(4)使用feign接口

package com.aaa.order.controller;

import com.aaa.entity.Order;
import com.aaa.entity.Product;
import com.aaa.order.feign.ProductFeign;
import com.aaa.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Random;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起2
 * @create: 2022-11-17 16:33
 **/
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private IOrderService orderService;

    //spring容器会为该接口生成带来实现类。
    @Autowired
    private ProductFeign productFeign;

    @GetMapping("/saveOrder")
    public String saveOrder(Long pid,Integer num){
        Order order=new Order();
        //用户得信息可以从登录后获取--Session  redis  jwt
        order.setUid(1);
        order.setUsername("张恒");
        //为订单对象设置商品得信息
        order.setPid(pid);
        //就像调用本地方法一样
        Product product = productFeign.getById(pid);

        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(num);

        orderService.save(order);
        return "成功";
    }
}

如果nacos单机出现故障,导致所有微服务服务注册和拉取相应的服务信息。从而导致整个项目无法使用。

所以就需要给nacos搭建集群模式
链接:xxx

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/25732.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nginx配置SSL证书

目录 获得证书 步骤一&#xff1a;购买证书 步骤二&#xff1a;申请证书 ​编辑 下载证书及证书转换&#xff1a;​编辑 配置SSL证书 在Nginx目录下新建certificate目录&#xff0c;并将下载好的证书/私钥等文件上传至该目录&#xff08;与配置文件同级目录&#xff09;。…

LiDAR点云转换到大地坐标系——简单粗标定

目录一、LiDAR和IMU位姿标定1.1安装角度标定1.2安装位置标定1.3部分代码二、点云转换到当地水平坐标系2.1基本理论2.1.1坐标系2.1.1.1激光雷达2.1.1.2导航坐标系/当地水平坐标系/大地坐标系2.1.2惯性传感器原理2.2点云转换试验2.2.1试验场地2.2.2试验内容2.2.3点云变换效果Wind…

C语言日记 37 类的友元(1)(全局函数做友元)

根据36 类和对象-友元-全局函数做友元_哔哩哔哩_bilibili复现出如下代码&#xff1a; 一、&#xff08;只是&#xff09;访问&#xff08;公开&#xff09;内部成员&#xff1a; #include <iostream> using namespace std; class Building { private:int ws;//卧室 pub…

NewStarCTF 公开赛-web

week1 HTTP cookie 修改admin 源码发现key GET和POST传参即可 Head?Header! User-Agent: CTF Referer: ctf.com X-Forwarded-For: 127.0.0.1我真的会谢 信息泄露 robots.txt www.zip 源码 /.index.php.swp NotPHP 函数绕过 if(file_get_contents($_GET[data]) &qu…

数据备份一般有哪些方式,如何进行数据备份

在如今这个时代&#xff0c;数据于我们而言是特别重要的&#xff0c;一旦发生丢失&#xff0c;可能会带来严重后果&#xff0c;如果你也很苦恼如何保证这些重要数据的安全&#xff0c;小编建议一定要对重要数据进行备份&#xff0c;以防发生丢失的意外。数据备份一般有哪些方式…

设计一个缓存策略,动态缓存热点数据

&#x1f468;‍&#x1f4bb;个人主页&#xff1a; 才疏学浅的木子 &#x1f647;‍♂️ 本人也在学习阶段如若发现问题&#xff0c;请告知非常感谢 &#x1f647;‍♂️ &#x1f4d2; 本文来自专栏&#xff1a; 常见场景解决方案 &#x1f308; 每日一语&#xff1a;努力不一…

C语言 0 —— 信息在计算机中的表示

计算机的电路 由 逻辑门电路组成。一个逻辑门电路可以看成为一个开关&#xff0c;每个开关的状态是“开” 则 高电位 对应 1 或者 “关” 则 低电位 对应 0 &#xff0c; 那么1和0 刚刚好用二进制数来表示&#xff1a; 每个位只能取1和0 &#xff0c;称为 one 个 bit &#…

谈一谈关于Linux内核编译详解原理

前言&#xff1a;为什么要做这个启动盘&#xff0c;因为内核编译是很危险的&#xff0c;中间出了错系统则直接崩溃&#xff0c;然后就无法开机了&#xff0c;你将看到一个_在你的左上角闪烁。知道启动盘可以帮你从外置设备启动系统&#xff0c;能启动系统才能恢复系统。1.编译前…

Java 线程和反射---尚硅谷Java视频学习

1.Java程序在运行得时候默认就会产生一个进程2.这个进程会有一个主线程3.代码都在主线程中执行 线程的生命周期 线程的执行方式 public class Java02_Thread {public static void main(String[] args) throws Exception {// TODO 线程 - 执行方式&#xff08;串行&#xff0c…

ASP.NET Core 3.1系列(14)——分布式缓存Redis的使用

1、前言 前一篇博客介绍了ASP.NET Core中本地缓存MemoryCache的使用方法。相较于本地缓存&#xff0c;分布式缓存更加适合大多数项目应用场景&#xff0c;下面就来介绍一下如何在ASP.NET Core中对Redis缓存进行相关操作。 2、分布式缓存接口——IDistributedCache 对于分布式…

pytorch深度学习实战24

第二十四课 VGG网络 VGG是Oxford的Visual Geometry Group的组提出的&#xff08;大家应该能看出VGG名字的由来了&#xff09;。该网络是在ILSVRC 2014上的相关工作&#xff0c;主要工作是证明了增加网络的深度能够在一定程度上影响网络最终的性能。VGG有两种结构&#xff0c;分…

远程重启电脑

一、设置电脑允许自动启动 在远程计算机上编辑设置远程注册表 步骤1. 按“WindowsR”键调用运行对话框。输入“services.msc”并点击“确定”。 步骤2. 在“服务”窗口中&#xff0c;双击“RemoteRegistry”以检查其状态。 步骤3. 将启动类型更改为“自动”。 二、查找远程计…

SPARKSQL3.0-各阶段自定义扩展规则源码剖析

一、前言 这一节主要介绍如何自定义扩展各阶段规则 虽然spark内部提供了很多优化规则&#xff0c;但在实际工作中&#xff0c;经常因为业务需求需要自定义扩展优化器或解析器&#xff0c;故自己实现一个优化器才对sparksql有更深的理解 二、扩展范围 spark在扩展方便做的很…

vue.js毕业设计,基于vue.js前后端分离教室预约小程序系统设计与实现

功能介绍 【后台管理功能模块】 系统设置&#xff1a;设置关于我们、联系我们、加入我们、法律声明 广告管理&#xff1a;设置小程序首页轮播图广告和链接 留言列表&#xff1a;所有用户留言信息列表&#xff0c;支持删除 会员列表&#xff1a;查看所有注册会员信息&#xff0…

从零开始学前端:DOM、BOM、焦点事件 --- 今天你学习了吗?(JS:Day20)

从零开始学前端&#xff1a;程序猿小白也可以完全掌握&#xff01;—今天你学习了吗&#xff1f;&#xff08;JS&#xff09; 复习&#xff1a;从零开始学前端&#xff1a;CSSOM视图模式 — 今天你学习了吗&#xff1f;&#xff08;JS&#xff1a;Day19&#xff09; 文章目录从…

java8 (jdk 1.8) 新特性——Stream ApI

在java8 中&#xff0c;有两个最重要的改变&#xff0c;一个就是之前了解的Lmbda java8 (jdk 1.8) 新特性——Lambda ,还有一个就是Stream Api 1. 什么是Stream API 简单来说就是一个类库&#xff0c;里边有一些方法方便我们对集合数据进行操作&#xff0c;就好像使用 SQL 语…

Windows cmd 命令及Linux 环境下导入导入mysql 数据库

文章目录一、背景二、Windows cmd 导入导出mysql 数据库1.导出数据库三种方式&#xff08;导出数据库时不需要连接数据库&#xff09;2. 操作步骤2.导入数据库三、linux 环境下导入导出数据库一、背景 最近在本机上安装了一个WMware 虚拟机&#xff0c;需要从本机&#xff08;…

从三层架构说起,谈谈对历史项目的小改造

项目背景说明 最近接手一个 “老” 项目的需求修改&#xff0c;项目整体基于 .net core 3.1 平台&#xff0c;以传统的三层架构为基础构建。了解需求后&#xff0c;逐步对原有项目框架进行大概的了解&#xff0c;主要是熟悉一些框架的开发规范&#xff0c;基本工具类库的使用&…

寒亭5.8万亩盐碱稻 国稻种芯·中国水稻节:山东潍坊插秧期

寒亭5.8万亩盐碱稻 国稻种芯中国水稻节&#xff1a;山东潍坊插秧期 新京报讯&#xff08;记者赵利新&#xff09;新闻中国采编网 中国新闻采编网 谋定研究中国智库网 中国农民丰收节国际贸易促进会 国稻种芯中国水稻节 中国三农智库网-功能性农业农业大健康大会报道&#xff…

MMRotate 全面升级,新增 BoxType 设计

引言&#xff1a;大大降低水平框检测器改旋转框检测器的难度 MMRotate 是一个基于 PyTorch 和 MMDetection 的开源旋转框目标检测工具箱。它将目标检测从水平框扩展到旋转框&#xff0c;为场景文字、遥感影像、自动驾驶等领域的应用打下了基础&#xff0c;为学术界和产业界提供…