SpringBoot 整合 Zookeeper 接入Starring微服务平台
背景
最近接的一个项目是基于公司产品Starring做的微服务支付平台,纯后台项目,实现三方支付公司和银行接口来完成用户账户扣款,整合成通用支付接口发布给前端调用。
但是扯蛋了,这边前端什么都不想做,只想我们提供一个链接,用户可以选择支付方式进行支付,这样的话相当于咱们又得起一个WEB版的收银台Project。
最近SpringBoot挺流行的,那就单独给起一个H5项目跑几个页面,调用后台的支付接口就完事了,如下?
最终的系统架构成了这样吧,随便画一画,请客官别吐槽。
公司的产品的服务都是发布到Zookeeper注册中心的,结果我们SpringBoot收银台成了直连某个IP端口,要是交易量一起来把直连的12001压垮了怎么办?
这样显然会存在问题,就因为一个收银台项目把整个微服务支付平台变成了单节点,所以我们收银台SpringBoot项目也必须连到上面的ZK中去查找平台服务。
环境
SpringBoot 2.2.1.Release
解决思路
从单web项目转成基于zookeeper调用的微服务项目:
1、Registry:服务注册,公司产品Starring 采取Zookeeper 作为我们的注册中心,我们现在要做的就是订阅服务。
2、Provider:服务提供者(生产者),提供具体的服务实现,这个是支付后台提供的服务。
3、Consumer:消费者,从注册中心中订阅服务,这个就是我们这边收银台要实现的功能啦。
4、Monitor:监控中心,RPC调用次数和调用时间监控,这块公司存在
从上图中我们可以看出RPC 服务调用的过程主要为:
1、生产者发布服务到服务注册中心
2、消费者在服务注册中心中订阅服务
3、消费者调用已注册的服务
操作步骤
A、配置文件
B、创建自己的Zookeeper连接
C、查找自己需要的服务
D、服务调用
A、配置文件
1、Maven 配置文件 pom.xml,引入zookeeper和zkclient两个包。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>排除slf4j是因为和其他jar包冲突,启动时检查报错。
2、SpringBoot配置文件 application.yml 增加zookeeper配置
zookeeper:
address: serverhost:2181,serverhost:2182,serverhost:2183
timeout: 20000
B、创建Zookeeper连接
SpringBoot项目启动后,自动连接Zookeeper配置中心,并获取到zookeeper实例,只需要连接一次,所以使用的单例。
关注SpringBoot平台启动后执行事件【@PostConstruct 】
这里需要注意,尝试过多种平台后执行事件来执行connect方法,只有这种方式在平台加载完所有Bean后执行。其他的方式下,无法获取Zookeeper中的配置。放在主函数后面执行,也不行。
package com.adtec.pay.util; import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.concurrent.CountDownLatch; @Component
public class ZKWatcher implements Watcher { @Value("${zookeeper.address}")
public String ZK_ADDRESS;
@Value("${zookeeper.timeout}")
public int ZK_TIMEOUT; private static ZKWatcher instance = null;
private CountDownLatch latch = new CountDownLatch(1);
private ZooKeeper zooKeeper; public ZKWatcher() {
} public static ZKWatcher getInstance() {
if (instance == null) {
instance = new ZKWatcher();
}
return instance;
}
// 平台启动后加载
@PostConstruct
public void connect() throws IOException {
zooKeeper = new ZooKeeper(ZK_ADDRESS, ZK_TIMEOUT, this);
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
setZooKeeper(zooKeeper);
System.out.println("Zookeeper已连接成功:" + ZK_ADDRESS);
} @Override
public void process(WatchedEvent event) {
if (event.getState() == Event.KeeperState.SyncConnected) {
latch.countDown();
}
} public ZooKeeper getZooKeeper() {
return zooKeeper;
} public void setZooKeeper(ZooKeeper zooKeeper) {
this.zooKeeper = zooKeeper;
}
}
C、查找自己的服务
好了,启动项目,到这里zookeeper已经连接上了。
现在咱们要发请求到后台,该怎么在注册中心找到自己需要的服务呢 ?
上面也已经提到整个微服务运行模式,由生产者(Starring支付平台)发布服务到 注册中心(Zookeeper),我们收银台项目是消费者要去订阅服务的。也就是我们得去注册中心搜服务。
所以我们首先得知道生产者发布的服务到注册中心是一个什么路径,就是生产者发布到 Zookeeper的目录节点。
稍微要懂一点Zookeeper知识,你才知道怎么查节点。不懂的话,百度一下,或者看一下别人的: https://blog.csdn.net/java_66666/article/details/81015302,如果还看不会,那劝你洗洗睡吧。
这里可以推荐一个图形界面查Zookeeper的工具,如下图:
通过工具查看到我们的服务目录节点路径:/Inst/cty/800002/V1.0/IcpPayReq/V1.0
我们要调用的服务是:【IcpPayReq】,也就是我们定义的服务码。
既然知道路径,知道服务码,事情就和把大象塞进冰箱需要几步一样。
1、获取Zookeeper连接实例。
2、根据目录节点获取服务实例。
3、随机选择其中一个实例,获取URL。
获取请求的类如下:
package com.adtec.pay.util; import org.apache.zookeeper.ZooKeeper;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import java.util.LinkedList;
import java.util.List;
import java.util.Random; @Component
public class ZKListener {
// private static String SERVER_PATH = "/Inst/cty/800002/V1.0/IcpPayReq/V1.0"; private String SERVER_PATH = "";
private ZooKeeper zooKeeper; private List<String> paths = new LinkedList<>(); public void findTranUrl(String tranCode) {
if (!StringUtils.isEmpty(tranCode)) {
SERVER_PATH = "/Inst/cty/800002/V1.0/" + tranCode + "/V1.0";
}
getChilds();
} private void getChilds() {
List<String> ips = new LinkedList<>();
zooKeeper = ZKWatcher.getInstance().getZooKeeper();
try {
//获取子节点
List<String> childs = zooKeeper.getChildren(SERVER_PATH, false);
for (String child : childs) {
byte[] data = zooKeeper.getData(SERVER_PATH + "/" + child, false, null);
String path = new String(data, "UTF-8");
ips.add(path);
}
this.paths = ips;
} catch (Exception e) {
e.printStackTrace();
}
} public String getPath() {
if (paths.isEmpty()) {
return null;
}
//这里我们随机获取一个ip端口使用
int index = new Random().nextInt(paths.size());
return paths.get(index);
}
}这样就能找到真实请求地址了,愉快的发送请求吧。
D、服务调用
这里我写了一个通用类,因为调用的服务不会只有一个,服务目录路径相同服务码不同就可以通用了。
package com.adtec.pay.entity; import com.adtec.pay.util.CommUtil;
import com.adtec.pay.util.ZKListener;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; public class Request { @Autowired
private ZKListener zkListener; @Value("${spring.profiles.active}")
private String env; protected String url;
protected Class<? extends Response> responseClass; public Request(String tranCode, Class<? extends Response> responseClass) {
if (env.equals("dev")){
if (tranCode.equals("HosOrderQuery")) {
this.url = "http://serverhost:13008/HttpServer/MEDICAL_MNG_SVR/QryOrderDetail";
} else if (tranCode.equals("IcpPayReq")) {
this.url = "http://serverhost:13008/HttpServer/MEDICAL_MNG_SVR/IcpPayReq";
} else if (tranCode.equals("QryOrderDetail")) {
this.url = "http://serverhost:13008/HttpServer/MEDICAL_MNG_SVR/QryOrderDetail";
}
} else {
zkListener.findTranUrl(tranCode);
String path = zkListener.getPath();
ZKStatusEntity zkStatus = JSONObject.parseObject(path, ZKStatusEntity.class);
this.url = zkStatus.getCOM_HTTP().getURL() + "/" + tranCode;
} this.responseClass = responseClass;
} public void setUrl(String url) {
this.url = url;
} public void setResponseClass(Class<? extends Response> responseClass) {
this.responseClass = responseClass;
} public <T> Response send(Request request) {
return CommUtil.httpRequestJSON(url, request, responseClass);
} }
总结
这次通过做这个项目,摸索了很多SpringBoot的细节,遇到了很多看着很小又很影响进度的问题。
1、项目启动后加载所有Bean文件后启动,尝试了很多种方式。
2、通用的请求类整合,泛型确实用的不太熟悉,需要再多理解。
3、新的HttpClient包包名 org.apache.httpcomponents 的请求方法调试,网上很多都是老的方法。
搞定,收工。
刚发出来,那什么源码寺就copy过去了,也不标识,所以附上原文地址:https://www.cnblogs.com/laramia/p/11978271.html
SpringBoot 整合 Zookeeper 接入Starring微服务平台的更多相关文章
- 【译文】用Spring Cloud和Docker搭建微服务平台
by Kenny Bastani Sunday, July 12, 2015 转自:http://www.kennybastani.com/2015/07/spring-cloud-docker-mi ...
- java springboot activemq 邮件短信微服务,解决国际化服务的国内外兼容性问题,含各服务商调研情况
java springboot activemq 邮件短信微服务,解决国际化服务的国内外兼容性问题,含各服务商调研情况 邮件短信微服务 spring boot 微服务 接收json格式参数 验证参数合 ...
- Spring Cloud和Docker搭建微服务平台
用Spring Cloud和Docker搭建微服务平台 This blog series will introduce you to some of the foundational concepts ...
- java springboot整合zookeeper入门教程(增删改查)
java springboot整合zookeeper增删改查入门教程 zookeeper的安装与集群搭建参考:https://www.cnblogs.com/zwcry/p/10272506.html ...
- 智能家居巨头 Aqara 基于 KubeSphere 打造物联网微服务平台
背景 从传统运维到容器化的 Docker Swarm 编排,从 Docker Swarm 转向 Kubernetes,然后在 Kubernetes 运行 SpringCloud 微服务全家桶,到最终拥 ...
- 微服务平台(Micro Service Platform : MSP)旨在提供一个集开发、测试、运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效。
微服务平台(Micro Service Platform : MSP)旨在提供一个集开发.测试.运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效. MSP采用业界 ...
- SpringBoot + Dubbo + zookeeper 搭建简单分布式服务
SpringBoot + Dubbo + zookeeper 搭建简单分布式服务 详细操作及源码见: https://github.com/BillyYangOne/dubbo-springboot
- 一站式入口服务|爱奇艺微服务平台 API 网关实战 原创 弹性计算团队 爱奇艺技术产品团队
一站式入口服务|爱奇艺微服务平台 API 网关实战 原创 弹性计算团队 爱奇艺技术产品团队
- surging 将推出社区版微服务平台
前言 对于.NET大家并不陌生,有大批的企业选择.NET作为公司构建多种应用的开发平台,但是近几年随着微服务,大数据,移动端,物联网兴起,而后.NET社区生态没有跟上时代的步伐,已开始趋于没落,而其中 ...
随机推荐
- 记录一些常用的python库、软件或者网址
1.数据收集 BeautifulSoup.scrapy.selenium.requests 2.数据分析 pandas.numpy.pyDD.spacy 3.数据可视化 matplotlib.seab ...
- Spring框架学习笔记(6)——阿里云服务器部署Spring Boot项目(jar包)
最近接外包,需要部署服务器,便是参考了网上的几篇博文,成功在阿里云服务器成功部署了Spring Boot项目,特记下本篇笔记 Spring Boot项目打包 这里说一下部署的一些问题 1.mysql驱 ...
- RSA学习1
对PEM文件(以前是一个邮件编码)进行编码,得到RSA公钥.国密的RSA标准,一般是tlv(tag-version)格式的. 明文hash后的数据进行BER编码再进行加密.-签名 对于RSA的结构,全 ...
- C语言存储类别和链接
目录 C语言存储类别和链接 存储类别 存储期 五种存储类别 C语言存储类别和链接 最近详细的复习C语言,看到存储类别的时候总感觉一些概念模糊不清,现在认真的梳理一下.C语言的优势之一能够让程序员恰 ...
- Tomcat项目部署
一 之前一直是在ecplise 利用tomcat插件的形式启动项目,这里可以通过选择server.xml和context files两种方式这里选择这两者方式,都是会在tomcat/bin下产生对应的 ...
- Java面试官最爱问的volatile关键字
在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...
- 闯缸鱼:看懂python如何实现整数加和,再决定是否自学编程
玩鱼缸的新手都知道有一种鱼叫"闯缸鱼",皮实好养,帮助新手判断鱼缸环境是否准备好.这篇笔记,最初用来解答一个编程新手的疑问,后来我发现,整理一下也可当做有兴趣自学python 编程 ...
- SasS 设计原则十二因素
Heroku 是业内知名的云应用平台,从对外提供服务以来,他们已经有上百万应用的托管和运营经验.其创始人 Adam Wiggins 根据这些经验,发布了一个“十二要素应用宣言(The Twelve-F ...
- Pandas IO 操作
数据分析过程中经常需要进行读写操作,Pandas实现了很多 IO 操作的API 格式类型 数据描述 Reader Writer text CSV read_csv to_csv text JSON r ...
- CSPS模拟 48
??? 分数越来越低??? T1 String Master 题目过于毒瘤,以至于我都不想改 T2 Tourist Attractions 稍微转化题意是求无向图的三角形个数 由于坚信bitset不是 ...


