如果你的服务已经能正常跑起来,个人建议可以先感受下nacos的魅力,也就是怎么使用吧

直接上代码

@Controller
@NacosPropertySource(dataId = "springboot2-nacos-config", autoRefreshed = true)
public class HealthController { @NacosValue(value = "${nacos.test.propertie:123}", autoRefreshed = true)
private String testProperties; @ResponseBody
@GetMapping("/nacos/test")
public String test(){
return testProperties;
} @ResponseBody
@RequestMapping(value = "/readiness", method = RequestMethod.GET)
public Object readiness(HttpServletRequest request) {
boolean isConfigReadiness = true;
boolean isNamingReadiness = false; if (isConfigReadiness && isNamingReadiness) {
return ResponseEntity.ok().body("OK");
} if (!isConfigReadiness && !isNamingReadiness) {
return ResponseEntity.status(500).body("Config and Naming are not in readiness");
} if (!isConfigReadiness) {
return ResponseEntity.status(500).body("Config is not in readiness");
} return ResponseEntity.status(500).body("Naming is not in readiness");
}
}

我们直接用postman请求下,直接返回结果了,

我们在nacos中的相关配置如下:

这样我就很方便的把我们需要的值取过来了,而且不是通过DB,cache方式获取,而是在远程nacos中配置,我们能够实时获取的到;

那么问题就来了,nacos是怎么做到的呢,当然nacos的功能远不止于此;

我们就根据这个作为一个最直观的入口,跟下代码:

在nacos中发布的操作

找代码v1/cs/configs,当然再试的时候可以找V1/CS

Constants.java
    
public static final String BASE_PATH = "/v1/cs";
public static final String CONFIG_CONTROLLER_PATH = BASE_PATH + "/configs";
/**
* 增加或更新非聚合数据。
*
* @throws NacosException
*/
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public Boolean publishConfig(HttpServletRequest request, HttpServletResponse response,
@RequestParam("dataId") String dataId, @RequestParam("group") String group,
@RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY)
String tenant,
@RequestParam("content") String content,
@RequestParam(value = "tag", required = false) String tag,
@RequestParam(value = "appName", required = false) String appName,
@RequestParam(value = "src_user", required = false) String srcUser,
@RequestParam(value = "config_tags", required = false) String configTags,
@RequestParam(value = "desc", required = false) String desc,
@RequestParam(value = "use", required = false) String use,
@RequestParam(value = "effect", required = false) String effect,
@RequestParam(value = "type", required = false) String type,
@RequestParam(value = "schema", required = false) String schema)
throws NacosException {
final String srcIp = RequestUtil.getRemoteIp(request);
String requestIpApp = RequestUtil.getAppName(request);
// 参数校验
ParamUtils.checkParam(dataId, group, "datumId", content);
ParamUtils.checkParam(tag); Map<String, Object> configAdvanceInfo = new HashMap<String, Object>(10);
if (configTags != null) {
configAdvanceInfo.put("config_tags", configTags);
}
if (desc != null) {
configAdvanceInfo.put("desc", desc);
}
if (use != null) {
configAdvanceInfo.put("use", use);
}
if (effect != null) {
configAdvanceInfo.put("effect", effect);
}
if (type != null) {
configAdvanceInfo.put("type", type);
}
if (schema != null) {
configAdvanceInfo.put("schema", schema);
}
ParamUtils.checkParam(configAdvanceInfo);
// 白名单
if (AggrWhitelist.isAggrDataId(dataId)) {
log.warn("[aggr-conflict] {} attemp to publish single data, {}, {}",
RequestUtil.getRemoteIp(request), dataId, group);
throw new NacosException(NacosException.NO_RIGHT, "dataId:" + dataId + " is aggr");
} final Timestamp time = TimeUtils.getCurrentTime();
String betaIps = request.getHeader("betaIps");
ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);

if (StringUtils.isBlank(betaIps)) {
if (StringUtils.isBlank(tag)) {
// 插入或者更新
persistService.insertOrUpdate(srcIp, srcUser, configInfo, time, configAdvanceInfo, false);
// 发布事件
EventDispatcher.fireEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime()));
} else {
persistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser, time, false);
EventDispatcher.fireEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
}
} else { // beta publish
persistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser, time, false);
EventDispatcher.fireEvent(new ConfigDataChangeEvent(true, dataId, group, tenant, time.getTime()));
}
ConfigTraceService.logPersistenceEvent(dataId, group, tenant, requestIpApp, time.getTime(),
LOCAL_IP, ConfigTraceService.PERSISTENCE_EVENT_PUB, content); return true;
}

就从这个controller去做分析,其实核心一下就能看出来就是一个insertOrUpdate,一个fireEvent;

insertorUpdate这个nacos没有用mybatis、hibernate这些ORM框架(减少依赖耦合吧);

下方高能!!!!!!!!!!!!!!!!!!!!!!!!!!

直接用jdbcTemblate就行数据插入,大家在进行debug的时候注意下,jdbcTemplate中有个事务超时时间,

nacos中有两种模板,

 private JdbcTemplate jt;
private TransactionTemplate tjt;

这个他都设置了默认超时时间(还有另外一个地方一个3秒一个5秒,建议大家在DEBUG的时候把这个时间调大一点,300,,500^_^)

BasicDataSourceServiceImpl.java
 @PostConstruct
public void init() {
queryTimeout = NumberUtils.toInt(System.getProperty("QUERYTIMEOUT"), 300);
jt = new JdbcTemplate();
/**
* 设置最大记录数,防止内存膨胀
*/
jt.setMaxRows(50000);
jt.setQueryTimeout(queryTimeout); testMasterJT = new JdbcTemplate();
testMasterJT.setQueryTimeout(queryTimeout); testMasterWritableJT = new JdbcTemplate();
/**
* 防止login接口因为主库不可用而rt太长
*/
testMasterWritableJT.setQueryTimeout(1);
/**
* 数据库健康检测
*/
testJTList = new ArrayList<JdbcTemplate>();
isHealthList = new ArrayList<Boolean>(); tm = new DataSourceTransactionManager();
tjt = new TransactionTemplate(tm);
/**
* 事务的超时时间需要与普通操作区分开
*/
tjt.setTimeout(TRANSACTION_QUERY_TIMEOUT);
if (!STANDALONE_MODE || PropertyUtil.isStandaloneUseMysql()) {
try {
reload();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(DB_LOAD_ERROR_MSG);
} TimerTaskService.scheduleWithFixedDelay(new SelectMasterTask(), 10, 10,
TimeUnit.SECONDS);
TimerTaskService.scheduleWithFixedDelay(new CheckDBHealthTask(), 10, 10,
TimeUnit.SECONDS);
}
}

看下config_info的表结构,他这边判断更新的依据就是直接插入,

捕获唯一索引的异常,data_id+group+tenant重复的话就会抛出异常,捕获这个异常进行更新操作!

表结构

persistService.insertOrUpdate
 /**
* 写入主表,插入或更新
*/
public void insertOrUpdate(String srcIp, String srcUser, ConfigInfo configInfo, Timestamp time,
Map<String, Object> configAdvanceInfo, boolean notify) {
try {
addConfigInfo(srcIp, srcUser, configInfo, time, configAdvanceInfo, notify);
} catch (DataIntegrityViolationException ive) { // 唯一性约束冲突
updateConfigInfo(configInfo, srcIp, srcUser, time, configAdvanceInfo, notify);
}
}

后面就是最核心的地方了

EventDispatcher.fireEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime()));

通过event的dispatcher,进行相应的操作,这个就是观察者模式的体现,Apollo中也有类似的操作;

篇幅过长,这里就不再追加了,看下一篇吧^_^

Nacos深入浅出(二)的更多相关文章

  1. java代理的深入浅出(二)-CGLIB

    java代理的深入浅出(二)-CGLIB 1.基本原理 CGLIB的原理就是生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法.在子类中拦截所有父类方法的调用,拦截下来交给设置的Me ...

  2. 02-Unity深入浅出(二)

    一. Unity声明周期 Unity容器为我们提供了6种生命周期,便于我们根据项目需求来选择使用. (1). 瞬时.默认省略即为瞬时,无论单线程还是多线程,每次都重新创建对象.new Transien ...

  3. Nacos深入浅出(十)

    基本上到第9篇,整个请求的一套就结束了,感觉这里跳跳绕绕很多东西,下面我们来做个总结:从Nacos配置平台修改,到Client请求更新,事件触发去取值返回给客户端,整个过程感觉只分析到了4.5层的深度 ...

  4. Nacos深入浅出(九)

    然而Nacos的发布操作并不是上面我们想的那样通过代理去实现,通过下面的代码我们分析下: public class NacosConfigurationPropertiesBindingPostPro ...

  5. Nacos深入浅出(八)

    Nacos-spring-context.java 感觉这个后台要比之前的Nacos复杂多了,涉及到很多基础的概念,慢慢看,这个后面慢慢更新解析过程 看到他的目录结构一个是基于注解,一个是XML的解析 ...

  6. Nacos深入浅出(七)

    大家可以把这个也下载下来,结合之前的Nacos一起来看下,感觉前面几篇看了好像冰山一角的感觉 学无止境! https://github.com/nacos-group/nacos-spring-pro ...

  7. Nacos深入浅出(六)

    其实我们发现在我们本地新生成了文件,这个文件就是nacos; 这个文件怎么那么眼熟,不就是我们的controller中的注解里面的参数value么: @Controller @NacosPropert ...

  8. Nacos深入浅出(五)

    四中标色的代码 result = ConfigService.dump(dataId, group, tenant, cf.getContent(), lastModified); 我们看下这个方法 ...

  9. Nacos深入浅出(四)

    private void executeAsyncInvoke() { while (!queue.isEmpty()) { NotifySingleTask task = queue.poll(); ...

随机推荐

  1. jQuery 网页禁止复制

    <script type="text/javascript">    $(document).ready(function(){         $('#文本框id') ...

  2. P3715 [BJOI2017]魔法咒语

    P3715 [BJOI2017]魔法咒语 用基本词汇组成\(L\)长度的单词,其中不能包含禁忌词汇 用禁忌词汇建强大的\(tire\)图 解决: 分类讨论,\(L<=100\)用普通dp暴力在\ ...

  3. event loop笔记

    注意四个对象: 主进程 执行栈 异步进程 任务队列 1.主进程读取js代码,形成对应的堆和执行栈(此时在同步环境) 2.当遇见异步任务,转交给异步进程进行处理 3.异步任务完成,将其推入任务队列 4. ...

  4. 标准兼容HTML5输入框提示信息的插件iHolder_v0.1.06.21.2014_预览版

    由于版面限制,简单说下,详细的内容及在线预览.预览版压缩包,见这里http://levi.cg.am/archives/3507 为什么说是标准兼容: 因为大多数placeholder插件是这样兼容的 ...

  5. 苹果手机app试玩赚钱平台汇总

    注意: 微信扫码下载,绑定手机号和微信.才能提现 每天3点更新任务,4点最多! | 平台 | 提现额 | 任务量| 推荐强度 | 扫码 | 1.小鱼,10元,大量,强推! →点开扫码 2.天天飞燕,5 ...

  6. vim 编辑器IDE版

    wget https://raw.github.com/ma6174/vim/master/setup.sh -O ma6174_vim_setup.sh && bash ma6174 ...

  7. BZOJ-3626:LCA(离线+树链剖分)

    Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...

  8. Python中with...as的用法

    原文:http://blog.csdn.net/magicharvey/article/details/20226969 这个语法是用来代替传统的try...finally语法的. with EXPR ...

  9. MySql介绍及优化(1)

    mysql 数据库 1.是关系型数据库: 2.体积小.支持多处理器.开源.免费 3.在 Internet 中小型网站中的使用率尤其高 mysql 数据库开发常见问题及优化 一.库表设计 1.1 引擎选 ...

  10. 安装时后的idea,项目不能运行,pom.xml文件不能下载到本地仓库,maven配置是正确的

    安装时后的idea,项目不能运行,pom.xml文件不能下载到本地仓库,maven配置是正确的 项目上传到svn后,同事下载项目后,没有识别出来mavn中的pom.xml文件,导致idea不能自动下载 ...