本文共 9483 字,大约阅读时间需要 31 分钟。
开发需求背景,在开发小程序视频时(springboot后端),需要一个后台管理系统(ssm后端),并且这两个系统是部署在不同的服务器上,当管理人员通过短视频后台管理背景音乐的上传和删除,需要小程序端的服务器能通过监听能自动下载背景音乐。这里我们就通过zookeeper中间件,springboot监听并且下载。
###内容目录1、中间件,提供协调服务。
2、作用于分布式系统,发挥其优势,可以为大数据服务。 3、支持java,提供java和c语言的客户端api。1、很多台计算机组成一个整体,一个整体一致对外并且处理同一请求。
2、内部的每台计算机都可以相互通信。 3、客户端到服务端的一次请求到响应结束会经历多台计算机。1、在安装zookeeper之前,需要先安装JDK,并进行环境配置。
2、下载zookeeper解压。在bin目录下, zkServer.cmd是zookeeper的启动脚本。在你执行启动脚本之前,还有几个基本的配置项需要配置一下,Zookeeper 的配置文件在 conf 目录下,这个目录下有 zoo_sample.cfg 和 log4j.properties,你需要做的就是将 zoo_sample.cfg 改名为 zoo.cfg,因为 Zookeeper 在启动时会找这个文件作为默认配置文件。
缺点:超时重连,不支持自动,需要手动操作。Watch注册一次后会失效,不支持递归的创建节点。
apche的开源项目,解决watcher的注册一次就失效的问题,api更加简单方便。
支持代码块,并解决常见的代码块换行不正确,特别是iPone、iPad上不能滚动的问题;
解决把内容粘贴到公众号时,图片、或样式丢失的问题;1、创建重试策略 - retryPolicy
2、创建客户端 - client 3、 初始化客户端,加入到spring容器,项目启动加载的时候执行。org.apache.curator curator-framework 4.0.0 org.apache.zookeeper zookeeper 3.4.11 org.apache.curator curator-recipes 4.0.0
zookeeper 放入spring容器,项目启动加载的时候就建立和zk的连接
import org.apache.curator.framework.CuratorFramework;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.ZooDefs.Ids;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class ZKCurator { // zk客户端 private CuratorFramework client = null; final static Logger log = LoggerFactory.getLogger(ZKCurator.class); public ZKCurator(CuratorFramework client) { this.client = client; } /** 初始化调用 */ public void init() { //使用admin命名空间,方便zookeeper节点目录区分。 client = client.usingNamespace("admin"); try { // 判断在admin命名空间下是否有bgm节点 /admin/bmg if (client.checkExists().forPath("/bgm") == null) { /** * 对于zk来讲,有两种类型的节点: * 持久节点: 当你创建一个节点的时候,这个节点就永远存在,除非你手动删除 * 临时节点: 你创建一个节点之后,会话断开,会自动删除,当然也可以手动删除 */ client.create().creatingParentsIfNeeded() .withMode(CreateMode.PERSISTENT) // 节点类型:持久节点 .withACL(Ids.OPEN_ACL_UNSAFE) // acl:匿名权限 .forPath("/bgm"); log.info("zookeeper初始化成功..."); log.info("zookeeper服务器状态:{}", client.isStarted()); } } catch (Exception e) { log.error("zookeeper客户端连接、初始化错误..."); e.printStackTrace(); } } /** * @Description: 增加或者删除bgm,向zk-server创建子节点,供小程序后端监听 * forPath的两个参数:第一个:表示创建的目录节点,第二个表示该节点下要保存的数据。 */ public void sendBgmOperator(String bgmId, String operObj) { try { client.create().creatingParentsIfNeeded() .withMode(CreateMode.PERSISTENT) // 节点类型:持久节点 .withACL(Ids.OPEN_ACL_UNSAFE) // acl:匿名权限 .forPath("/bgm/" + bgmId, operObj.getBytes()); // bgm/bgmId 子节点 } catch (Exception e) { e.printStackTrace(); } } }
package com.imooc.enums;public enum BGMOperatorTypeEnum { ADD("1", "添加bgm"), DELETE("2", "删除bgm"); public final String type; public final String value; BGMOperatorTypeEnum(String type, String value){ this.type = type; this.value = value; } public String getUserType() { return type; } public String getValue() { return value; } public static String getValueByKey(String key) { for (BGMOperatorTypeEnum type : BGMOperatorTypeEnum.values()) { if (type.getUserType().equals(key)) { return type.value; } } return null; } }
@Override public void addBgm(Bgm bgm) { String bgmId = sid.nextShort(); bgm.setId(bgmId); bgmMapper.insert(bgm); Mapmap = new HashMap<>(); map.put("operType", BGMOperatorTypeEnum.ADD.type); map.put("path", bgm.getPath()); zkCurator.sendBgmOperator(bgmId, JsonUtils.objectToJson(map)); }
@Override public void deleteBgm(String id) { Bgm bgm = bgmMapper.selectByPrimaryKey(id); bgmMapper.deleteByPrimaryKey(id); Mapmap = new HashMap<>(); map.put("operType", BGMOperatorTypeEnum.DELETE.type); map.put("path", bgm.getPath()); zkCurator.sendBgmOperator(id, JsonUtils.objectToJson(map)); }
package com.imooc;import java.io.File;import java.net.URL;import java.net.URLEncoder;import java.util.Map;import org.apache.commons.io.FileUtils;import org.apache.commons.lang3.StringUtils;import org.apache.curator.RetryPolicy;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.framework.recipes.cache.PathChildrenCache;import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;import org.apache.curator.retry.ExponentialBackoffRetry;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import com.imooc.cofig.ResourceConfig;import com.imooc.enums.BGMOperatorTypeEnum;import com.imooc.utils.JsonUtils;@Componentpublic class ZKCuratorClient { // zk客户端 private CuratorFramework client = null; final static Logger log = LoggerFactory.getLogger(ZKCuratorClient.class);// @Autowired// private BgmService bgmService; // public static final String ZOOKEEPER_SERVER = "192.168.1.210:2181"; @Autowired private ResourceConfig resourceConfig; public void init() { if (client != null) { return; } // 重试策略 RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5); // 创建zk客户端 client = CuratorFrameworkFactory.builder().connectString(resourceConfig.getZookeeperServer()) .sessionTimeoutMs(10000).retryPolicy(retryPolicy).namespace("admin").build(); // 启动客户端 client.start(); try { //测试 从这个(admin/bgm/18052674D26HH3X4)节点下获取数据// String testNodeData = new String(client.getData().forPath("/bgm/18052674D26HH3X4"));// log.info("测试的节点数据为: {}", testNodeData); addChildWatch("/bgm"); //监听bgm下的子节点 } catch (Exception e) { e.printStackTrace(); } } //事件监听 public void addChildWatch(String nodePath) throws Exception { final PathChildrenCache cache = new PathChildrenCache(client, nodePath, true); cache.start(); cache.getListenable().addListener(new PathChildrenCacheListener() { @Override public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { if (event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)) { log.info("监听到事件 CHILD_ADDED"); // 1. 从数据库查询bgm对象,获取路径path String path = event.getData().getPath(); String operatorObjStr = new String(event.getData().getData()); //节点类型 Mapmap = JsonUtils.jsonToPojo(operatorObjStr, Map.class); String operatorType = map.get("operType"); String songPath = map.get("path"); // String arr[] = path.split("/");// String bgmId = arr[arr.length - 1]; //在删除的时候,有可能bgm这条记录已经被后台管理删除,这里再查询就查不到记录。// Bgm bgm = bgmService.queryBgmById(bgmId);// if (bgm == null) {// return;// } // 1.1 bgm所在的相对路径// String songPath = bgm.getPath(); // 2. 定义保存到本地的bgm路径// String filePath = "C:\\imooc_videos_dev" + songPath; String filePath = resourceConfig.getFileSpace() + songPath; // 3. 定义下载的路径(播放url) String arrPath[] = songPath.split("\\\\"); String finalPath = ""; // 3.1 处理url的斜杠以及编码 for(int i = 0; i < arrPath.length ; i ++) { if (StringUtils.isNotBlank(arrPath[i])) { finalPath += "/"; finalPath += URLEncoder.encode(arrPath[i], "UTF-8") ; } }// String bgmUrl = "http://192.168.1.2:8080/mvc" + finalPath; String bgmUrl = resourceConfig.getBgmServer() + finalPath; if (operatorType.equals(BGMOperatorTypeEnum.ADD.type)) { // 下载bgm到spingboot服务器 URL url = new URL(bgmUrl); File file = new File(filePath); FileUtils.copyURLToFile(url, file); client.delete().forPath(path); } else if (operatorType.equals(BGMOperatorTypeEnum.DELETE.type)) { File file = new File(filePath); FileUtils.forceDelete(file); client.delete().forPath(path); } } } }); } }
@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter { @Bean(initMethod="init") public ZKCuratorClient zkCuratorClient() { return new ZKCuratorClient(); }}
@ConfigurationProperties(prefix=“com.imooc”)中的com.imooc是对resource.properties文件中com.imooc.zookeeperServer的com.imooc的统一定义。
@Configuration //定义配置文件@ConfigurationProperties(prefix="com.imooc") // 定义前缀。@PropertySource("classpath:resource.properties") //指定资源文件目录public class ResourceConfig { private String zookeeperServer; private String bgmServer; private String fileSpace; public String getZookeeperServer() { return zookeeperServer; } public void setZookeeperServer(String zookeeperServer) { this.zookeeperServer = zookeeperServer; } public String getBgmServer() { return bgmServer; } public void setBgmServer(String bgmServer) { this.bgmServer = bgmServer; } public String getFileSpace() { return fileSpace; } public void setFileSpace(String fileSpace) { this.fileSpace = fileSpace; }}
资源文件:resource.properties
com.imooc.zookeeperServer=192.168.1.210:2181com.imooc.bgmServer=http://192.168.1.2:8080/mvccom.imooc.fileSpace=C:\\imooc_videos_dev
转载地址:http://qjfoi.baihongyu.com/