分布式学习之zookeeper实战篇服务注册与发现2
前面我们使用zk的原生客户端实现了简单的服务注册与发现
先来分析下前面的程序缺点有哪些 原生客户端的监听都是一次性的 没有负载均衡(说白了就是前面写的就不支持同一个服务注册多个)
我们来一个一个解决上面的问题。首先我们这次不采用原生客户端而采用zkClinet来处理改写之前的程序。在此基础上 先解决只能监听一次 的问题。
pom.xml文件自然要增加 zkClinet的依赖 com.101tec zkclient 0.10
配置文件 applciation..yml - 这里将原来写死在类里面的部分数据抽取到了配置文件中,如节点目录、zk地址、项目名称 spring: config: name: product server: port: 8081 zk: address: 127.0.0.1:2181 root: /clinetServices
product
首先使用zkClinet来首先 注册器 @Component public class RegisterClinet { @Value("${zk.root}") private String zkRoot; @Value("${spring.config.name}") private String appName; @Value("${zk.address}") private String address; @Value("${server.port}") private String serverPort; // 注册 public void register(){ ZkClient zkClient = new ZkClient(address, 5000); // 解决乱码问题 zkClient.setZkSerializer(new ZkCodeSerializer()); // 创建根目录 if (!zkClient.exists(zkRoot)) { zkClient.createPersistent(zkRoot); } String ip = ""; try { InetAddress ip4 = Inet4Address.getLocalHost(); ip = ip4.getHostAddress(); } catch (UnknownHostException e) { System.out.println("--------------------------"); } String value = ip + ":" + serverPort; zkClient.createEphemeralSequential(zkRoot + "/" + appName, value); } // 解决中文乱码 class ZkCodeSerializer implements ZkSerializer { @Override public byte[] serialize(Object object) throws ZkMarshallingError { return ((String)object).getBytes(Charset.forName("UTF-8")); } @Override public Object deserialize(byte[] bytes) throws ZkMarshallingError { return new String(bytes, Charset.forName("UTF-8")); } } }
初始化的地方自然也要改写一下 public class InitListener implements ServletContextListener { // 前面写过,这里就把变动点写一下 /* String hostAddress = InetAddress.getLocalHost().getHostAddress(); ServiceRegister.register(hostAddress,port); */ registerClinet.register(); // ... }
cusotmer
消费者这边的获取服务列表及持续监听 @Component public class InitZkClinetListener { @Value("${zk.root}") private String zkRoot; @Value("${zk.address}") private String address; @PostConstruct public void contextInitialized() { ZkClient zkClient = new ZkClient(address, 5000); // 解决乱码问题 zkClient.setZkSerializer(new ZkCodeSerializer()); try { // 第一次直接调用刷新缓存列表 refreshServiceList(); // 监听变化 reWatch(zkClient); } catch (Exception e) { System.out.println("---------------"); } } /** * 刷新注册列表 */ private void refreshServiceList() { ZkClient zkClient = new ZkClient(address, 5000); // 解决乱码问题 zkClient.setZkSerializer(new ZkCodeSerializer()); List serverList = new ArrayList(); List children = zkClient.getChildren(zkRoot); for (String child: children) { String sAddr = zkClient.readData(zkRoot + "/" + child); serverList.add(sAddr); } ServiceCache.SERVICE_LIST = serverList; } /** * 持续监听 * @param zkClient */ private void reWatch(ZkClient zkClient){ zkClient.subscribeChildChanges(zkRoot, new IZkChildListener() { // 监测子节点的操作事件 @Override public void handleChildChange(String s, List list) throws Exception { refreshServiceList(); reWatch(zkClient); } }); } // 解决中文乱码 class ZkCodeSerializer implements ZkSerializer { @Override public byte[] serialize(Object object) throws ZkMarshallingError { return ((String)object).getBytes(Charset.forName("UTF-8")); } @Override public Object deserialize(byte[] bytes) throws ZkMarshallingError { return new String(bytes, Charset.forName("UTF-8")); } } }
消费者不在使用ServletContextListener,所以从启动类中注释掉之前写的注入bean @SpringBootApplication public class SpackManagerZkCustomerApplication { public static void main( String[] args ) { SpringApplication.run(SpackManagerZkCustomerApplication.class); } /* @Bean public ServletListenerRegistrationBean servletListenerRegistrationBean() { ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean(); servletListenerRegistrationBean.setListener(new InitListener()); return servletListenerRegistrationBean; }*/ @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
ok,启动测试。测试过程: 启动product 启动customer 调用customer测试类,debug查看列表(当然也可以写一个方法直接查列表) 停止product(直接停止应用不会立即删除临时节点,需要稍微等一会、这里可以使用zk客户端查看zk对应的临时节点是否还在) 调用customer测试类,debug查看列表 启动product 调用customer测试类,debug查看列表
当然也可以直接打断点的方式测试.我这里就不把测试截图贴上了.
接下来我们来解决负载问题(我们就简单的采用随机负载)
首先我们先来处理解决缓存名称问题,很简单。在product注册的时候将服务名称也写进去。代码如下 String value = appName + "#" + ip + ":" + serverPort; zkClient.createEphemeralSequential(zkRoot + "/" + appName, value);
在customer解析的时候按照规则进行拆分解析即可 private void refreshServiceList() { ZkClient zkClient = new ZkClient(address, 5000); // 解决乱码问题 zkClient.setZkSerializer(new ZkCodeSerializer()); Map> service_map = new HashMap<>(); List children = zkClient.getChildren(zkRoot); for (String child: children) { String sAddr = zkClient.readData(zkRoot + "/" + child); String key = sAddr.split("#")[0]; Set set = service_map.get(key) == null ? new HashSet<>() : service_map.get(key); set.add(sAddr.split("#")[1]); service_map.put(key, set); } ServiceCache.SERVICE_MAP = service_map; }
负载的处理 public class ServiceCache { // zk service列表缓存 public volatile static List SERVICE_LIST; public volatile static Map> SERVICE_MAP; // 实现随机访问 public static String loadBalance(String servieName){ Set set = SERVICE_MAP.get(servieName); if(!CollectionUtils.isEmpty(set)) { int index = new Random().nextInt(SERVICE_LIST.size()); return SERVICE_LIST.get(index); } return ""; } }
这样就完成了整体的二次优化。后面继续优化
为什么美国要投放7。5亿只转基因蚊子?背后的影响,值得警惕美国的佛罗里达州曾出现这样的景象,乌泱泱的蚊子大军被研究人员从箱子中放出来,让人感觉到头皮发麻,他们到底在做什么?原来,为了达成消灭蚊子的计划,美国投放了大量的转基因蚊子,试图让野
推特创始人的NFT从290万暴跌至1万,马斯克我要全款买推特NFT有风险,入手需谨慎。买的时候有多开心,卖的时候就有多伤心。最近,马来西亚一家区块链公司的CEO新浪(SinaEstavi)正在出售一枚NFT。鉴于他的名字这么可爱,我们就叫他
使用TensorFlow进行文本分类1前言在自然语言处理中,文本分类是非常普遍的应用,本文将介绍使用TensorFlow开发基于嵌入(Embedding)的文本分类模型,由于TensorFlow的API变化迅速且兼容
超级富豪们转战银河贝索斯将发射3200颗卫星与马斯克竞争阿根廷布宜诺斯艾利斯经济新闻网近日报道称,世界上最富有的两个人再次开启对最有前途的电信市场之一的控制权的争夺战。亚马逊的创始人兼首席执行官杰夫贝索斯的对手是特斯拉汽车公司和太空探索
智慧矿山从头做起近年来,可穿戴设备成为热点,不仅是资本投资的风口,也是消费者追捧的潮品。而安全帽是矿山及建筑工地等行业的被动防护用品,给人的印象是傻笨重,两者毫无关联性。日前,我国自主研发的智能式
据韩国媒体称,韩国的电商企业爆发式增长即将结束据行业分析师周五表示,随着越来越多的公司进入快速增长的在线零售行业,竞争加剧,本地电子商务公司今年的销售增长开始停滞不前。韩国统计局公布的数据显示,电子商务运营商此前每年至少增长2
再流氓的软件也没有三头六臂郭元鹏帮助老年人跨越数字鸿沟,让更多老年人享受互联网带来的便捷生活,是数字化时代的重要课题。然而,据媒体报道,一些旨在方便老年人用户的适老化App及互联网应用,成了部分商家精准营销
为什么中国的叙事越来越难以影响美国民众?文观察者网专栏作者李泉重庆大学经略研究院研究员如果说1991年的海湾战争预示了人工智能技术支撑下的陆海空天加电磁和网络的综合军事斗争形态,今年的俄乌冲突则将军事战场之外全球化条件下
港媒自给自足,中国半导体进口减少来源环球时报香港南华早报4月13日文章,原题随着继续大力推进自给自足攻势,中国的半导体(集成电路)进口总量正在下降中国海关总署的数据显示,今年一季度,中国的集成电路进口总量同比减少
259项(人)获2021年度河北省科学技术奖从河北省科技厅获悉,259项(人)获2021年度河北省科学技术奖。今年,省科技厅围绕河北省科技奖励制度改革方案确定的重点任务,继续深化科技奖励改革,取得显著成效。从评选结果看,今年
思皓新能源E10X在过去的11月,思皓新能源订单突破15000辆,环比增长50,再创新高!而其中,思皓E10X成为了思皓新能源的台柱子,当之无愧是思皓新能源品牌中为出名的明星,同时也是思皓新能源的拳