不妨大胆一点 自己做一个Nacos(用JAVA实现 )
点击小卡片参与粉丝专属福利什么是NacosNacos是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos的主要功能:
服务发现和服务健康监测动态配置服务动态 DNS 服务服务及其元数据管理直接参考Nacos文档 :Nacos文档
我们要做的功能是Nacos的功能实在是太成熟了,但是我们可以通过官网和文档总结出Nacos的两大核心功能:
服务发现配置管理Let'sgo一、实现 服务发现服务发现,与其说是实现服务与发现,不如说是实现以下三个功能:
服务启动时候进行注册查询已注册服务信息确认服务状态是否健康1、创建一个SpringBoot项目,用来做服务端这个项目要实现几个目的:
首先我们的服务需要可以支持Http请求(GRPC更好,Nacos用的就是GRPC,Http请求我们更熟悉一点,以后我们会专门出有关于JAVA使用GRPC的文章)。其次我们需要我们的服务可以集成和连接一个关系型数据库(Mysql或者Oracle...)和非关系型数据库(Redis...)所以我们需要创建一个SringBoot项目,因为我们需要一个配置与发现中心的这么一个服务,类似于搭建Nacos,我们只不过是将这个中间件变成一个我们熟悉的SpringBoot项目,方便我们开发。
2、服务端在 「注册中心 服务端」 ,我们需要一个注册接口。
实例 数据库同理创建publicclassClientBody
{
privatestaticfinallongserialVersionUID=1L;
/**自增id*/
privateLong
/**项目名*/
privateStringprojectName;
/**端口*/
privateStringport;
/**健康检测回调接口*/
privateStringCallbackInterface;
/**内网ip*/
privateStringinNetIp;
/**外网ip*/
privateStringoutNetIp;
/**注册时间*/
@JsonFormat(pattern="yyyy-MM-ddHH:mm:ss")
privateDateregSerTime;
/**0-健康1-异常2-死亡*/
privateStringserType;
/**异常时间*/
@JsonFormat(pattern="yyyy-MM-ddHH:mm:ss")
privateDateexceptTime;
/**死亡时间*/
@JsonFormat(pattern="yyyy-MM-ddHH:mm:ss")
privateDatedeathTime;
/**检测次数*/
privateLongcheckNum;
/**异常次数*/
privateLongexceNum;
}
服务端注册接口/**
*令牌自定义标识
*/
@Value("${token.header}")
privateStringheader;
/**
*服务注册
*/
@PostMapping("/serviceRegistration")
publicBooleanadd(HttpServletRequestrequest,@RequestBodyClientBodyclientBody){
/**
*获取token
*/
Stringtoken=request.getHeader("header");
/**
*验证请求合法性
*/
BooleanisLegal=SecurityUtils.verLegal(token);
if(isLegal){
/**
*检测serType!=2端口+内网地址
*/
ClientBodyclient=clientBodyService.checkClient(clientBody);
if(ObjectUtils.isNotEmpty(client)){
/**
*说明是在心跳检测期间重新启动。
*注销这台实例.
*
*Mysqlclient这条数据
*deathTime改为现在时间
*serType改为2
*
*Redis直接删除这个数据id为Key的数据
*直接删除这台实例
*/
clientBodyService.logoutCient(client);
/**
*redis和Mysql中新增一台实例
*regSerTime现在时间
*serType为0
*/
clientBodyService.insert(clientBody);
}else{
/**
*启动了一台实例
*/
clientBodyService.insert(clientBody);
}
returntrue;
}else{
returnfalse;
}
}
服务端健康检测定时任务/**
*60秒定时健康检测
*/
@Scheduled(cron="0/60****?")
publicvoidheartbeatCheck(){
/**
*查询serType=0健康的实例List
*/
ListClientBodyclientBodyList=clientBodyService.selectOnlineServer();
for(ClientBodyclientBody:clientBodyList){
//回调接口
StringCallbackInterface=clientBody.getCallbackInterface();
//内网地址
StringinNetIp=clientBody.getInNetIp();
//拿到端口号
Stringport=clientBody.getPort();
//发送http请求true为正常false为异常
Booleanstate=HttpUtils.sendHead(CallbackInterface,inNetIp,port);
if(state){
//检测次数+1(checkNum+1)
clientBodyService.updateCientNormal(clientBody);
}else{
/**
*检测ping不通原因可能时网络波动
*检测十次都是异常才判定死亡
*/
if(clientBody.getCheckNum()10){
//修改这条数据为死亡(serType=2)
clientBodyService.updateCientDeath(clientBody);
}else{
//修改这条数据为异常,然后检测次数+1,异常次数+1,异常时间[现在时间字符串拼接在原有数据之后](serType=checkNum+exceNum+)
clientBodyService.updateCientException(clientBody);
}
}
}
}
3、客户端在我们的 「客户端服务」 我们需要在启动的时候注册:
客户端注册接口/**
*注册
*@PostConstruct解释:在项目启动时加载数据
*/
@PostConstruct
publicvoidregisterService(){
HashMapString,Objectmap=newHashMapString,Object(){{
//项目名
put("projectName",MyConfig.getName());
//我注册选择内网地址,这个可以根据自己项目的实际情况选用。
put("inNetIp",MyConfig.getUrl());
//回调接口,这个接口就是下边的健康检测接口
put("CallbackInterface","/checkHealthy");
//项目端口号
put("port",MyConfig.getPort());
AjaxResultajaxResult=HttpUtils.sendPostRequest('注册与配置中心url',"/serviceRegistration",map);
}
我们还需要一个健康检测客户端接口,以便于服务注册中心心跳检测。我们选择用轻量级的头请求。
客户端健康检测接口/**
*健康检测接口
*/
@RequestMapping(value="/CallbackInterface",method=RequestMethod.HEAD)
publicvoidhealthyByHead(HttpServletResponseresponse){
response.setHeader("data","200");
}
好了,我们的服务注册就完成了!
二、实现 配置管理配置管理只需要我们完成两件事情
服务端管理配置客户端启动的时候拉取配置1、服务端管理配置第一步我们需要在服务注册中心 「服务端管理配置」,我们将所有application.yml中的文件用properties的方式存入数据库。publicclassConfigData
{
privatestaticfinallongserialVersionUID=1L;
/**id*/
privateLong
/**key*/
privateString
/**value*/
privateStringvalue;
/**tag*/
privateString
/**remark*/
privateStringremark;
}
入库的形式就是这种:
image.png「服务端拉取配置接口」@GetMapping("/getConfigDataByTag")
publicListMapString,StringgetConfig(@RequestParamStringtag)throwsJsonProcessingException{
MapString,StringconfigData=configDataService.selectconfigDataList(newconfigData(tag));
returnlist;
}
2、客户端拉取配置「客户端拉取配置接口」,我们客户端程序启动的时候需要从注册服务中心来拉取配置。
首先我们在路径src\main\resources\META-INF\spring.factories中的spring.factories文件中加入到最后一行。org.springframework.boot.env.EnvironmentPostProcessor=com.test.web.core.config.ServerConfigProcessor
然后我们需要创建一个拉取配置文件的类ServerConfigProcessor实现EnvironmentPostProcessor
publicclassServerConfigProcessorimplementsEnvironmentPostProcessor{
privatestaticfinalStringPROPERTY_SOURCE_NAME="databaseProperties";
@Override
publicvoidpostProcessEnvironment(ConfigurableEnvironmentenvironment,SpringApplicationapplication){
log.info("ServerConfigloadingstart");
MapString,ObjectpropertySource=newHashMap();
try{
/**
*拉取配置
*MyConfig.ServerConfigHttpUrl服务端url
*MyConfig.ServerConfigInterface服务端接口
*MyConfig.MyServerTag本服务标识(用来判断拉取的配置条件)
*/
MapString,ObjectconfigSource=HttpUtils.sendGet(MyConfig.ServerConfigHttpUrl,MyConfig.ServerConfigInterface,MyConfig.MyServerTag);
propertySource.putAll(configSource);
environment.getPropertySources().addFirst(newMapPropertySource(PROPERTY_SOURCE_NAME,propertySource));
log.info("ServerConfigloadingSuccess");
}catch(Throwablee){
e.printStackTrace();
thrownewRuntimeException(e);
}
}
}
OK到此为止我们的自定义Nacos就做好了。
总结我们的自定义Nacos就做好了,它可以实现的功能有:
客户端启动可以注册到服务端。服务端可以心跳检测每个客户端的项目。数据分析,比如我们什么时候项目异常?总共启动多少次项目?...可以不用application.yml,配置文件全部放在数据库中。(和Nacos一样)「可以实现热部署配置文件,远程更改,实时有效」。其他问题src\main\resources\META-INF\spring.factories为什么可以自动装载配置?这就要涉及SpringBoot源码啦,关于SpringBoot启动时候加载配置的优先级和环境配置的上下文,请参考SpringBoot源码。(读源码啦~ 必须要过这一关的嘛)
自定义拓展功能可以把服务注册发现和配置管理都用前端展示到页面上方便管理。以下是我自己实现的前端界面,不美观无所谓,看的懂就行。
服务注册发现image.png
配置管理(可以和Nacos一样在页面进行修改和热部署)image.png?觉得作者写的不错的,值得你们借鉴的话,就请点一个免费的赞吧!这个对我来说真的很重要。?(?? ? ??)?
?如果文章对你有帮助的话欢迎「关注+点赞+收藏」
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线