首页 文章 精选 留言 我的

精选列表

搜索[fota升级],共10000篇文章
优秀的个人博客,低调大师

Spring Cloud 升级之路 - 2020.0.x - 5. 理解 NamedContextF

spring-cloud-commons 中参考了 spring-cloud-netflix 的设计,引入了 NamedContextFactory 机制,一般用于对于不同微服务的客户端模块使用不同的 子 ApplicationContext 进行配置。 spring-cloud-commons 是 Spring Cloud 对于微服务基础组件的抽象。在一个微服务中,调用微服务 A 与调用微服务 B 的配置可能不同。比较简单的例子就是,A 微服务是一个简单的用户订单查询服务,接口返回速度很快,B 是一个报表微服务,接口返回速度比较慢。这样的话我们就不能对于调用微服务 A 和微服务 B 使用相同的超时时间配置。还有就是,我们可能对于服务 A 通过注册中心进行发现,对于服务 B 则是通过 DNS 解析进行服务发现,所以对于不同的微服务我们可能使用不同的组件,在 Spring 中就是使用不同类型的 Bean。 在这种需求下,不同微服务的客户端有不同的以及相同的配置,有不同的 Bean,也有相同的 Bean。所以,我们可以针对每一个微服务将他们的 Bean 所处于 ApplicationContext 独立开来,不同微服务客户端使用不同的 ApplicationContext。NamedContextFactory 就是用来实现这种机制的。 通过实例了解 NamedContextFactory 的使用 编写源码: package com.github.hashjang.spring.cloud.iiford.service.common; import org.junit.Assert; import org.junit.Test; import org.springframework.cloud.context.named.NamedContextFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import java.util.List; import java.util.Objects; public class CommonNameContextTest { private static final String PROPERTY_NAME = "test.context.name"; @Test public void test() { //创建 parent context AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); //添加 BaseConfig 相关配置 parent.register(BaseConfig.class); //初始化 parent parent.refresh(); //创建 testClient1,默认配置使用 ClientCommonConfig TestClient testClient1 = new TestClient(ClientCommonConfig.class); //创建 service1 与 service2 以及指定对应额外的配置类 TestSpec testSpec1 = new TestSpec("service1", new Class[]{Service1Config1.class, Service1Config2.class}); TestSpec testSpec2 = new TestSpec("service2", new Class[]{Service2Config.class}); //设置 parent ApplicationContext 为 parent testClient1.setApplicationContext(parent); //将 service1 与 service2 的配置加入 testClient1 testClient1.setConfigurations(List.of(testSpec1, testSpec2)); BaseBean baseBean = testClient1.getInstance("service1", BaseBean.class); System.out.println(baseBean); //验证正常获取到了 baseBean Assert.assertNotNull(baseBean); ClientCommonBean commonBean = testClient1.getInstance("service1", ClientCommonBean.class); System.out.println(commonBean); //验证正常获取到了 commonBean Assert.assertNotNull(commonBean); Service1Bean1 service1Bean1 = testClient1.getInstance("service1", Service1Bean1.class); System.out.println(service1Bean1); //验证正常获取到了 service1Bean1 Assert.assertNotNull(service1Bean1); Service1Bean2 service1Bean2 = testClient1.getInstance("service1", Service1Bean2.class); System.out.println(service1Bean2); //验证正常获取到了 service1Bean2 Assert.assertNotNull(service1Bean2); BaseBean baseBean2 = testClient1.getInstance("service2", BaseBean.class); System.out.println(baseBean2); //验证正常获取到了 baseBean2 并且 baseBean2 就是 baseBean Assert.assertEquals(baseBean, baseBean2); ClientCommonBean commonBean2 = testClient1.getInstance("service2", ClientCommonBean.class); System.out.println(commonBean2); //验证正常获取到了 commonBean2 并且 commonBean 和 commonBean2 不是同一个 Assert.assertNotNull(commonBean2); Assert.assertNotEquals(commonBean, commonBean2); Service2Bean service2Bean = testClient1.getInstance("service2", Service2Bean.class); System.out.println(service2Bean); //验证正常获取到了 service2Bean Assert.assertNotNull(service2Bean); } @Configuration(proxyBeanMethods = false) static class BaseConfig { @Bean BaseBean baseBean() { return new BaseBean(); } } static class BaseBean {} @Configuration(proxyBeanMethods = false) static class ClientCommonConfig { @Bean ClientCommonBean clientCommonBean(Environment environment, BaseBean baseBean) { //在创建 NamedContextFactory 里面的子 ApplicationContext 的时候,会指定 name,这个 name 对应的属性 key 即 PROPERTY_NAME return new ClientCommonBean(environment.getProperty(PROPERTY_NAME), baseBean); } } static class ClientCommonBean { private final String name; private final BaseBean baseBean; ClientCommonBean(String name, BaseBean baseBean) { this.name = name; this.baseBean = baseBean; } @Override public String toString() { return "ClientCommonBean{" + "name='" + name + '\'' + ", baseBean=" + baseBean + '}'; } } @Configuration(proxyBeanMethods = false) static class Service1Config1 { @Bean Service1Bean1 service1Bean1(ClientCommonBean clientCommonBean) { return new Service1Bean1(clientCommonBean); } } static class Service1Bean1 { private final ClientCommonBean clientCommonBean; Service1Bean1(ClientCommonBean clientCommonBean) { this.clientCommonBean = clientCommonBean; } @Override public String toString() { return "Service1Bean1{" + "clientCommonBean=" + clientCommonBean + '}'; } } @Configuration(proxyBeanMethods = false) static class Service1Config2 { @Bean Service1Bean2 service1Bean2() { return new Service1Bean2(); } } static class Service1Bean2 { } @Configuration(proxyBeanMethods = false) static class Service2Config { @Bean Service2Bean service2Bean(ClientCommonBean clientCommonBean) { return new Service2Bean(clientCommonBean); } } static class Service2Bean { private final ClientCommonBean clientCommonBean; Service2Bean(ClientCommonBean clientCommonBean) { this.clientCommonBean = clientCommonBean; } @Override public String toString() { return "Service2Bean{" + "clientCommonBean=" + clientCommonBean + '}'; } } static class TestSpec implements NamedContextFactory.Specification { private final String name; private final Class<?>[] configurations; public TestSpec(String name, Class<?>[] configurations) { this.name = name; this.configurations = configurations; } @Override public String getName() { return name; } @Override public Class<?>[] getConfiguration() { return configurations; } } static class TestClient extends NamedContextFactory<TestSpec> { public TestClient(Class<?> defaultConfigType) { super(defaultConfigType, "testClient", PROPERTY_NAME); } } } 结果输出为: com.github.hashjang.spring.cloud.iiford.service.common.CommonNameContextTest$BaseBean@3faf2e7d ClientCommonBean{name='service1', baseBean=com.github.hashjang.spring.cloud.iiford.service.common.CommonNameContextTest$BaseBean@3faf2e7d} Service1Bean1{clientCommonBean=ClientCommonBean{name='service1', baseBean=com.github.hashjang.spring.cloud.iiford.service.common.CommonNameContextTest$BaseBean@3faf2e7d}} com.github.hashjang.spring.cloud.iiford.service.common.CommonNameContextTest$Service1Bean2@4648ce9 com.github.hashjang.spring.cloud.iiford.service.common.CommonNameContextTest$BaseBean@3faf2e7d ClientCommonBean{name='service2', baseBean=com.github.hashjang.spring.cloud.iiford.service.common.CommonNameContextTest$BaseBean@3faf2e7d} Service2Bean{clientCommonBean=ClientCommonBean{name='service2', baseBean=com.github.hashjang.spring.cloud.iiford.service.common.CommonNameContextTest$BaseBean@3faf2e7d}} 代码中实现了这样一个 Context 结构: 图中的被包含的 ApplicationContext 可以看到外层 ApplicationContext 的 Bean,也就是通过对被包含的 ApplicationContext 调用 getBean(xxx) 可以获取到外层 ApplicationContext 的 Bean (其实外层就是 parent ApplicationContext),但是外层的看不到内层私有的 Bean。 在我们的测试代码中,首先,创建了一个 AnnotationConfigApplicationContext。这个其实就是模拟了我们平常使用 Spring 框架的时候的根核心 ApplicationContext,所以我们将其命名为 parent。我们向里面注册了 BaseConfig,BaseConfig 里面的 BaseBean 会注册到 parent。之后我们 建 testClient1,默认配置使用 ClientCommonConfig。如果我们指定了 testClient1 的 parent ApplicationContext 为 parent,那么 parent 里面的 Bean 都能被 testClient1 里面的子 ApplicationContext 访问到。然后,我们创建 service1 与 service2 以及指定对应额外的配置类。service1 会创建 ClientCommonConfig、Service1Config1 和 Service1Config2 里面配置的 Bean。service2 会创建 ClientCommonConfig 和 Service2Config 里面配置的 Bean。 NamedContextFactory 的基本原理以及源码 NamedContextFactory 的核心方法是 public &lt;T&gt; T getInstance(String name, Class&lt;T&gt; type),通过这个方法获取 NamedContextFactory 里面的子 ApplicationContext 里面的 Bean。源码是: NamedContextFactory.java /** * 获取某个 name 的 ApplicationContext 里面的某个类型的 Bean * @param name 子 ApplicationContext 名称 * @param type 类型 * @param <T> Bean 类型 * @return Bean */ public <T> T getInstance(String name, Class<T> type) { //获取或者创建对应名称的 ApplicationContext AnnotationConfigApplicationContext context = getContext(name); try { //从对应的 ApplicationContext 获取 Bean,如果不存在则会抛出 NoSuchBeanDefinitionException return context.getBean(type); } catch (NoSuchBeanDefinitionException e) { //忽略 NoSuchBeanDefinitionException } //没找到就返回 null return null; } protected AnnotationConfigApplicationContext getContext(String name) { //如果 map 中不存在,则创建 if (!this.contexts.containsKey(name)) { //防止并发创建多个 synchronized (this.contexts) { //再次判断,防止有多个等待锁 if (!this.contexts.containsKey(name)) { this.contexts.put(name, createContext(name)); } } } return this.contexts.get(name); } //根据名称创建对应的 context protected AnnotationConfigApplicationContext createContext(String name) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); //如果 configurations 中有对应名称的配置类,则注册之 if (this.configurations.containsKey(name)) { for (Class<?> configuration : this.configurations.get(name).getConfiguration()) { context.register(configuration); } } //如果 configurations 中有名称开头为 default. 的配置类,则注册之 for (Map.Entry<String, C> entry : this.configurations.entrySet()) { if (entry.getKey().startsWith("default.")) { for (Class<?> configuration : entry.getValue().getConfiguration()) { context.register(configuration); } } } //注册 PropertyPlaceholderAutoConfiguration,这样可以解析 spring boot 相关的 application 配置 //注册默认的配置类 defaultConfigType context.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType); //将当前 context 的名称,放入对应的属性中,在配置类中可能会用到 //我们上面举得例子,就是通过 environment.getProperty() 获取了这个属性 context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName, Collections.<String, Object>singletonMap(this.propertyName, name))); if (this.parent != null) { // Uses Environment from parent as well as beans context.setParent(this.parent); //spring boot 可以打包成一种 fatjar 的形式,将依赖的 jar 包都打入同一个 jar 包中 //fatjar 中的依赖,通过默认的类加载器是加载不正确的,需要通过定制的类加载器 //由于 JDK 11 LTS 相对于 JDK 8 LTS 多了模块化,通过 ClassUtils.getDefaultClassLoader() 有所不同 //在 JDK 8 中获取的就是定制的类加载器,JDK 11 中获取的是默认的类加载器,这样会有问题 //所以,这里需要手动设置当前 context 的类加载器为父 context 的类加载器 context.setClassLoader(this.parent.getClassLoader()); } //生成展示名称 context.setDisplayName(generateDisplayName(name)); context.refresh(); return context; }

优秀的个人博客,低调大师

Darkside勒索软件攻击升级,不给钱就“做空”企业

根据最新的动态,勒索软件Darkside正采用全新技术针对已经在纳斯达克或者其他股票市场上市的公司,试图通过网络攻击手段做空企业,让公司股价下跌,增加受害者的压力。 4月20日,DarkSide的数据泄露网站上公开写道:“我们的团队和合作伙伴加密了许多纳斯达克和其他证券交易所上市公司的数据。如果公司拒绝支付赎金,我们准备公布攻击信息,从而在股票减持价格中获利。” 这也就是说,一旦有不道德的交易者愿意接受DarkSide的报价,那么该勒索团伙就可以通过售卖上市公司内幕信息牟利,当交易者数量足够多的情况下,公司的股票完全可能因人为操纵而下跌。对于勒索团伙来说,其目的在于加大恐吓,逼迫受害者支付赎金,但做空的风险和可能性似乎是存在的。 从投资者角度来看,内幕交易活动会对公司的股票产生多大影响?穆迪投资的副总裁兼网络风险分析师Leroy Terrelonge表示:股票的波动通常是短暂的,交易者从黑客那里得到的任何事先通知最终都会随着市场上其他人同样获得这些信息后而不再产生影响。也就是当正确的信息通过市场过滤,证券价格就会回到之前的水平。 参考来源:scmagazine 【责任编辑:赵宁宁 TEL:(010)68476606】

优秀的个人博客,低调大师

Fizz Gateway 1.5.1 发布,更加稳定的核心依赖库升级

Changelog: 修复固定值被引用值覆盖的问题 修复在更新路由时路由与appid的关系丢失的问题 更新管理后台的bladex依赖到v2.7.2 Fixed the issue where fixed values were overwritten by reference values when expecting merge in path mapping Fixed the issue where the relationship between route and appid was lost when updating the route Update the version of core of fizz-manager to v2.7.2 Fizz Gateway是什么? A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的微服务网关,能够实现热服务编排、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。 产品特性 集群管理:Fizz网关节点是无状态的,配置信息自动同步,支持节点水平拓展和多集群部署。 服务编排:支持HTTP、Dubbo、gRPC协议热服务编排能力,支持前后端编码,随时随地更新API。 负载均衡:支持round-robin负载均衡。 服务发现:支持从Eureka或Nacos注册中心发现后端服务器。 配置中心:支持接入apollo配置中心。 HTTP反向代理:隐藏真实后端服务,支持 Rest API反向代理。 访问策略:支持不同策略访问不同的API、配置不同的鉴权等。 IP黑白名单:支持配置IP黑白名单。 自定义插件:强大的插件机制支持自由扩展。 可扩展:简单易用的插件机制方便扩展功能。 高性能:性能在众多网关之中表现优异。 版本控制:支持操作的发布和多次回滚。 管理后台:通过管理后台界面对网关集群进行各项配置。 回调管理:支持回调的管理、订阅、重放、以及日志

优秀的个人博客,低调大师

kkFileView-v3.3.0 年终版本发布,架构功能全面升级

kkFileView 是以 spring boot 构建的文件在线预览的项目,已评码云 GVP 项目。以最宽松的 Apache 协议开源。此次 v3.3.0 版本发布,是 2020 最后一个重大迭代版本发布,从 v2 到 v3 版本,是架构模式和代码精进的全面提升。Kkfileview从开源至今三年,力争做开源文件在线预览解决方案的标杆项目。感谢新老用户的支持,Kkfileview在gitee平台收获了7000+的star。从v3版本开始,告别2020,Kkfileview将开启新的迭代篇章。 本次版本迭代内容 2020 年年终大版本更新,架构全面设计,代码全面重构,代码质量全面提升,二次开发更便捷,欢迎拉源码品鉴 v3.3.0 Releases 地址:https://gitee.com/kekingcn/file-online-preview/releases/v3.3.0 架构模块调整,大量的代码重构,代码质量提升 N 个等级,欢迎品鉴 增强 XML 文件预览效果,新增 XML 文档树结构预览 新增 markdown 文件预览支持,预览支持md渲染和源文本切换支持 切换底层 web server 为 jetty,解决这个 issue:https://github.com/kekingcn/kkFileView/issues/168 引入 cpdetector,解决文件编码识别问题 url 采用 base64+urlencode 双编码,彻底解决各种奇葩文件名预览问题 新增配置项 office.preview.switch.disabled,控制 office 文件预览切换开关 优化文本类型文件预览逻辑,采用 Base64 传输内容,避免预览时再次请求文件内容 office 预览图片模式禁用图片放大效果,达到图片和 pdf 预览效果一致的体验 直接代码静态设置 pdfbox 兼容低版本 jdk,在 IDEA中 运行也不会有警告提示 移除 guava、hutool 等非必须的工具包,减少代码体积 Office 组件加载异步化,提速应用启动速度最快到5秒内 合理设置预览消费队列的线程数 修复压缩包里文件再次预览失败的 bug 修复图片预览的 bug 新增 markdown 文档预览支持 新增XML文档树预览效果

优秀的个人博客,低调大师

云办公系统 skyeye v3.3.9 发布,ERP 模块升级

云办公系统 skyeye v3.3.9发布。 erp:https://gitee.com/doc_wei01/erp-pro OA:https://gitee.com/doc_wei01/skyeye 项目开发计划:https://docs.qq.com/doc/DQlRxcVRMWWVjbU1i?_from=1&disableReturnList=1,有问题可以联系作者,详情请看开发计划。 更新内容: 收款单操作选择客户方式修改 收入单操作选择客户方式修改 新增个人中心界面(简易版) 国际化英文版修改中(耗时耗力)... 效果图: 效果图 效果图

优秀的个人博客,低调大师

HBase 如何减少升级时重启rs节点造成的影响

最近被问到这个问题,一时没有很好的回答,事后仔细思考了下,整理如下。 rs节点重启对于应用的影响可分为如下2个阶段: region不可用 region读取慢 不可用的优化 从rs停止到各个region重新上线前都处于不可用阶段,其中包含了master感知到有rs退出,进而调度执行scp的过程,详细的过程可以参考我的另外一篇文章《HBase2.0 regionServer退出处理流程》,尤其是末尾链接中的详细流程图; 而不可用阶段最为耗时的部分应该是scp的执行阶段,其核心部分伪代码如下: if(carryingMeta) { split meta log; assign meta region; wait meta loaded; } split log; assign reigons; 因此减少不可用的时间主要就是简化上述过程,可用的手段有如下2个: 重启rs前先执行flush,从而减少split log以及后续replay log所需的时间; 重启rs前先把region move到其它节点去,这个方法需要获取region信息并且要自己指定目标节点,稍微麻烦一些,但是效果更彻底,因为完全不受scp执行时间影响,不可用时间缩减到1个ap的时间; 还有就是利用region replica特性,在主region不可用阶段,也能够利用副本提供读服务,这个方法的缺点,1是副本要消耗额外的io和内存资源,2是写请求依然不可用; 读取慢的优化 读取慢的原因,1是在新的rs上region的locality很可能会降低,2是blockcache是空的; locality的问题,正常情况下在rs重启完成后,balancer会基于locality的考虑将region迁移回原rs,但由于balance的过程还受其它因素影响,所以也并不必然,因此还是主动move更好一些; 如果已将自动balance关闭, 那主动move回原节点就是自然而然的了; blockcache的问题,可以考虑在rs停止前将其保存在本地磁盘上,重新启动时进行加载,印象中之前看过一篇分享文章中提到过这个优化;

优秀的个人博客,低调大师

WGCLOUD 监控系统,升级数据扫描机制,提升性能

WGCLOUD基于java语言开发,是微服务架构构建监控系统,支持高并发高性能高可用,核心模块包括:服务器集群监控,ES集群状态监控,CPU监控,内存监控,数据监控(mysql,postgresql,oracle,sqlserver,db2),服务心跳检测,应用进程管理,磁盘IO监控,系统负载监控,监控告警信息推送。 此次更新,新增数据监控间隔时间配置,服务接口监控间隔时间配置,使之更快更灵活。根据个人需求酌情修改扫描时间,时间间隔越短,监控更实时,但是server压力相应会加大,根据服务器配置观察调整。 base: #登陆账号admin的密码 admindPwd: 111111 #通信token,agent端和此保持一致 wgToken: wgcloud #是否开启公众看板,yes开启,no关闭,公众看板页面无需登陆 dashView: yes #数据表监控间隔,单位毫秒,默认60分钟 dbTableTimes: 3600000 #服务接口监控间隔,单位毫秒,默认10分钟 heathTimes: 600000

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册