Dubbo加载配置文件方式,加载流程,加载配置文件源码解析
配置方法
API配置
以Java编码的方式组织配置,Dubbo3配置API详解 :https://dubbo.apache.org/zh/docs3-v2/java-sdk/reference-manual/config/api/#bootstrap-api
public static void main(String[] args) throws IOException {ServiceConfig<GreetingsService> service = new ServiceConfig<>();service.setApplication(new ApplicationConfig("first-dubbo-provider"));service.setRegistry(new RegistryConfig("multicast://224.5.6.7:1234"));service.setInterface(GreetingsService.class);service.setRef(new GreetingsServiceImpl());service.export();System.out.println("first-dubbo-provider is running.");System.in.read();
}
xml配置
以XML方式配置各种组件,支持与Spring无缝集成
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder/><dubbo:application name="demo-provider"/><dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/><dubbo:provider token="true"/><bean id="demoService" class="org.apache.dubbo.samples.basic.impl.DemoServiceImpl"/><dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService" ref="demoService"/></beans>
Annotation 结合SpringBoot配置
以注解方式暴露服务和引用服务接口,支持与Spring无缝集成
- 注解有 @DubboService、@DubboReference 与 @EnableDubbo。
其中 @DubboService 与 @DubboReference 用于标记 Dubbo 服务
@EnableDubbo 启动 Dubbo 相关配置并指定 Spring Boot 扫描包路径。
- 配置文件 application.properties 或 application.yml
@Service
与 @Reference
注解从 3.0 版本开始就已经废弃,改用 @DubboService,@DubboReference
,以区别于 Spring 的 @Service,@Reference
注解
@DubboService(version = "1.0.0", group = "dev", timeout = 5000,registry="zk-registry")
@DubboReference(version = "1.0.0", group = "dev", timeout = 5000)
注解中的参数有限,如果需要可以使用dubbo.properties 或者javaconfig代替,或者通过SpringBoot的配置文件结合
SpringBoot配置文件
spring.application.name=dubbo--provider-sample
dubbo.scan.base-packages=com.alibaba.boot.dubbo.demo.provider.service# Dubbo Application
## The default value of dubbo.application.name is ${spring.application.name}
## dubbo.application.name=${spring.application.name}# Dubbo Protocol
dubbo.protocol.name=dubbo
dubbo.protocol.port=12345## Dubbo Registry
dubbo.registry.address=N/A## DemoService version
demo.service.version=1.0.0
JavaConfig
JavaConfig即使用 @Bean的方式添加到Spring容器中
@Configuration
public class Configuration {@Beanpublic ServiceConfig demoService() {ServiceConfig service = new ServiceConfig();service.setInterface(DemoService.class);service.setRef(new DemoServiceImpl());service.setGroup("dev");service.setVersion("1.0.0");Map<String, String> parameters = new HashMap<>();service.setParameters(parameters);return service;}
}
dubbo.properties
参考
dubbo.service.org.apache.dubbo.springboot.demo.DemoService.timeout=5000
dubbo.service.org.apache.dubbo.springboot.demo.DemoService.parameters=[{myKey:myValue},{anotherKey:anotherValue}]
dubbo.reference.org.apache.dubbo.springboot.demo.DemoService.timeout=6000
配置加载流程
- JVM System Properties,JVM -D 参数
- System environment,JVM进程的环境变量
- Externalized Configuration,外部化配置,从配置中心读取
- Application Configuration,应用的属性配置,从Spring应用的Environment中提取"dubbo"打头的属性集
- API / XML /注解等编程接口采集的配置可以被理解成配置来源的一种,是直接面向用户编程的配置采集方式
- 从classpath读取配置文件 dubbo.properties
关于dubbo.properties属性:
- 如果在 classpath 下有超过一个 dubbo.properties 文件,比如,两个 jar 包都各自包含了 dubbo.properties,dubbo 将随机选择一个加载,并且打印错误日志。
- Dubbo 可以自动加载 classpath 根目录下的 dubbo.properties,但是你同样可以使用 JVM 参数来指定路径:
-Ddubbo.properties.file=xxx.properties
。
常用配置组件如下:
- application: Dubbo应用配置
- registry: 注册中心
- protocol: 服务提供者RPC协议
- config-center: 配置中心
- metadata-report: 元数据中心
- service: 服务提供者配置
- reference: 远程服务引用配置
- provider: service的默认配置或分组配置
- consumer: reference的默认配置或分组配置
- module: 模块配置
- monitor: 监控配置
- metrics: 指标配置
- ssl: SSL/TLS配置
属性覆盖
发生属性覆盖可能有两种情况,并且二者可能是会同时发生的:
- 不同配置源配置了相同的配置项
- 相同配置源,但在不同层次指定了相同的配置项
不同配置源
按配置加载流程 从上到下覆盖, JVM -D 优先级最高,dubbo.properties 优先级最低
相同配置源
属性覆盖是指用配置的属性值覆盖config bean实例的属性,类似Spring PropertyOverrideConfigurer
的作用。
但与PropertyOverrideConfigurer
的不同之处是,Dubbo的属性覆盖有多个匹配格式,优先级从高到低依次是:
#1. 指定id的实例级配置 dubbo.{config-type}s.{config-id}.{config-item}={config-item-value}
#2. 指定name的实例级配置 dubbo.{config-type}s.{config-name}.{config-item}={config-item-value}
#3. 应用级配置(单数配置) dubbo.{config-type}.{config-item}={config-item-value}
属性覆盖处理流程:
按照优先级从高到低依次查找,如果找到此前缀开头的属性,则选定使用这个前缀提取属性,忽略后面的配置。
配置加载源码解析
DefaultApplicationDeployer#initialize()
@Override
public void initialize() {if (initialized) {return;}// Ensure that the initialization is completed when concurrent callssynchronized (startLock) {if (initialized) {return;}// register shutdown hookregisterShutdownHook();startConfigCenter();loadApplicationConfigs();initModuleDeployers();// @since 2.7.8startMetadataCenter();initialized = true;if (logger.isInfoEnabled()) {logger.info(getIdentifier() + " has been initialized!");}}
}
始化过程中会先启动配置中心配置信息处理,然后 调用加载初始化应用程序配置方法loadApplicationConfigs()
进行配置加载
Dubbo框架的配置项比较繁多,为了更好地管理各种配置,将其按照用途划分为不同的组件,最终所有配置项都会汇聚到URL中,传递给后续处理模块。
配置信息的初始化回顾
在创建dubbo环境时,ModuleEnvironment环境信息 getApplicationModel().getModelEnvironment()获取对象时,使用spi扩展加载ModuleEnvironment,会触发 ExtensionLoader#initExtension ()
对象如下代码所示:
public ModuleEnvironment(ModuleModel moduleModel) {super(moduleModel);this.moduleModel = moduleModel;this.applicationDelegate = moduleModel.getApplicationModel().getModelEnvironment();
}@Override
public ModuleEnvironment getModelEnvironment() {if (moduleEnvironment == null) {moduleEnvironment = (ModuleEnvironment) this.getExtensionLoader(ModuleExt.class).getExtension(ModuleEnvironment.NAME);}return moduleEnvironment;
}private void initExtension(T instance) {if (instance instanceof Lifecycle) {Lifecycle lifecycle = (Lifecycle) instance;lifecycle.initialize();}}
属性加载
Environment中属性的初始化方法 initialize()
这个初始化方法对应ModuleEnvironment的父类型Environment中的初始化方法如下
@Override
public void initialize() throws IllegalStateException {if (initialized.compareAndSet(false, true)) {//加载在JVM或者环境变量指定的dubbo.properties配置文件 配置的key为dubbo.properties.file ,如果未指定则查找类路径下的dubbo.propertiesthis.propertiesConfiguration = new PropertiesConfiguration(scopeModel);//系统JVM参数的配置无需我们来加载到内存,系统已经加载好了放到了System中,我们只需System.getProperty(key)来调用this.systemConfiguration = new SystemConfiguration();//系统环境变量的配置,无需我们来加载到内存,系统已经加载好了放到了System中,我们只需System.getenv(key)来获取就可以this.environmentConfiguration = new EnvironmentConfiguration();//从远程配置中心的全局配置获取对应配置this.externalConfiguration = new InmemoryConfiguration("ExternalConfig");//从远程配置中心的应用配置获取对应配置this.appExternalConfiguration = new InmemoryConfiguration("AppExternalConfig");//应用内的配置比如: Spring Environment/PropertySources/application.propertiesthis.appConfiguration = new InmemoryConfiguration("AppConfig");//加载迁移配置,用户在JVM参数或者环境变量中指定的dubbo.migration.file,如果用户未指定测尝试加载类路径下的dubbo-migration.yamlloadMigrationRule();}
}
dubbo.properties配置文件加载解析原理
如前面所示:
//加载在JVM或者环境变量指定的dubbo.properties配置文件 配置的key为dubbo.properties.file ,如果未指定则查找类路径下的dubbo.properties
this.propertiesConfiguration = new PropertiesConfiguration(scopeModel);
下面就直接提构造器的PropertiesConfiguration代码了:
public PropertiesConfiguration(ScopeModel scopeModel) {this.scopeModel = scopeModel;refresh();}public void refresh() {//配置获取的过程是借助工具类ConfigUtils来获取的properties = ConfigUtils.getProperties(scopeModel.getClassLoaders());}
继续看ConfigUtils的getProperties方法:
public static Properties getProperties(Set<ClassLoader> classLoaders) {//这个配置的KEY是dubbo.properties.file System.getProperty是从JVM参数中获取配置的 一般情况下我们在启动Java进程的时候会指定Dubbo配置文件 如配置://-Ddubbo.properties.file=/dubbo.propertiesString path = System.getProperty(CommonConstants.DUBBO_PROPERTIES_KEY);if (StringUtils.isEmpty(path)) {//优先级最高的JVM参数拿不到数据则从 环境变量中获取,这个配置key也是dubbo.properties.file System.getenv是从环境变量中获取数据//例如我们在环境变量中配置 dubbo.properties.file=/dubbo.propertiespath = System.getenv(CommonConstants.DUBBO_PROPERTIES_KEY);if (StringUtils.isEmpty(path)) {//如果在JVM参数和环境变量都拿不到这个配置文件的路径我们就用默认的吧//默认的路径是类路径下的资源文件 这个路径是: dubbo.properties path = CommonConstants.DEFAULT_DUBBO_PROPERTIES;}}return ConfigUtils.loadProperties(classLoaders, path, false, true);}
路径获取之后加载详细的配置内容:
ConfigUtils的loadProperties代码如下:
ConfigUtils.loadProperties(classLoaders, path, false, true);
代码如下:
public static Properties loadProperties(Set<ClassLoader> classLoaders, String fileName, boolean allowMultiFile, boolean optional) {Properties properties = new Properties();// add scene judgement in windows environment Fix 2557//检查文件是否存在 直接加载配置文件如果加载到了配置文件则直接返回if (checkFileNameExist(fileName)) {try {FileInputStream input = new FileInputStream(fileName);try {properties.load(input);} finally {input.close();}} catch (Throwable e) {logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e);}return properties;}//为什么会有下面的逻辑呢,如果仅仅使用上面的加载方式只能加载到本系统下的配置文件,无法加载封装在jar中的根路径的配置Set<java.net.URL> set = null;try {List<ClassLoader> classLoadersToLoad = new LinkedList<>();classLoadersToLoad.add(ClassUtils.getClassLoader());classLoadersToLoad.addAll(classLoaders);//这个方法loadResources在扩展加载的时候说过set = ClassLoaderResourceLoader.loadResources(fileName, classLoadersToLoad).values().stream().reduce(new LinkedHashSet<>(), (a, i) -> {a.addAll(i);return a;});} catch (Throwable t) {logger.warn("Fail to load " + fileName + " file: " + t.getMessage(), t);}if (CollectionUtils.isEmpty(set)) {if (!optional) {logger.warn("No " + fileName + " found on the class path.");}return properties;}if (!allowMultiFile) {if (set.size() > 1) {String errMsg = String.format("only 1 %s file is expected, but %d dubbo.properties files found on class path: %s",fileName, set.size(), set);logger.warn(errMsg);}// fall back to use method getResourceAsStreamtry {properties.load(ClassUtils.getClassLoader().getResourceAsStream(fileName));} catch (Throwable e) {logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e);}return properties;}logger.info("load " + fileName + " properties file from " + set);for (java.net.URL url : set) {try {Properties p = new Properties();InputStream input = url.openStream();if (input != null) {try {p.load(input);properties.putAll(p);} finally {try {input.close();} catch (Throwable t) {}}}} catch (Throwable e) {logger.warn("Fail to load " + fileName + " file from " + url + "(ignore this file): " + e.getMessage(), e);}}return properties;}
完整的配置加载流程这里用简单的话描述下:
-
项目内配置查询
-
- 路径查询
-
-
- 从JVM参数中获取配置的 dubbo.properties.file配置文件路径
- 如果前面未获取到路径则从环境变量参数中获取配置的dubbo.properties.file配置文件路径
- 如果前面未获取到路径则使用默认路径dubbo.propertie
-
-
- 配置加载
-
-
- 将路径转为FileInputStream 然后使用Properties加载
-
-
依赖中的配置扫描查询
-
- 使用类加载器扫描所有资源URL
- url转InputStream 如 url.openStream() 然后使用Properties加载
加载JVM参数的配置
这里我们继续看SystemConfiguration配置的加载 这个直接看下代码就可以了:
这个类型仅仅是使用System.getProperty来获取JVM配置即可
public class SystemConfiguration implements Configuration {@Overridepublic Object getInternalProperty(String key) {return System.getProperty(key);}public Map<String, String> getProperties() {return (Map) System.getProperties();}
}
加载环境变量参数的配置
这里我们来看EnvironmentConfiguration
public class EnvironmentConfiguration implements Configuration {@Overridepublic Object getInternalProperty(String key) {String value = System.getenv(key);if (StringUtils.isEmpty(value)) {value = System.getenv(StringUtils.toOSStyleKey(key));}return value;}public Map<String, String> getProperties() {return System.getenv();}
}
内存配置的封装:InmemoryConfiguration
这里我们看下InmemoryConfiguration的设计,这个直接看代码吧内部使用了一个LinkedHashMap来存储配置
public class InmemoryConfiguration implements Configuration {private String name;// stores the configuration key-value pairsprivate Map<String, String> store = new LinkedHashMap<>();public InmemoryConfiguration() {}public InmemoryConfiguration(String name) {this.name = name;}public InmemoryConfiguration(Map<String, String> properties) {this.setProperties(properties);}@Overridepublic Object getInternalProperty(String key) {return store.get(key);}/*** Add one property into the store, the previous value will be replaced if the key exists*/public void addProperty(String key, String value) {store.put(key, value);}/*** Add a set of properties into the store*/public void addProperties(Map<String, String> properties) {if (properties != null) {this.store.putAll(properties);}}/*** set store*/public void setProperties(Map<String, String> properties) {if (properties != null) {this.store = properties;}}public Map<String, String> getProperties() {return store;}}
Dubbo迁移新版本的配置文件加载dubbo-migration.yaml
这个配置文件的文件名字为:dubbo-migration.yaml
private void loadMigrationRule() {//JVM参数的dubbo.migration.file配置String path = System.getProperty(CommonConstants.DUBBO_MIGRATION_KEY);if (StringUtils.isEmpty(path)) {//环境变量的dubbo.migration.file配置path = System.getenv(CommonConstants.DUBBO_MIGRATION_KEY);if (StringUtils.isEmpty(path)) {//默认的迁移配置文件 dubbo-migration.yamlpath = CommonConstants.DEFAULT_DUBBO_MIGRATION_FILE;}}this.localMigrationRule = ConfigUtils.loadMigrationRule(scopeModel.getClassLoaders(), path);}
初始化加载应用配置
加载配置涉及到了配置优先级的处理,
下面来看加载配置代码 loadApplicationConfigs()方法
private void loadApplicationConfigs() {//发布器还是不处理配置加载的逻辑还是交给配置管理器configManager.loadConfigs();
}
配置管理器加载配置:
@Overridepublic void loadConfigs() {// application config has load before starting config center// load dubbo.applications.xxx//加载应用配置loadConfigsOfTypeFromProps(ApplicationConfig.class);// load dubbo.monitors.xxx//加载监控配置loadConfigsOfTypeFromProps(MonitorConfig.class);// load dubbo.metrics.xxx//加载指标监控配置loadConfigsOfTypeFromProps(MetricsConfig.class);// load multiple config types:// load dubbo.protocols.xxx//加载协议配置loadConfigsOfTypeFromProps(ProtocolConfig.class);// load dubbo.registries.xxxloadConfigsOfTypeFromProps(RegistryConfig.class);// load dubbo.metadata-report.xxx//加载元数据配置loadConfigsOfTypeFromProps(MetadataReportConfig.class);// config centers has bean loaded before starting config center//loadConfigsOfTypeFromProps(ConfigCenterConfig.class);//刷新配置refreshAll();//检查配置checkConfigs();// set model nameif (StringUtils.isBlank(applicationModel.getModelName())) {applicationModel.setModelName(applicationModel.getApplicationName());}}
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
Dubbo加载配置文件方式,加载流程,加载配置文件源码解析
配置方法 API配置 以Java编码的方式组织配置,Dubbo3配置API详解 :https://dubbo.apache.org/zh/docs3-v2/java-sdk/reference-manual/config/api/#bootstrap-api public static void main(String[] args) throws IOException {ServiceConfig<Greet…...
![](https://img-blog.csdnimg.cn/d7484d1892d941f09be5b0f69d8756fc.webp)
十大开源测试工具和框架,一定有你需要的
目录 前言 Katalon Studio Selenium Appium JMeter SOAP UI Robot Framework Watir JUnit Robotium Citrus 总结 前言 免费的开源框架和工具由于其开源特性,现在逐渐成为自动化测试的首选解决方案。区别在于,你是喜欢使用类库编写一个全新的…...
![](https://www.ngui.cc/images/no-images.jpg)
加密技术在android中的应用
1、算法基础 算法基础参照linux的全盘加密与文件系统加密在android中的应用 消息摘要算法 对称加密算法 非对称加密算法...
![](https://img-blog.csdnimg.cn/f3381d255f194ddbabed51eb9e34642e.png#pic_center)
备战蓝桥杯【一维前缀和】
🌹作者:云小逸 📝个人主页:云小逸的主页 📝Github:云小逸的Github 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前…...
![](https://img-blog.csdnimg.cn/img_convert/76dbb0fd2b8c3488d8b0499251bca483.png)
研报精选230214
目录 【行业230214艾瑞股份】中国增强现实(AR)行业研究报告【行业230214国信证券】信息安全深度剖析5:密评和信创双催化,密码产业开启从1到N【行业230214民生证券】磁性元器件深度报告:乘新能源之风,磁性元…...
![](https://img-blog.csdnimg.cn/50b8a6d9cd73410c8cf7a58ec07b4964.png)
【SSL/TLS】准备工作:证书格式
证书格式1. 格式说明1.1 文件编码格式1.2 文件后缀格式2. xca导出格式1. 格式说明 1.1 文件编码格式 1. PEM格式: 使用Base 64 ASCII进行编码的纯文本格式。后缀为“.pem”, ".cer", ".crt", ".key" 2. DER格式 二进制编码格式,文件…...
![](https://img-blog.csdnimg.cn/370ebc538e874e669ba0b2d8c724222c.png)
Linux常用命令---系统常用命令
Linux系统常用命令场景一: 查看当前系统内核版本相关信息场景二: sosreport 命令场景三: 如何定位并确定命令?场景四:查看当前系统运行负载怎场景五: 查看当前系统的内存可用情况场景六:查看网卡…...
![](https://www.ngui.cc/images/no-images.jpg)
C 结构体
C 数组允许定义可存储相同类型数据项的变量,结构是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。结构用于表示一条记录,假设您想要跟踪图书馆中书本的动态,您可能需要跟踪每本书的下列属性ÿ…...
![](https://img-blog.csdnimg.cn/4335d809b6d64b0a88a9f967e947b09d.png)
手语检测识别
论文:Real-Time Sign Language Detection using Human Pose Estimation Github:https://github.com/google-research/google-research/tree/master/sign_language_detection SLRTP 2020 手语识别任务包括手语检测(Sign language detection&a…...
![](https://img-blog.csdnimg.cn/a1d4b71862664df2ac4aed5308b6b3a4.png)
android fwk模块之Sensor架构
本文基于Android 12源码整理,包含如下内容: 通信架构应用层实现使用方式SensorManager抽象接口具体实现fwk层的实现native中的SensorManager的初始化流程native中的消息队列初始化与数据读取sensorservice实现HAL层的实现通信架构 应用层实现 涉及代码&…...
![](https://img-blog.csdnimg.cn/aa61578497414de2a438c851f63f2501.png)
安装less-loader5出现webpack版本不兼容
今天遇到一个问题: 安装less-loader5之后其它包提示peerDependencies WARNING,意思是包版本不兼容。 【难题】 虽然NPM已经很自动化了,但依赖问题真的是一个难题,无法自动解决,需要人工干预调整。 【解决办法】 去查…...
![](https://www.ngui.cc/images/no-images.jpg)
Java 网络编程
1.UDP和TCPUDP和TCP是传输层协议中最核心的两种协议他们的特点分别是UDP: 无连接,不可靠传输,面向数据报,全双工TCP: 有连接,是可靠传输,面向字节流,全双工有无连接有连接:就好比两个人打电话,打电话的一方发出连接请求,被打电话的一方选择确认连接,此时双方才能进行通话无连接…...
![](https://www.ngui.cc/images/no-images.jpg)
BEV学习记录
近期可能要经常性的开展BEV工作,打算把自己觉着不错的网站拿出来记录一下。 首先贴上来我还没有细读的一篇觉着不错的文章。 自动驾驶感知新范式——BEV感知经典论文总结和对比(上)_苹果姐的博客-CSDN博客_bev视角 开山之作--LSS ECCV 202…...
![](https://www.ngui.cc/images/no-images.jpg)
Webrtc Native C++切换音频输入源
modules/audio_device/audio_device_impl.cc #include “api/audio_options.h” #include “modules/audio_device/include/factory.h” // 创建一个 AudioDeviceModule 对象 auto audio_device_module = webrtc::AudioDeviceModule::Create( webrtc::AudioDeviceModule::kPl…...
![](https://img-blog.csdnimg.cn/ea48c1dc15804d2a965dcd5c0b0969c2.png)
裸辞5个月,面试了37家公司,终于找到理想工作了
上半年裁员,下半年裸辞,有不少人高呼裸辞后躺平真的好快乐!但也有很多人,裸辞后的生活五味杂陈。 面试37次终于找到心仪工作 因为工作压力大、领导PUA等各种原因,今年2月下旬我从一家互联网小厂裸辞,没想…...
![](https://www.ngui.cc/images/no-images.jpg)
Mybatis-plus@DS实现动态切换数据源应用
目录1 DS实现动态切换数据源原理2 不可在事务中切换数据库分析解决3 原因解析1 DS实现动态切换数据源原理 首先mybatis-plus使用com.baomidou.dynamic.datasource.AbstractRoutingDataSource继承 AbstractDataSource接管数据源;具体实现类为com.baomidou.dynamic.d…...
![](https://img-blog.csdnimg.cn/img_convert/761e86e81055470f8b1cdedeafd50bb6.png)
SpringBoot的创建和使用
SpringBoot是什么?SpringBoot诞生的目的就是为了简化Spring开发,而相对于Spring,SpringBoot算是一个很大的升级,就如同汽车手动挡变成了自动挡。Spring:SpringBoot:SpringBoot的优点SpringBoot让Spring开发…...
![](https://www.ngui.cc/images/no-images.jpg)
居家电话客服宝典
客服分类从销售的流程来分,客服分为售前和售后。售前一般都带有销售性质,工资主要靠提成,售后一般是解答问题,工资主要看服务质量和差评量。从工作模式来分,客服分为在线客服和热线客服。在线客服以打字聊天为主&#…...
![](https://www.ngui.cc/images/no-images.jpg)
开发方案设计
1、开发流程产品需求设计-->需求粗评-->做设计方案-->粗估时-->需求细评-->排期-->开发-->提测、修bug-->code review-->上线设计方案主要是写实现思路、模块划分code review:完善代码,发现未考虑到的边界问题2、具体实现方案…...
![](https://www.ngui.cc/images/no-images.jpg)
文件路径模块pathlib
文件路径模块pathlib 文章目录文件路径模块pathlib1.概述2.创建路径2.1.创建非windos平台路径2.2.动态拼接路径joinpath2.3.替换文件名称 with_name2.4.创建固定目录2.5.创建文件夹和文件1.创建多级目录mkdir2.创建空文件3.路径解析3.1.根据路径分隔符解析路径parts3.2.获取父级…...
![](https://img-blog.csdnimg.cn/00f49e81117040918d74664fe046f2cf.png)
spring cloud篇——什么是服务熔断?服务降级?服务限流?spring cloud有什么优势?
文章目录一、spring cloud 有什么优势二、服务熔断2.1、雪崩效应2.2、DubboHystrixCommand三、服务降级四、服务限流4.1、限流算法4.2、应用级限流4.3、池化技术4.4、分布式限流4.5、基于Redis 功能的实现限流4.6、基于令牌桶算法的实现4.6.1 、Java实现一、spring cloud 有什么…...
![](https://img-blog.csdnimg.cn/img_convert/056e5053ca69d31604a568453bb78991.png)
Tomcat构建
软件架构C/S:Client/Server.需要安装才能使用。B/S:Brower/Server。有浏览器就可以。资源分类动态资源:每个用户访问相同的资源后,得到的结果可能不一样,称为动态资源。动态资源被访问后,先转换为静态资源,再被浏览器解…...
![](https://img-blog.csdnimg.cn/eb7ddd00a79e435f979e0f0bb9b5ba2c.png#pic_center)
入门深度学习——基于全连接神经网络的手写数字识别案例(python代码实现)
入门深度学习——基于全连接神经网络的手写数字识别案例(python代码实现) 一、网络构建 1.1 问题导入 如图所示,数字五的图片作为输入,layer01层为输入层,layer02层为隐藏层,找出每列最大值对应索引为输…...
![](https://img-blog.csdnimg.cn/img_convert/39cef06a269afab72e13fb9fdfa8e4c4.png)
预算砍砍砍,IT运维如何降本增效
疫情短暂过去,一个乐观的共识正在蔓延:2023年的互联网,绝对不会比2022年更差。 “降本”是过去一年许多公司的核心策略,营销大幅缩水、亏损业务大量撤裁,以及层出不穷的裁员消息。而2023年在可预期的经济复苏下&#…...
![](https://img-blog.csdnimg.cn/2088790f58614ec9902029a4e3fe16df.png)
10.Jenkins用tags的方式自动发布java应用
Jenkins用tags的方式自动发布java应用1.配置jenkins,告诉jenkins,jdk的安装目录,maven的安装目录2.构建一个maven项目指定构建参数,选择Git Paramete在源码管理中,填写我们git项目的地址,调用变量构建前执行…...
![](https://www.ngui.cc/images/no-images.jpg)
2023新华为OD机试题 - 相同数字的积木游戏 1(JavaScript)
相同数字的积木游戏 1 题目 小华和小薇一起通过玩积木游戏学习数学。 他们有很多积木,每个积木块上都有一个数字, 积木块上的数字可能相同。 小华随机拿一些积木挨着排成一排,请小薇找到这排积木中数字相同且所处位置最远的 2 块积木块,计算他们的距离。 小薇请你帮忙替她…...
![](https://lucas-default-bucket.oss-cn-hangzhou.aliyuncs.com/imgbed/image-20230131195507602.png)
重构之改善既有代码的设计(一)
1.1 何为重构,为何重构 第一个定义是名词形式: 重构(名词):对软件内部结构的一种调整,目的是在不改变「软件可察行为」前提下,提高其可理解性,降低修改成本。 「重构」的另一个用…...
![](https://www.ngui.cc/images/no-images.jpg)
Kotlin data class 数据类用法
实验数据 {"code":1,"message":"成功","data":{"name":"周杰轮","gender":1} }kotlin数据类使用方便提供如下内部Api: equals()/hashCode()对 toString() componentN()按声明顺序与属性相…...
![](https://img-blog.csdnimg.cn/b64ec2c7b615411eb78e9a79206095df.jpeg)
随笔-老子不想牺牲了
18年来到这个项目组,当时只有8个人,包括经常不在的架构师和经理。当时的工位在西区1栋A座,办公桌很宽敞。随着项目的发展,入职的人越来越多,项目的工位也是几经搬迁。基本上每次搬迁时,我的工位都是挑剩下的…...
![](https://img-blog.csdnimg.cn/a005782838df46fbb558876269d43e78.png#pic_center)
三种查找Windows10环境变量的方法
文章目录一.在设置中查看二. 在我的电脑中查看三. 在资源管理器里查看一.在设置中查看 在系统中搜索设置 打开设置,在设置功能里,点击第一项 系统 在系统功能里,左侧菜单找到关于 在关于的相关设置里可以看到高级系统设置 点击高级系…...
![](/images/no-images.jpg)
网站手机版跳转代码/微信营销软件
[b]Closure[/b]:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。它只不过是个"内层"的函数,由一个名字&…...
![](https://images0.cnblogs.com/blog/464052/201307/18161925-b7c2ab021d594fb88b3dea6e7de64cc0.png)
申请一个网站需要怎么做/怎么用手机制作网站
Fibonacci Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2087 Accepted Submission(s): 999 Problem Description 2007年到来了。经过2006年一年的修炼,数学神童zouyu终于把0到100000000的Fibonacci数列…...
![](/images/no-images.jpg)
就是做网站的...../关键词seo优化排名公司
本代码主要实现的是利用网络传输图片,用在我的树莓派项目之上。该项目在PC上运行服务端,树莓派上运行客户端,两者连接到同一局域网中,修改代码中的IP地址,就可以实现将树莓派采集到的图像数据实时传输到PC端。先运行服…...
![](https://images2018.cnblogs.com/blog/625432/201807/625432-20180717092619922-770913303.png)
规划网站的总结/seo提升排名技巧
登录JIRA访问打开缓慢,查询日志出现下述提示:java.lang.OutOfMemoryError: GC overhead limit exceeded 修改setenv.sh文件中的JVM配置,/data/atlassian/jira/bin 是我JIRA安装的路径 #cd /data/atlassian/jira/bin #vi setenv.sh 编辑保存后…...
![](/images/no-images.jpg)
手机网站建设万网/电商网站入口
java 生成4位随机数 验证码刘振兴代码分享2015年11月16日8166暂无评论public static String yzm(){String str "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";String str2[] str.split(",");//将字符串以,分割Random rand…...
![](/images/no-images.jpg)
别墅装修设计图片大全 效果图/seo基础知识包括什么
1. 随着经济的繁荣 with the booming of the economy 2. 随着人民生活水平的显著提高 with the remarkable improvement of peoples living standard 3. 先进的科学技术 advanced science and technology 4. 为我们日常生活增添了情趣 add much spice / flavor to our dail…...