谷粒商城高级篇(36)——商品上架之上传数据到Elasticsearch

2023-11-16

商品上架之上传数据到Elasticsearch

功能需求分析

  1. 需要保存 sku 信息
    当搜索商品名时,查询的是 sku 的标题 sku_title;
    可能通过 sku 的标题、销量、价格区间检索
  2. 需要保存品牌、分类等信息
    点击分类,检索分类下的所有信息
    点击品牌,检索品牌下的商品信息
  3. 需要保存 spu 信息
    选择规格,检索共有这些规格的商品

分析-怎么设计存储结构来保存数据

空间换时间

{
    skuId:1
    spuId:11
    skyTitile:华为xx
    price:999
    saleCount:99
    attrs:[
        {尺寸:5存},
        {CPU:高通945},
        {分辨率:全高清}
	]
}
# 缺点:会产生冗余字段,对于相同类型的商品,attrs 属性字段会重复,空间占用大
# 好处:方便检索

时间换空间

sku索引
{
    skuId:1
    spuId:11
}
attr索引
{
    spuId:11
    attrs:[
        {尺寸:5寸},
        {CPU:高通945},
        {分辨率:全高清}
	]
}
# 缺点:选择公共属性attr时,会检索当前属性的所有商品分类,然后再查询当前商品分类的所有可能属性;
# 		 导致耗时长。
# 好处:空间利用率高

最终方案-存储结构

PUT product
{
  "mappings": {
    "properties": {
      "skuId": { "type": "long" },
      "spuId": { "type": "keyword" },
      "skuTitle": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuPrice": { "type": "keyword" },
      "skuImg": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "saleCount":{ "type":"long" },
      "hasStock": { "type": "boolean" },
      "hotScore": { "type": "long"  },
      "brandId":  { "type": "long" },
      "catalogId": { "type": "long"  },
      "brandName": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "brandImg":{
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "catalogName": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "attrs": {
        "type": "nested",
        "properties": {
          "attrId": {"type": "long"  },
          "attrName": {
            "type": "keyword",
            "index": false,
            "doc_values": false
          },
          "attrValue": { "type": "keyword" }
        }
      }
    }
  }
}
关于 nested 类型

Object 数据类型的数组会被扁平化处理为一个简单的键与值的列表,即对象的相同属性会放到同一个数组中,在检索时会出现错误。参考官网:How arrays of objects are flattened
对于 Object 类型的数组,要使用 nested 字段类型。参考官网:Using nested fields for arrays of objects

官网

商品上架功能实现

guimall-common

我们在远程调用nacos的服务时出现ribbon的报错提示

我在pom.xml的文件中间

pom.xml

    <!--注册中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>

封装了es的操作的model

com/xfwang/gulimall/common/to/es/SkuEsModel.java

@Data
public class SkuEsModel {
    private Long skuId;
    private Long spuId;
    private String skuTitle;
    private BigDecimal skuPrice;
    private String skuImg;
    private Long saleCount;
    /**
     * 是否有库存
     */
    private Boolean hasStock;
    /**
     * 热度
     */
    private Long hotScore;
    private Long brandId;
    private Long catalogId;
    private String brandName;
    private String brandImg;
    private String catalogName;
    private List<Attrs> attrs;
    @Data
    public static class Attrs {
        private Long attrId;
        private String attrName;
        private String attrValue;
    }


}

com/xfwang/gulimall/common/exception/BizCodeEnume.java

public enum BizCodeEnume {
    /**
     * 系统未知异常
     */
    UNKNOW_EXCEPTION(10000, "系统未知异常"),

    PRODUCT_UP_EXCEPTION(11000,"商品上架错误"),
    /**
     * 参数校验错误
     */
    VAILD_EXCEPTION(10001, "参数格式校验失败");




    private final int code;
    private final String msg;
    BizCodeEnume(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }



}

com/xfwang/gulimall/common/constant/ProductConstant.java

public class ProductConstant {

	public enum AttrEnum {
		ATTR_TYPE_BASE(1, "基本属性"), ATTR_TYPE_SALE(0, "销售属性");

		private int code;

		private String msg;

		AttrEnum(int code, String msg) {
			this.code = code;
			this.msg = msg;
		}

		public int getCode() {
			return code;
		}

		public String getMsg() {
			return msg;
		}
	}



	public enum StatusEnum {
		SPU_UP(1, "商品上架"), NEW_UP(0, "新建"),SPU_DOWN(2, "商品下架");

		private int code;

		private String msg;

		StatusEnum(int code, String msg) {
			this.code = code;
			this.msg = msg;
		}

		public int getCode() {
			return code;
		}

		public String getMsg() {
			return msg;
		}
	}
}

com/xfwang/gulimall/common/vo/SkuHasStockVo.java

@Data
public class SkuHasStockVo {
    private Long skuId;
    private Boolean hasStock;
}

首先es的模块加入注册到nacos服务,这样可以通过gateway网关调用服务

guimall-search

application.yml

spring:
  application:
    name: gulimall-search
  cloud:
    nacos:
      discovery:
        server-addr: 123.57.234.28:8848


server:
  port: 12000

com/xfwang/gulimall/search/constant/EsConstant.java

public class EsConstant {
    public static final  String PRODUCT_INDEX = "product";


}

com/xfwang/gulimall/search/controller/ElasticSaveController.java

@Slf4j
@RestController
@RequestMapping("/search/save")
public class ElasticSaveController {


    @Autowired
    private ProductSaveService productSaveService;

    /**
     * 上架商品
     */
    @PostMapping("/product") // ElasticSaveController
    public R productStatusUp(@RequestBody List<SkuEsModel> skuEsModels){

        boolean status;
        try {
            status = productSaveService.productStatusUp(skuEsModels);
        } catch (IOException e) {
            log.error("ElasticSaveController商品上架错误: {}", e);
            return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(), BizCodeEnume.PRODUCT_UP_EXCEPTION.getMsg());
        }
        if(!status){
            return R.ok();
        }
        return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(), BizCodeEnume.PRODUCT_UP_EXCEPTION.getMsg());
    }






}

com/xfwang/gulimall/search/service/ProductSaveService.java

public interface ProductSaveService {

    boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException;
}

com/xfwang/gulimall/search/service/iml/ProductSaveServiceImpl.java

@Slf4j
@Service
public class ProductSaveServiceImpl implements ProductSaveService {


    @Autowired
    private RestHighLevelClient client;


    @Override
    public boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException {
        // 1.给ES建立一个索引 product
        BulkRequest bulkRequest = new BulkRequest();
        // 2.构造保存请求
        for (SkuEsModel esModel : skuEsModels) {
            // 设置索引
            IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX);
            // 设置索引id
            indexRequest.id(esModel.getSkuId().toString());
            String jsonString = JSON.toJSONString(esModel);
            indexRequest.source(jsonString, XContentType.JSON);
            // add
            bulkRequest.add(indexRequest);
        }
        // bulk批量保存
        BulkResponse bulk = client.bulk(bulkRequest, EsConfig.COMMON_OPTIONS);
        // TODO 是否拥有错误
        boolean hasFailures = bulk.hasFailures();
        if(hasFailures){
            List<String> collect = Arrays.stream(bulk.getItems()).map(item -> item.getId()).collect(Collectors.toList());
            log.error("商品上架错误:{}",collect);
        }
        return hasFailures;
    }

}

设置启动类可以注册到nacos

GulimallSearchApplication
@EnableDiscoveryClient

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@EnableDiscoveryClient
public class GulimallSearchApplication {

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

}

guimall-ware

查询库存方法通过openFeign远程调用

com/xfwang/gulimall/ware/controller/WareSkuController.java

@RestController
@RequestMapping("ware/waresku")
public class WareSkuController {
    @Autowired
    private WareSkuService wareSkuService;


    @PostMapping("/hasStock")
    public  List<SkuHasStockVo> getSkuHasStock(@RequestBody List<Long> SkuIds){
        List<SkuHasStockVo> vos = wareSkuService.getSkuHasStock(SkuIds);
        return vos;
        //return R.ok().put("data",vos);
    }
     ...
}

com/xfwang/gulimall/ware/service/WareSkuService.java

public interface WareSkuService extends IService<WareSkuEntity> {

    PageUtils queryPage(Map<String, Object> params);

	/**
	 * 保存库存的时候顺便查到商品价格
	 */
	double addStock(Long skuId, Long wareId, Integer skuNum);

    List<SkuHasStockVo> getSkuHasStock(List<Long> skuIds);
}

com/xfwang/gulimall/ware/service/impl/WareSkuServiceImpl.java


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {
	...
	@Override
	public List<SkuHasStockVo> getSkuHasStock(List<Long> skuIds) {
		List<SkuHasStockVo> collect = skuIds.stream().map(skuId -> {
			SkuHasStockVo vo = new SkuHasStockVo();
			//查询库存的总库存量

			Long count = baseMapper.getSkuStock(skuId);
			vo.setHasStock(count== null ?true:count>0 );
			vo.setSkuId(skuId);
			return vo;
		}).collect(Collectors.toList());

		return collect;
	}
}

com/xfwang/gulimall/ware/dao/WareSkuDao.java

@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {

	void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);

    Long getSkuStock(Long skuId);
}

mapper/ware/WareSkuDao.xml

<mapper namespace="com.xfwang.gulimall.ware.dao.WareSkuDao">
	...

    <select id="getSkuStock" resultType="java.lang.Long">
        SELECT
            SUM(stock - stock_locked) count
        FROM
            wms_ware_sku
        WHERE
            sku_id = #{skuId}
    </select>


</mapper>

guimall-product

上架功能主要通过 product远程调用其他服务来实现

com/xfwang/gulimall/product/controller/SpuInfoController.java

@RestController
@RequestMapping("product/spuinfo")
public class SpuInfoController {

    @Autowired
    private SpuInfoService spuInfoService;


    /**
     * 商品上架功能
     *
     * @param spuId
     * @return
     */
    @PostMapping("/{spuId}/up")
    public R upSpu(@PathVariable Long spuId) {
        spuInfoService.up(spuId);
        return R.ok();
    }
    	...
 }

service

AttrService

public interface AttrService extends IService<AttrEntity> {
	...
    List<Long> selectSearchAttrIds(List<Long> attrIds);
}

AttrServiceImpl

@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {
	...
	@Override
	public List<Long> selectSearchAttrIds(List<Long> attrIds) {
		QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().select(AttrEntity::getAttrId).in(AttrEntity::getAttrId,attrIds).eq(AttrEntity::getSearchType,"1");
		List<Long> collect = list(queryWrapper).stream().map(item -> item.getAttrId()).collect(Collectors.toList());
		return collect;
	}
}

SkuInfoService

public interface SkuInfoService extends IService<SkuInfoEntity> {
	...
    List<SkuInfoEntity> getSkusBySpuId(Long spuId);
}

SkuInfoServiceImpl

@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {
	...
	@Override
	public List<SkuInfoEntity> getSkusBySpuId(Long spuId) {

		List<SkuInfoEntity> list = this.list(new QueryWrapper<SkuInfoEntity>().eq("spu_id",spuId));
		return list;
	}
}

SpuInfoService

public interface SpuInfoService extends IService<SpuInfoEntity> {
	...
  void up(Long spuId);
}

SpuInfoServiceImpl

@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
	...
@Override
	public void up(Long spuId) {
		//1、查出当前spuId对应的所有sku信息,品牌的名字
		List<SkuInfoEntity> skuInfoEntities=skuInfoService.getSkusBySpuId(spuId);
		//TODO 4、根据spu查出当前sku的所有可以被用来检索的规格属性
		List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
		List<Long> attrIds = productAttrValueEntities.stream().map(attr -> {
			return attr.getAttrId();
		}).collect(Collectors.toList());
		List<Long> searchIds=attrService.selectSearchAttrIds(attrIds);
		Set<Long> ids = new HashSet<>(searchIds);
		List<SkuEsModel.Attrs> searchAttrs = productAttrValueEntities.stream().filter(entity -> {
			return ids.contains(entity.getAttrId());
		}).map(entity -> {
			SkuEsModel.Attrs attr = new SkuEsModel.Attrs();
			BeanUtils.copyProperties(entity, attr);
			return attr;
		}).collect(Collectors.toList());


		//TODO 1、发送远程调用,库存系统查询是否有库存
		Map<Long, Boolean> stockMap = null;
		try {
			List<Long> longList = skuInfoEntities.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
			List<SkuHasStockVo> skuHasStocks = wareFeignService.getSkuHasStock(longList);
			stockMap = skuHasStocks.stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, SkuHasStockVo::getHasStock));
		}catch (Exception e){
			log.error("远程调用库存服务失败,原因{}",e);
		}

		//2、封装每个sku的信息
		Map<Long, Boolean> finalStockMap = stockMap;
		List<SkuEsModel> skuEsModels = skuInfoEntities.stream().map(sku -> {
			SkuEsModel skuEsModel = new SkuEsModel();
			BeanUtils.copyProperties(sku, skuEsModel);
			skuEsModel.setSkuPrice(sku.getPrice());
			skuEsModel.setSkuImg(sku.getSkuDefaultImg());
			//TODO 2、热度评分。0
			skuEsModel.setHotScore(0L);
			//TODO 3、查询品牌和分类的名字信息
			BrandEntity brandEntity = brandService.getById(sku.getBrandId());
			skuEsModel.setBrandName(brandEntity.getName());
			skuEsModel.setBrandImg(brandEntity.getLogo());
			CategoryEntity categoryEntity = categoryService.getById(sku.getCatalogId());
			skuEsModel.setCatalogName(categoryEntity.getName());
			//设置可搜索属性
			skuEsModel.setAttrs(searchAttrs);
			//设置是否有库存
			skuEsModel.setHasStock(finalStockMap==null?false:finalStockMap.get(sku.getSkuId()));
			return skuEsModel;
		}).collect(Collectors.toList());


		//TODO 5、将数据发给es进行保存:gulimall-search
		R r = searchFeignService.productStatusUp(skuEsModels);
		if (r.getCode()==0){
			this.baseMapper.upSpuStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
		}else {
			log.error("商品远程es保存失败");
		}

		
	}
}

WareSkuDao

@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {

	void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);

    Long getSkuStock(Long skuId);
}

WareSkuDao.xml

<mapper namespace="com.xfwang.gulimall.ware.dao.WareSkuDao">
	...
    <select id="getSkuStock" resultType="java.lang.Long">
        SELECT
            SUM(stock - stock_locked) count
        FROM
            wms_ware_sku
        WHERE
            sku_id = #{skuId}
    </select>


</mapper>

openFeign

SearchFeignService

@FeignClient("gulimall-search")
public interface SearchFeignService {


    @PostMapping("/search/save/product") // ElasticSaveController
     R productStatusUp(@RequestBody List<SkuEsModel> skuEsModels);
}

WareFeignService

@FeignClient("gulimall-ware")
public interface WareFeignService {
    @PostMapping("/ware/waresku/hasStock")
    List<SkuHasStockVo> getSkuHasStock(@RequestBody List<Long> SkuIds);
}

pom.xml

	<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.cloud</groupId>
					<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-loadbalancer</artifactId>
		</dependency>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谷粒商城高级篇(36)——商品上架之上传数据到Elasticsearch 的相关文章

  • 谷粒商城 - 项目环境搭建

    文章目录 1 安装 linux 虚拟机2 安装docker3 docker安装mysql4 docker安装redis5 开发环境统一1 Maven2 Idea amp VsCode 插件3 安装配置git 6 创建git仓库7 创建对应项
  • 谷粒商城 - 架构图

    商城项目地址 xff1a 后端项目源码 xff1a https gitee com StarSea007 gulimall parent 前端项目源码 xff1a https gitee com StarSea007 gulimall vu
  • 【白话spring cloud(一)】为什么要用spring cloud?

    前言 此系列文章针对有spring boot基础的 无此基础的建议先了解spring boot才会更加有印象 文章不会讲解源码这些 只会通过大白话的语言让你了解cloud 让你对cloud有个从0到1的认识 废话不多说let is go 1
  • 七:微服务调用组件Feign

    目录 JAVA 项目中如何实现接口调用 1 什么是Feign 1 1 优势 1 2 Feign的设计架构 1 3 Ribbon Feign对比 1 4 Feign单独使用 2 Spring Cloud Alibaba快速整合Feign 3
  • Spring Cloud Alibaba实战(八) - Dubbo + Nacos

    目录 一 Nacos动态配置 二 Nacos注册中心 三 Sentinel之限流 四 Sentinel之熔断 五 Gateway之路由 限流 六 Gateway之鉴权 日志 七 Gateway搭配Nacos实现动态路由 八 Dubbo Na
  • 谷粒商城微服务分布式高级篇ElasticSearch五——商城业务-商品上架

    文章目录 商品上架 ES数据模型 上架流程 mybatis之foreach用法 TypeReference Feign调用流程 商品上架 后台管理员对spu审核进行操作 点击上架 只有当商品上架才应该被检索 即需要导入商品数据到ES中 请求
  • 基于Spring Cloud Alibaba 分布式微服务高并发数据平台化(中台)思想+多租户saas企业开发架构技术选型和设计方案

    基于Spring Cloud Alibaba 分布式微服务高并发数据平台化 中台 思想 多租户saas设计的企业开发架构 支持源码二次开发 支持其他业务系统集成 集中式应用权限管理 支持拓展其他任意子项目 架构源码可以加我WX haiwab
  • Nacos startup无反应,启动报错的解决办法

    今天在运行Nacos的时候遇见了点问题 记录一下 我的系统是win11 运行的Nacos版本是 2 0 3 https github com alibaba nacos releases tag 2 0 3 运行startup cmd 无反
  • 基于Spring Cloud Alibaba搭建nacos

    关系 Spring Boot是框架 将各个组件集合在一起 方便快速开发web应用 Spring Cloud基于Spring Boot 限定了一组特定的组件 从而可以方便地进行微服务工程的开发 Spring Cloud Alibaba在Spr
  • Spring Cloud Alibaba Dubbo

    Spring Cloud Alibaba Dubbo 为什么 是什么 怎么做 为什么 单体应用 单体服务经过长期的迭代更新 逐渐走向代码臃肿 高耦合 这显然与我们软件开发设计理念高内聚 低耦合背道而驰 从而难以维护 市场需求也在逐渐要求服务
  • 系统架构演变历史及集群、分布式、微服务、SOA的概念区别

    文章目录 1 系统架构演变历史 1 单一应用架构 ORM 2 垂直应用架构 MVC 3 面向服务框架 SOA 4 微服务架构 1 微服务的特点 2 微服务主要解决的问题与场景 3 微服务的缺点 2 集群和分布式 微服务和soa概念和区别理解
  • 07、环境-虚拟机网络设置、开启远程登录

    1 Oracle VM VirtualBox默认网络方式 Oracle VM VirtualBox创建的虚拟机默认使用的是 网络地址转换 端口转发的方式 2 默认虚拟机ip地址不是固定IP 不方便开发 修改Vagrantfile confi
  • 关于elasticsearch连接时断时续以及Kibana出现server is not ready yet的问题,大坑!

    代码小白 记录自学制作谷粒商城遇到的坑 如有错误请轻喷 1 问题的出现 elasticsearch连接时断时续 在加完分词插件之后 出现了elasticsearch连接失败的情况 但是经过多次刷新之后居然是可以成功连接上去的 查看日志也没发
  • Nacos入门

    1 简介 Nacos 致力于帮助您发现 配置和管理微服务 Nacos 提供了一组简单易用的特性集 帮助您快速实现动态服务发现 服务配置 服务元数据及流量管理 Nacos 帮助您更敏捷和容易地构建 交付和管理微服务平台 Nacos 是构建以
  • Spring Cloud Alibaba Sentinel 整合 nacos 进行规则持久化

    上篇文章Spring Cloud Alibaba Sentinel 初体验介绍了Sentinel 的简单使用 在使用过程中我们发现在Sentinel 控制台中配置了规则之后 随着服务的重启 配置的规则也随之消失 Sentinel 控制台控制
  • Docker Portainer 安装与报错处理

    安装docker 管理器 Portainer 最近在看spring cloud alibaba的时候 觉得docker是肯定要用的 然后找了个管理的docker的东东 比较方便的查询docker的情况 直接看操作吧 root localho
  • seata server 1.6版本安装及配置

    文章目录 下载 安装并启动 数据库 导入数据库 修改配置文件 服务注册 配置中心 手动添加 脚本导入 前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网站 Seata 是一款开源的分布式事务解决方
  • Spring Cloud Gateway网关工作原理、网关谓词和GatewayFilter工厂

    Spring Cloud Gateway 官方文档地址 https docs spring io spring cloud gateway docs current reference html Spring Cloud Gateway项目
  • 四、Arthas

    四 Arthas 1 安装 卸载 1 Arthas支持在Linux Unix Mac等平台上一键安装 请复制以下内容 并粘贴到命令行中 敲回车执行即可 curl L https arthas aliyun com install sh sh
  • 全网最全谷粒商城记录_01、简介-项目介绍(2022-07-06更新完成)

    声明 本教程不收取任何费用 欢迎转载 尊重作者劳动成果 不得用于商业用途 侵权必究 目录 分布式基础 全栈开发篇 分布式高级 微服务架构篇 高可用集群 架构师提升篇 希望大家 微服务架构图简单介绍 项目简介 1 项目背景 1 电商模式 1

随机推荐

  • 保留指定位数小数点的方法(五种)

    package feifan import java text DecimalFormat import java text NumberFormat public class YuoXiaoShuzi public static void
  • 从mpeg ts文件中提取I帧(5):I帧的解码

    找到含有I帧的pes后就可以对其进行解码 对I帧的解码我们使用ffmpeg 这里用到的版本是3 0 0 一 pes解码为yuv ffmpeg一般都是这个套路 直接上代码 int ffdecode pes uint8 t pes data i
  • 硬件十万个为什么

    1 电源类 1 1 电源基础 各种 地 各种 GND 板载电源设计规范 电源环路稳定性评价方法 深入芯片内部 理解去耦电容的作用 减小DC DC变换器中的接 地反弹 一些接地要点 开关电源中的小启示 电源相关的测试 去耦电容的选择 容值计算
  • 马上:纸币互动,智能笔数据点压缩

    马上 纸币互动 智能笔数据点压缩 对接一款智能笔 笔的数据是通过蓝牙传给app 但是笔的笔迹点数量很多 网络传输用json就不恰当 所以一番调研才起二进制压缩点 数字压缩基本原理 基本数据 class Dot implements Seri
  • Python-爬虫实现天气查询-有GUI界面

    Python用缩进来区分代码层次 代码的主体是爬虫与Tkinter 执行程序后会先出现一个选择城市的界面 这里需要输入城市名 点击确认即会出现城市天气状况 执行效果如下 完整代码如下 from tkinter import GUI设计 tk
  • .NET和Web 3.0

    Professional Visual Studio Extensibility 的作者Keyvan Nayyeri 在他的博客里头发表了 NET and Web 3 0 作为 NET社区的一个名人 他同时是 Professional Co
  • JLabel显示图片,及其它使用方法。。。实现九九乘法表

    JLabel的使用 显示九九乘法表 并使用JLabel载入背景图片 窗口大小固定public MyFrame extends JFrame public MyFrame String str JLabel jL setLayout null
  • 在Element-ui的table表格中,如何让分页的序号延续上一页的序号

    可以通过传递index属性来自定义索引 1 页面
  • 爽!一个注解,搞定 SpringBoot 操作日志

    来源 blog csdn net weixin 43954303 article details 113781801 使用方式 基本使用 源码 此组件解决的问题是 谁 在 什么时间 对 什么 做了 什么事 本组件目前针对 Spring bo
  • hadoop实践(一)环境准备

    1 安装linux或者安装linux虚拟机 本人是安装linux虚拟机centos 至于网上很多用乌班图 我觉的因为是实践 所以基本无差 2 安装ssh linux 一般自带 rpm qa grep ssh 3 创建 hadoop用户 用r
  • Git、GitHub和Gitee的使用

    Git GitHub和Gitee之间的关系 1 Git 是一个开源的分布式版本控制系统 简单来说就是可以通过使用git去管理项目 我们可以将项目存放在一个仓库中 通过git去管理这个仓库 以此来达到管理项目的目的 2 GitHub是一个基于
  • 剑指Offer 62 -- 圆圈中最后剩下的数字

    剑指Offer 62 圆圈中最后剩下的数字 题目 0 1 n 1这n个数字排成一个圆圈 从数字0开始 每次从这个圆圈里删除第m个数字 删除后从下一个数字开始计数 求出这个圆圈里剩下的最后一个数字 例如 0 1 2 3 4这5个数字组成一个圆
  • Python语言基础—if判断和循环总结

    系列文章目录 Python语言基础 注释的作用及分类 Python语言基础 常用运算符总结 Python语言基础 定义变量与数据类型 Python语言基础 if判断和循环总结 Python语言基础 理解面向对象 Python语言基础 集合的
  • 新专辑《AI秘籍》,你所感兴趣的一切

    Hi 大家好 我时茶桁 最近 我花了几天时间仔细思考了一下即将要开始写的专栏 AI秘籍 再根据自己的能力大概规划了一下 目前大致已经理出了一些相关信息可以分享给大家 专栏形式 本次专栏应该会以文章的形式先和大家见面 后续还会根据能力以原本的
  • 十四、使用Selector(多路复用器)实现Netty中Reactor单线程模型

    导论 前面几篇文章我们分别从 一 C10K问题经典问答 二 java nio ByteBuffer用法小结 三 Channel 通道 四 Selector选择器 五 Centos Linux安装nc 六 windows环境下netcat的安
  • C++ 类大小分析

    以下测试代码的运行环境 Ubuntu 16 04 4 LTS gcc version 4 8 5 x64 空类 单一继承的空类 多重继承的空类所占空间大小为 1 字节 实例在内存中都有一个独一无二的地址 为了达到这个目的 编译器往往会给一个
  • 编译原理-总概

    语言执行过程 代码 解释器编译器 机器代码 cpu执行 编译型语言 在程序在执行之前需要一个专门的编译过程 通过编译器把程序编译成为可执行文件 再由机器运行这个文件 运行时不需要重新翻译 直接使用编译的结果就行了 解释型语言 是一边执行一边
  • NFT 笔记:我的加密艺术品投资逻辑

    There really is no such things as Art There are only artists 没有大写的艺术这种东西 只有艺术家 贡布里希 艺术的故事 撰文 小毛哥 Mao 推特 porounclemao 每当身
  • 钉钉F1 RK3399 咸鱼80元板子使用记录

    1 简单介绍 12V电源 建议2A 默认插电不开机 有大佬找到金属罩下的焊盘 短接可上电开机 在usb旁边的旁边有个端子接口 短接就可以开机 建议找个一样大的接口接个开关 到目前为止还未测试需要哪种接口 其它接口暂时不知 谁舍得拆一个钉钉F
  • 谷粒商城高级篇(36)——商品上架之上传数据到Elasticsearch

    商品上架之上传数据到Elasticsearch 功能需求分析 分析 怎么设计存储结构来保存数据 空间换时间 时间换空间 最终方案 存储结构 关于 nested 类型 商品上架功能实现 guimall common pom xml com x