设计
不管你是否使用HTTL,都欢迎看一下此设计文档,可能对你设计上有帮助,因为设计理念是相通的。
静态视图
查看大图
模型划分原则
按实体域,服务域,会话域划分。
不管你做一个什么产品,都一定有一个被操作的主体,比如:服务框架管理的Service,任务框架管理的Task,Spring管理的Bean等,这就是实体域。
即然有被操作者,就一定有操作者,它管理被操作者的生命周期,发起动作,比如:服务框架的ServiceInvoker,,任务框架的TaskScheduler,Spring的BeanFactory等,这就是服务域。
服务域发起动作,在执行过程中,会有一些临时状态需要存储交换,比如:Invacation,Execution,Request等,这就是会话域。
相应的,在HTTL中:
Engine 为服务域
它是API的入口,并负责实体域Template的生命周期管理,它是Singleton单一实例的,加载后不可变,所以是线程安全的,它的初始化过程较重,请复用单例。
Template 为实体域
代表着被操作者,它是Prototype原型实例的,即每个模板产生一个实例,加载后不可变,同样也是线程安全的,模板变化后,将产生不同的实例,而不改变原实例。
Context 为会话域
持有操作过程中的所有可变状态,它是ThreadLocal线程内实例的,即不和其它线程竞争使用,所以也是线程安全的,请不要跨线程传递,它的初始化过程很轻量,每次模板执行前都新建实例,执行完即销毁。
这样划分的好处是,职责清晰,可变状态集中,每个域都是无锁线程安全的,保证在大并发下,不会降低系统的活性。
这些核心领域模型也就是HTTL的API(Application Programming Interface),它是HTTL暴露给用户的最少概念,也就是上面类图中的第一列。
扩展点组装原则
按“微核+插件”体系组装。
但凡有生命力的产品,都是在扩展性方面设计的比较好的,因为没有哪个产品可以覆盖所有需求,对于开源软件尤其如此。
所以,产品只有具有良好的扩展性,允许用户或第三方参与进来,进行二次开发,才能保持生命力。
怎么样的扩展性才是最好的?通常来讲,就是没有任何功能是硬编码的,所有的功能都可被用户替换。
那要如何才能做到这样?一个重要的原则就是:平等对待第三方。
也就是凡是原作者能实现的功能,第三方也要能够在不改变源代码的前提下实现。
换言之,原作者应把自己也当作扩展者,自己添加功能时,也要用第三方扩展者同样的方式进行,而不要有特权。
要做到这一点,就需要一个良好的框架支撑,“微核+插件”是一个不错的选择,Eclipse, Maven等知名软件都采用该体系。
什么是“微核+插件”?微核,即最小化核心,内核只负责插件的组装,不带任何功能逻辑,所有功能都由可替换的插件实现,
并且,组装过程应基于统一的规则,比如基于setter注入,而不能对不同插件硬编码组装,这样可以确保没有任何功能在内核中硬编码。
比如:Spring, OSGI, JMX, ServiceLoader等都是常见的微核容器,它们负责基于统一规则的组装,但不带功能逻辑。
当然,如果你不想带这么重的框架,也可以自行实现,HTTL就采用自行实现的httl.util.BeanFactory作为组装微核。
在Engine.getEngine()中调用了BeanFatory.createBean(Engine.class, properties),
其中,properties即为httl.properties配置,BeanFatory基于setter方法,递归注入所有对象的属性。
比如:httl.properties中配置了parser=httl.spi.parsers.CommentParser,
而DefaultEngine中有setParser(Parser parser)方法,就会被注入,并且Parser本身的属性也会递归注入。
如果你需要扩展或替换HTTL的实现,请参见:扩展集成
既然非功能性的插件组装过程,可以由微核框架来完成,那功能性的组装怎么办呢?
我们应该把功能性的组装过程也封装成插件,即让大插件组装小插件,形成级联组装关系。
比如,HTTL的入口类Engine的实例也是一个插件,它负责模板的缓存,加载,解析的总调度,即你可以替换DefaultEngine实现。
只需在httl.properties中配置:engine=com.your.YourEngine,可以将现有Parser等SPI注入你的Engine。
这些插件的接口,也就是HTTL的SPI(Service Provider Interface),它是HTTL暴露给扩展者的最小粒度的替换单元,也就是上面类图中的第二列。
整体分包原则
按复用度,抽象度,稳定度分包。
复用度:
每种用户所需用到的类,就是同一复用粒度的,比如:使用者和扩展者,这样可以减少代码干扰,以及最大化复用。
稳定度:
被依赖包和依赖包的占比,如果一个包依赖很多包,那别的包变化都会引起它跟随变化,所以它就不稳定,反之即稳定, 保持被依赖者总是比依赖者的稳定度高,形成金子塔关系,这样可以防止不稳定性传染,比如a包只依赖3个包,而b包依赖10个包,那就不要让a包去依赖b包。
抽象度:
包中抽象类个数占比,比如包中有10个类,其中3个为抽象类(包括接口),则抽象度为3/10, 保持包的稳定度和抽象度成正比,即把抽象类(包括接口)放到稳定的包中,把具体实现类放到不稳定的包中,这样可以保持每层都有足够的扩展性。
稳定度与抽象度关系如下图:
也就是分包应该如下:
其中上面那个包不依赖其它包。所以它很稳定,应尽量把抽象类或接口放在这一层,
而下面那个包依赖了三个包,三个包变化都会引起它跟随变化,所以它是不稳定的,应尽量把具体实现类放在这一层。
因稳定度与抽象度成正比,所以不稳定度与抽象度成反比,用反比方便画图,计算方式如下:
(1) I = Ce / (Ca + Ce)
I: Instability (不稳定度)
Ca: Afferent Coupling (传入依赖,也就是被其它包依赖的个数)
Ce: Efferent Coupling (输出依赖,也就是依赖其它包的个数)
(2) A = Na / Nc
A: Abstractness (抽象度)
Na: Number of abstract classes (抽象类的个数)
Nc: Number of classes (类的个数,包括抽象类)
(3) D = abs(1 - I - A) * sin(45)
D: Distance (偏差)
I: Instability (不稳定度)
A: Abstractness (抽象度)
应该保持偏差越小越好,即下图所示交点都落在绿色反比线左右:
基于上面的原则,HTTL的包结构整体上划分为三层:(对应上面类图中的三列)
API (Application Programming Interface)
模板引擎的使用者依赖的接口类,也是核心领域模型所在,保持最少概念,并隐藏实现细节,其中Engine类相当于微内核,只管理非功能性的扩展点的加载,不硬编码模板加载解析渲染的任何部分。
SPI (Service Provider Interface)
模板引擎的扩展者依赖的接口类,它依赖于API的领域模型,它是模板引擎功能正交分解的抽象层,以保证用户可以最小粒度替换需要改写的地方,方便二次开发。
BUILT-IN (Built-in Implementation)
内置扩展实现,它是SPI标准实现,也是可被用户替换的类,它包含引擎所有做的事,包括扩展点之间的组装过程(可替换DefaultEngine),以确保没有功能换不掉,即平等对待扩展者。
采用子包依赖父包风格,所以将API放在根目录,SPI接口独立子包,各种实现放在SPI的下一级子包中。
使用者API导入:import httl.*;
扩展者SPI导入:import httl.spi.*;
下图是HTTL所有包的不稳定度与抽象度的比值距阵:(下图为JDepend绘制)
HTTL所有核心包都是靠近反比线的,即上图中用绿色标识的点,表示分包是合理的。
注:图中黑色的点为util相关包,它们不抽象,却被很多包依赖,只是内部复用代码,不影响整体设计,用户请不要依赖HTTL的util类。
动态视图
如果你要看代码,可以从入口类Engine和DefaultEngine开始,按此调用过程跟踪。
获取模板过程
查看大图
获取模板过程说明:(与上图中的序号对应)
1 当从引擎中获取模板时,
1.1 首先会在缓存查找是否已缓存,如果有缓存就直接返回,
1.2 如果没有,则加载模板源文件为Resource对象,
1.3 接着通过转换器(分为编译和解释两种),将Resource转换成Template,
1.3.1 转换的第一步是将模板解析成AST抽象语法树,
1.3.2 并对静态文本进行编译前过滤,比如删除空白等,
1.3.3 对解析后的Java代码进行编译,得到具体模板实现类,
1.3.4 实例化模板实现类,
1.4 将模板实例写入缓存,并返回给用户。
渲染模板过程
查看大图
渲染模板过程说明:(与上图中的序号对应)
1 当用户调用模板的渲染方法时,
1.1 将非Map变量对象转换成Map,将非Writer或OutputStream输出对象转成Writer或OutputStream,
1.2 将变量Map压入Context栈,
1.3 如果有拦截器,将实际渲染过程封装成Listener,传给拦截器执行,
1.3.1 拦截器执行完拦截逻辑后,调用拦截时传入的Listener,
1.3.1.1 该Listener回调模板的doRender方法,执行实际渲染过程,
1.4 模板中的变量,均从Context中读取,
1.4.1 如果当前Context不存在,则向上一级Context中读取,
1.4.1.1 如果已经是根级别Context,则向Resolver读取,
1.5 模板输出变量时,先通过Formatter,将值对象转成String,
1.6 再通过Filter,过虑输出String的XML特殊符等,
1.7 最终,将过滤后的String输出,
1.8 模板渲染结束后,将当前Conetext弹出。
性能
性能对比
性能测试类:BenchmarkTest.java
引擎
模板
十万次耗时
每秒次数
java
books.java
8,739ms
11,442/s
httl
books.httl
9,608ms
10,407/s
velocity
books.vm
41,969ms
2,382/s
freemarker
books.ftl
56,192ms
1,779/s
smarty4j
books.st
65,855ms
1,518/s
环境:os: Mac OS X 10.8.2, cpu: 2 x 1.70GHz, mem: 4G, jvm: 1.7.0_09 -> mem: 80M
HTTL的速度接近于直接用Java硬编码输出,比其它模板引擎高一个数量级。
HTTL用到的JDK的Compiler,编译一个类通常需要几百毫秒,比其它模板的编译要慢,但每个模板只在加载时编译一次。
以上测试,不包含HTTL在编译期将静态文本转成byte[],以减少输出时重复转码的优化。 全部采用忽略输出的方式进行测试,测的是模板引擎纯渲染时间,否则HTTL将更快。 如果要测试该优化项,不能忽略输出时的编码开销,否则将不公平。
另外,HTTL缺省开启了EscapeXmlFilter,而其它模板引擎没有,为了公平,性能测试时配置关闭了Filter:
value.filter=null
注:不同环境的运行结果可能存在差异,以上测试数据仅供参考,你可以在自己的机器上执行测试:
git clone https://github.com/httl/httl-benchmark.git
cd httl-benchmark
mvn test -Dtest=httl.test.BenchmarkTest -Dcount=10000
执行结果如:
Running httl.test.BenchmarkTest
====================test environment=====================
os: Mac OS X 10.8.2 x86_64, cpu: 4 cores, jvm: 1.6.0_37,
mem: max: 505M, total: 125M, free: 110M, use: 15M
====================test parameters======================
count: 10000, warm: 100, list: 100, stream: false,
engines: java,httl,velocity,freemarker,smarty4j,beetl
====================test result==========================
engine, time, tps, rate,
java, 690ms, 14492/s, 100%,
httl, 785ms, 12738/s, 87%,
velocity, 3828ms, 2612/s, 18%,
freemarker, 6489ms, 1541/s, 10%,
smarty4j, 6181ms, 1617/s, 11%,
beetl, 9642ms, 1037/s, 7%,
=========================================================
优化策略
强类型编译
强类型编译,并推导关联类型
对于表达式${user.name}的编译:
弱类型字节码生成:
Object user = context.get("user"); // 无法确定user是Map还是POJO
// 反射获取属性的值,而且要运行期判断是user.getName(),还是user.name字段
Object name = ReflectUtil.get(user,"name"); // 接下来name也要反射
HTTL强类型字节码生成:
User user = (User)context.get("user"); // 通过声明类型
// 在编译期决定使用getName()方法获取属性的值,并通过getUser()的返回类型推演name的类型
String name = user.getName();
预编译字节流
编译时就将文本编译成字节,加快输出
文本编译:
writer.write(" ");
writer.write(user.getName());
二进制编译:
private static final byte[] _B1_ = new byte[] {60, 116, 97, 98, 108, 101, 62, 60, 116, 114, 62, 60, 116, 100, 62};
output.write(_B1_);
output.write(user.getName().getBytes());
这样可以大幅度降低IO输出时将文本通过字符集编码成二进制流的速度,否则一个页面被渲染一亿次,上面的静态文本就要被编码一亿次。
HTTL缺省每模板同时生成两份class,在用户传入OutputStream和Writer时,执行不同的class:
template.render(paramaters, outputStream); // 内部将执行二进制输出版本的Template类
template.render(paramaters, writer); // 内部将执行文本输出版本的Template类
本地局部变量
对于赋值生成局部变量,不put回参数map
比如将:
${price}
编译成:
int price = price * discount / 100;
write(price);
而不是:
context.put("price", price * discount / 100);
write(context.get("price"));
这样可以大量减少参数map的put和get的调用,减少hash查找的时间。
字节码不含字符串
将文本不编译到字节码中,减少内存perm区占用,以及防止JIT失效
当模板的内容较大时,会导致生成的字节码也比较大,字节码运行时会放在内存perm区,导致perm区过大。 模板多时,用户可能需要不断调大perm区:java -XX:PermSize=256MB -XX:MaxPermSize=256MB
另外,SunJDK缺省对大于8K字节码的方法不进行JIT优化,我们常规开启的JVM是mixed模式的, 即调用量大的,将由JIT编译成本地码运行,其它在JVM内解释执行,解释执行和编译执行的速度相差10倍以上。 参见JVM的:globals.hpp
product(bool, DontCompileHugeMethods, true,
"don't compile methods > HugeMethodLimit")
develop(intx, HugeMethodLimit, 8000,
"don't compile methods larger than this if +DontCompileHugeMethods")
通过将文本不编译到字节码中,减少内存perm区占用,也能防止JIT失效。
将:
// 如果这个串有8K以上,就会导致生成的字节码超过8K
writer.write("...A Large String...");
改成:
// 在生成字节码前,将文本内容存到一个Map缓存中,
// 在生成的类加载时,类的静态字段从缓存中读取值,并删除缓存,
// 这样文本内容,就从字节码存储的Perm区,转到了常量对象存储的Old区,
// 因为是静态字段,所以不会影响模板执行性能。
private static final String _TXT1_ = StringCache.getAndRemove("1");
writer.write(_TXT1_);
快速文本处理
减少反射调用,无用锁,基本类型装箱,以及文本处理。
反射经常是性能瓶颈所在,HTTL对所有反射调用的地方都很非常小心, 比如:因为int[]不继承于Object[],为了通用处理,改为Array.get(array, index)来获取数组的项, 导致在Profiler分析时,发现80%的CPU时间都耗在Array.get()上。
因为模板输出的大量是基本类型和字符串,HTTL遇到任何类似需要boxed和unboxed的地方, 都会重载所有基本类型方法,以减少boxed和unboxed的处理。 比如:当输出基本类型时,需要转成String,如果使用format(Object)接口,就会将基本类型装箱。
JDK6加入的Biased Locking优化是有开销和不稳定性的, 所以程序中无用的锁是可能影响性能的,HTTL会主动规避JDK中的无用锁, 比如:覆盖方法去掉Writer,ByteArrayOutputStream等的锁。
文本处理也是经常出现性能瓶颈的地方,HTTL极尽小心的处理文本。 比如:正则表达式的贪婪模式,StringBuilder扩容导致数组拷贝,过滤字符串没有替换时不做append操作等。
等等。一切影响性能的细节,持续关注和优化中。
质量
严格确保质量,请放心使用,HTTL在发布前已做:
所有语法指令函数模板单元测试,确保所有模板指令的解析和执行正确。
性能对比基准测试,确保性能接近Java硬编码输出,高出其它引擎一个数量级。
长时间运行稳定性测试,确保不出现FullGC,内存溢出,死锁,CPU占满,抖动等。
内存占用和CPU耗时Profiler分析,确保不出现非预期的内存和CPU瓶颈。
Web应用集成测试,确保在SpringMVC,Struts,Webx等集成中可用。
环境兼容性测试,确保在Liunx,Windows,OSX,JDK1.5,1.6,1.7等环境可用。
FindBugs代码问题检测,确保不出现空指针,资源未关闭等明显错误。
JDepend分包依赖检测,确保分包依赖的合理性。
单元测试
单元测试覆盖率: (分析工具EclEmma)
HTTL对所有语法,指令,函数,都有相应模板进行测试,参见:
https://github.com/httl/httl/tree/master/httl/src/test/resources/comment/templates
FINDBUGS检测
已通过FindBugs最新版本(2.0.2)检测,零发现。参见:FindBugs能发现的问题
JDEPEND检测
已通过JDepend检测检测,无环依赖,稳定度与抽象度比正常。
稳定性测试
在长时间重复运行所有单元测试后,CPU保持平稳:(分析工具JVisualVM)
内存也保持平稳,以YoungGC为主:
虽然HTTL大量使用字节码生成以提升性能,但因为有全量缓存,Perm区也是稳定的:
因设置的内存只有500M,而常规已占400多M,在OLD区几乎快满情况下,也只发生3次FullGC:(分析工具jstat)
从下面Dump后的数据可以看出,JDK编译占用了171M内存。如果开启-Xlint:unchecked编译参数会更大。 如果你觉得JdkCompiler内存占用过多,也可以通过配置换成Javassist编译。(分析工具jmap + MAT)
PROFILE分析
CPU分析
测试用例为长时间跑模板渲染过程,因解析后有缓存,所以CPU几乎全耗在渲染过程, 解析过程占比较小,符合预期:(分析工具JProfiler)
因同时测试了Writer和OutputStream两种场景,所以上图中各分一半。
展开其中一个渲染过程,各模板比较均匀,占比都不大,没有出现绝对热点,符合预期:
从上图可以看上,相对而言,xml.httl和include_withfilter.httl较慢,展开如下:
可以看出,主要消耗在xstream的parseXml解析和filter的escapseXml转义上。
XML的解析和处理本身就很耗时,在可接受范围内,并且不是核心组件。
长时间运行后,因样本少,xstream解析数据被缓存,所以时间都集中到了escapseXml的charAt上。
注意,上面的图中,浅红色表示当前方法消耗,深红色表示子函数消耗总和。
即然占比如此大,我们来看下代码:
首先String.charAt只是一个char[]下标取值,已经足够简单,不存在性能问题:
public char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index + offset];
}
那再来看看HTTL的escapseXml:
public static String escapeXml(String value) {
if (value == null || value.length() == 0) {
return value;
}
int len = value.length();
StringBuilder buf = null;
for (int i = 0; i < len; i ++) {
char ch = value.charAt(i);
switch (ch) {
case '&':
if (buf == null) {
buf = new StringBuilder(len * 2);
if(i > 0) {
buf.append(value.substring(0, i));
}
}
buf.append("&");
break;
case '<':
if (buf == null) {
buf = new StringBuilder(len * 2);
if(i > 0) {
buf.append(value.substring(0, i));
}
}
buf.append("<");
break;
case '>':
if (buf == null) {
buf = new StringBuilder(len * 2);
if(i > 0) {
buf.append(value.substring(0, i));
}
}
buf.append(">");
break;
case '\"':
if (buf == null) {
buf = new StringBuilder(len * 2);
if(i > 0) {
buf.append(value.substring(0, i));
}
}
buf.append(""");
break;
case '\'':
if (buf == null) {
buf = new StringBuilder(len * 2);
if(i > 0) {
buf.append(value.substring(0, i));
}
}
buf.append("'");
break;
default:
if (buf != null) {
buf.append(ch);
}
break;
}
}
if (buf != null) {
return buf.toString();
}
return value;
}
从代码中可以看出escapseXml已经做了一些优化:
在没有发现特殊符前,不创建StringBuilder对象。
在发现第一个特殊符时,将将之前的内容,一次性拷到StringBuilder中。
StringBuilder对象以两倍长度创建,防止扩容带来数据迁移。
通过switch每字符,以最短路径分发处理逻辑。
因escapseXml在没有发现特殊符时,只是通过charAt遍历字符串,不会做其它动作, 所以长时间运行后,会显得charAt比较热,要过滤至少要遍历一遍,这已经是最低复杂度,所以并不是什么问题。
在压测Apache开源commons-lang中的StringEscapeUtils中的escapeXml后,发现性能甚至不如HTTL的实现。
那也看下commons-lang的StringEscapeUtils源代码:(注释中有说明它慢的原因)
public static String escapeXml(String str) {
if (str == null) {
return null;
}
return Entities.XML.escape(str);
}
public String escape(String str) {
// 这里总是创建StringWriter,如果str没有特殊符,这样首先会浪费创建Writer对象的成本。
// 其次浪费将一个个字符写到writer中,再toString回来的大量性能,而且没有特殊符是大概率事件。
// HTTL在没有特殊符时是直接返回原始串的,不创建任何对象,不做任何来回拷贝。
// 另外,StringWriter里面封装的StringBuffer,它的所有方法是带同步锁的,而HTTL采用无锁的StringBuilder。
StringWriter stringWriter = createStringWriter(str);
try {
this.escape(stringWriter, str);
} catch (IOException e) {
throw new UnhandledException(e);
}
return stringWriter.toString();
}
public void escape(Writer writer, String str) throws IOException {
int len = str.length();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
// 这里使用map的hash查找实体的名称,比HTTL的switch慢。
String entityName = this.entityName(c);
if (entityName == null) {
if (c > 0x7F) {
writer.write("");
writer.write(Integer.toString(c, 10));
writer.write(';');
} else {
writer.write(c);
}
} else {
writer.write('&');
writer.write(entityName);
writer.write(';');
}
}
}
当然,如果你有更好的实现,欢迎提供,非常感谢。
你可以通过配置切换实现:
value.filters=com.your.YourEscapeXmlFilter
内存分析
内存中以char[]和String最多,因为模板本身是大量文本处理,符合预期:(分析工具JProfiler)
你可能感兴趣的:(HTLL 设计原则)
解析REST API与OpenAPI之差异:避免混淆
幂简集成
程序人生
在网络API领域,常提及的两种术语为RestAPI与OpenAPI,其既存在差异亦存在联系。前者是一种API设计方式,后者则是一种API描述及定义规范。值得注意的是,OpenAPI可用于描述和定义RESTAPI。什么是RESTAPI?RESTAPI是一种符合REST的设计原则或具象状态传输架构风格的API,又称为RESTfulAPI。简单的说,REST就是客户端按照约定向服务端请求指定数据、或者在
自己实现一个简易RPC调用框架
殷俊杰
最近在看dubbo,去创始人之一梁飞大神的博客搂了几眼,找到这个demo自己实现了一下,关于dubbo就不再介绍了,快速开始、框架设计、设计原则官网都有,有兴趣可以自己看Dubbo官网1.服务接口packagecom.yjj.my.api;/***@Description:*@Author:yinjunjie*@CreateDate:2018/8/713:16*@Version:1.0*/publ
Flutter电商项目实践-架构设计
Zhouztashin
Flutter flutter 电子商务 项目架构
1、框架设计图框架设计总体说明整个框架划分成业务层、组件层、基础层与外部层。其中外部层对应着第三方或者自己封装的提供单独功能的依赖库,基础层主要对应着非UI的基础性功能,组件层对应着UI功能的基础性功能,可以向业务层提供完整可以使用的UI组件功能。业务层则是应用的核心,除了外部层之外,组件层、基础层以库的形式提供给业务层使用,这样的好处是提高了这两层的复用性。框架设计原则层级职责划分需要单一且清晰
【架构篇】软件架构的指南针之架构原则
林木森^~^
架构 架构 数据库
软件架构的设计原则是一组指导思想,帮助我们在设计系统时做出有效的决策,以确保软件的可维护性、可扩展性和可靠性。以下是一些关键的软件架构设计原则:模块化(Modularity):将系统分解为功能独立的模块,每个模块负责系统中的一个特定的功能区域。这种分解有助于降低系统的复杂性,便于理解和维护。抽象(Abstraction):提供系统组件的简化表示,隐藏其内部复杂性,只暴露必要的接口。这有助于理解系统
阿里内部保姆级教程:手把手带你搭建一个优秀的Android项目架构
zhireshini233
Android 架构 android 架构 java
当我们新进一个公司,接受别人的项目的时候,基本都会说句MMP,SHI一样的代码啊,啥玩意啊,搞得什么啊。我擦,我就改了一个参数,怎么全乱套了,一个功能怎么天上地下都需要改啊。没有经受过痛苦的人,是不会想了解架构的,只有痛苦过的人,才会急切的了解架构,好好做人,不作孽。那么一个良好的架构需要什么呢?根据设计原则,有以下:实现项目所需要的功能,为业务需求打下基础可扩展性、可配置性足够强大易用性,方便新
三一班数学作业设计方案
姬磨小学史雅君
一、设计原则:作业设计在考虑学生心理特点,生理特点,认知特点和承受能力的基础上,精心筛选设计。二、作业形式:按时间分:家庭作业和课堂作业家庭作业要求学生在放学后回家完成的作业,这部分作业不要求多,基本以读为主,旨在培养学生的作业意识和合理安排课余时间的意识。课堂作业则要求学生在校完成,每周至少完成四次,此类作业是学生作业的重点,既要保证量,又要保证质。根据河南省小学数学作业设计与实施指导意见,三年
设计模式背后的设计原则和思想
纣王家子迎新
java 设计模式 java
设计模式背后的设计原则和思想是一套指导我们如何设计高质量软件系统的准则和方法论。这些原则和思想不仅有助于提升软件的可维护性、可扩展性和可复用性,还能帮助开发团队更好地应对复杂多变的需求。以下是一些核心的设计原则和思想:1.设计原则设计模式背后的设计原则主要包括但不限于以下几点:单一职责原则一个类应该仅有一个引起它变化的原因,即一个类应该负责一组相对独立的功能。这有助于降低类的复杂度,提高系统的可
RESTful API:架构风格与实现指南
啊取名真困难
restful 前端 架构 web 安全
摘要在当今的Web开发领域,RESTfulAPI已成为构建可扩展、易于维护的应用程序的关键技术。本文详细介绍了RESTfulAPI的架构风格、设计原则、实现步骤,并结合实际代码示例和案例分析,探讨了RESTfulAPI在现代Web服务中的应用。此外,文章还讨论了RESTfulAPI开发中的挑战、最佳实践以及安全性问题,为开发人员提供了实用的指导。关键词RESTfulAPI,Web服务,设计原则,实
深透析面向对象的编码设计规则
全栈神
java 前端 javascript
一、面向对象的五大设计原则:SOLID原则SOLID是面向对象设计中的五个基础原则的缩写,分别是:单一职责原则(SingleResponsibilityPrinciple,SRP)开放封闭原则(Open/ClosedPrinciple,OCP)里氏替换原则(LiskovSubstitutionPrinciple,LSP)接口隔离原则(InterfaceSegregationPrinciple,IS
android系统设计模式
轻口味
Android系列 android 设计模式
Android官方架构组件介绍之LifeCycle,Android架构组件一共包括以下几个:LifeCycle:与Activity和Fragment的生命周期有关LiveData:异步可订阅数据,也是生命周期感知ViewModel:视图数据持有模型,也是生命周期感知Room:SQLite抽象层,用于简化SQLite数据存储官网设计原则Android应用程序的开发使用Java编写,在架构上使用MVC
设计模式 | 详解设计模式的七大原则
一颗白菜o
学习之路 JavaWeb 随记 设计模式 java 面试
目录一、设计模式的目的二、设计模式七大原则1、单一职责原则2、接口隔离原则3、依赖倒转原则4、里氏替换原则5、开闭原则6、迪米特法则7、合成复用原则设计原则核心思想一、设计模式的目的编写软件的过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序具有更好的:代码重用性(即相同功能的代码,不用多次编写)可读性(即编程规范性,便于其他程序员的阅
设计模式之七大设计原则详解
carl的分享笔记
设计模式与设计原则 设计模式 java 设计原则 面试
七大设计原则:七大设计原则:开闭原则、依赖倒置原则、单一职责原则、接口隔离原则、迪米特原则、里氏替换原则、合成复用原则Java有三大特性:封装、继承、多态。而这七大设计原则,更像是对三大特性的一种体现。七大原则并不是分别独立的原则,他们之间是相互有联系的,甚至可以看做是一体的。有时候你为了符合某种原则会无意之间破坏另一个原则有时候你为了符合某种原则还会发现这也符合另外几种原则开闭原则对(类、方法)
一些项目架构设计
想要追着光
面试复习 1024程序员节 java
本文章目录面向对象程序设计的主要原则1、单一职责原则(Single-ResponsibilityPrinciple)2、里氏代换原则(LiskovSubstitutionPrinciple)3、依赖倒置原则(DependenceInversionPrinciple)4、接口隔离原则(InterfaceSegregationPrinciple)5、迪米特原则(LawofDemeter)数据库设计原则
【设计模式】第四章:原型模式详解及应用案例
Bummon.
设计模式 原型模式 设计模式
系列文章【设计模式】七大设计原则【设计模式】第一章:单例模式【设计模式】第二章:工厂模式【设计模式】第三章:建造者模式【设计模式】第四章:原型模式【设计模式】第五章:适配器模式【设计模式】第六章:装饰器模式【设计模式】第七章:代理模式【设计模式】第八章:桥接模式【设计模式】第九章:外观模式/门面模式【设计模式】第十章:组合模式【设计模式】第十一章:享元模式【设计模式】第十二章:观察者模式【设计模式
软件架构师:理论与实践全攻略
二院大蛙
本文还有配套的精品资源,点击获取简介:本文探讨了软件架构师在IT行业中的重要性,讲解了软件架构设计的核心概念和实践方法。软件架构设计作为软件开发的关键阶段,定义了系统的整体结构和组织方式,包括模块化设计原则、系统扩展性、稳定性、可维护性和技术选型等方面。文章还强调了沟通协作的重要性,以及软件架构的迭代和敏捷性,旨在帮助读者成为优秀的软件架构师。1.软件架构设计核心概念在构建复杂的软件系统时,良好的
小规模的流处理框架.Part 1: thread pools
loredp
java threadpool 流处理
原文链接作者:TomaszNurkiewicz译者:simonwang(译者:强力推荐这篇文章,作者设计了一个用于小流量的流式数据处理框架,并详细给出了每一个需要注意的设计细节,对比了不同设计方案的优缺点,能够让你对流处理过程,某些设计模式和设计原则以及指标度量工具有一个更深刻的认识!)在GeeCON2016上我为我的公司准备了一个编程竞赛,这次的任务是设计并实现一个能够满足以下要求的系统:系统能
go--知识点
chanTwo_00
golang 开发语言 后端
Go语言遵循简洁、明确的设计原则,因此它没有类似的魔法函数机制。Go语言中有一些特性可以起到类似魔法函数的效果,例如init()函数。Go中有一个特别的函数init(),它会在包初始化时自动调用,而无需显式调用。每个包可以定义多个init()函数,它们会按照声明顺序在main()函数之前执行。packagemainimport"fmt"funcinit(){fmt.Println("Thisrun
6、FreeCAD的设计
网卡了
FreeCAD FreeCAD
一、FreeCAD的模块化设计(插件系统)模块化设计是成功的软件架构的关键设计原则。FreeCAD采用了与Salome平台相似的模块化结构,后者是一个开源的CAE平台,包含几何建模、网格划分、FEM和CFD求解器模块。FreeCAD拥有生成新模块的基础设施、模板和Python代码。快速入门FreeCAD提供了官方模板用于创建新模块,这些模板包括C++模板和纯Python模板,位于官方源码仓库中。f
流程制造行业数字化智能工厂总体规划建设方案:1. 总体设计方法:确立智能工厂的设计原则和方法论,以支持整个规划和实施过程。 2. 业务调研与分析:深入了解企业的业务流程、技术需求和市场定位。
数字化建设方案
数字化转型 数据治理 主数据 数据仓库 制造
流程制造行业数字化智能工厂总体规划建设方案流程制造行业数字化智能工厂总体规划建设方案总体设计方法智能工厂设计原则确立方法论支持与规划实施跨部门协作与沟通机制持续改进策略业务调研与分析企业业务流程梳理技术需求评估与对接市场定位及竞争策略调研成果整合与报告系统架构规划数字化管理框架构建核心业务模块划分数据集成与共享策略系统可扩展性与灵活性保障功能架构设计智能机构设置及职责划分智能检测与监控功能开发智能
【Java那些年系列-启航篇 04】Java程序架构:深入理解类与对象的设计原则
夏之以寒
Java那些年专栏 java 架构 类 对象 数据结构
作者名称:纸飞机-暖阳作者简介:专注于Java和大数据领域,致力于探索技术的边界,分享前沿的实践和洞见文章专栏:Java那些年专栏专栏介绍:本专栏涵盖了JavaSE从基础语法到面向对象编程,从异常处理到集合框架,从I/O流到多线程并发,再到网络编程和虚拟机内部机制等一系列编程要素个人感慨:市面上关于JavaSE的学习路线或知识图谱很繁杂,学习起来比较费劲,Java知识体系非常庞大,刚接触阶段只需要
企业级业务架构(EBA)设计方法论
数字化建设方案
数字化转型 数据治理 主数据 数据仓库 架构 数据库 运维
企业级业务架构(EBA)设计方法论企业级业务架构(EBA)设计方法论引言目的和背景业务架构定义与重要性设计方法论概述企业战略与业务架构关系企业战略制定过程业务架构对企业战略支撑作用战略导向下业务架构调整策略EBA设计原则与方法设计原则设计方法关键成功因素EBA核心组件设计组织架构设计流程体系设计信息系统架构设计数据治理与管理体系设计EBA实施落地策略实施步骤与计划制定变革管理与风险应对策略培训、宣
企业架构设计(业务架构、数据架构、应用架构、技术架构)方法及实例
数字化建设方案
数字化转型 数据治理 主数据 数据仓库 架构 大数据 微服务
企业架构设计方法及实例企业架构设计方法及实例企业架构设计概述定义与重要性架构设计原则架构设计流程业务架构设计业务架构定义与目标业务架构组成要素业务架构设计方法业务架构实例分析数据架构设计数据架构定义与目标数据架构组成要素数据架构设计方法数据架构实例分析应用架构设计应用架构定义与目标应用架构组成要素应用架构设计方法应用架构实例分析技术架构设计技术架构定义与目标技术架构组成要素技术架构设计方法技术架构
Apache Flink 运行时架构
生病的毛毛虫
flink 架构
Flink运行时架构Flink整个系统由两个主要部分组成JobManager和TaskManager,Flink架构也遵循Master-Slave架构设计原则,JobManager为Master节点,TaskManager为worker(Slave)节点,所有组件之间通讯都是借助AkkaFramework,包括任务的状态以及Checkpoint触发等信息。Flink运行时候架构如下:FlinkCl
Java实战:分布式ID生成方案
拥抱AI
java 分布式 开发语言
在分布式系统的设计与开发过程中,如何生成全局唯一、有序且高可用的ID是一个绕不开的核心问题。尤其是在电商、社交网络、金融交易等领域,ID不仅是业务数据的重要标识,还可能直接影响系统的稳定性和扩展性。本文将深入剖析分布式ID生成方案的设计原则、常见算法,并通过Java示例展示一种可行的实现方式。一、分布式ID生成的需求分析全局唯一性:在分布式环境下,必须保证生成的ID在全球范围内不重复,避免数据冲突
element-ui Cascader级联选择器实现一级二级单选,三级多选
搬砖的小白
element-ui使用心得 vue
exportdefault{data(){return{value:[],shareScopeEnd:[],options:[{value:'zhinan',label:'指南',children:[{value:'shejiyuanze',label:'设计原则',children:[{value:'yizhi',label:'一致'},{value:'fankui',label:'反馈'},{
物联网平台开发核心技术揭秘-架构设计篇
架构师修炼
物联网平台开发实战 网络 物联网 人工智能 java python
一书,力推!引言上一篇物联网平台开发实战-初探从宏观层面了解了物联网平台相关内容。随着物联网的快速发展和普及,越来越多的企业和机构开始构建自己的物联网平台。物联网平台是连接大量设备和系统的中心枢纽,通过数据传输和处理,实现设备之间的互联和智能控制。这一篇将讨论物联网平台架构设计,主要从物联网平台的概述、架构设计原则、要素以及设备层、数据处理层讨论。一、物联网平台概述物联网平台是实现物联网的核心组成
spring ioc是做什么的?
gb4215287
java spring log4j java
Spring框架的IOC(InversionofControl,控制反转)是Spring框架的一个核心特性,它主要解决的是对象管理和依赖管理的问题。下面我将简要解释SpringIOC的主要作用:什么是SpringIOC?控制反转:这是一种设计原则,目的是减少代码之间的耦合度。在Spring中,IOC意味着将对象的控制权转移给Spring框架。这意味着对象的创建、配置和管理都由Spring容器负责。
医药医疗行业数字化转型数据架构设计方法论及典型案例
数字化建设方案
数字化转型 数据治理 主数据 数据仓库 大数据 人工智能 数据挖掘 数据库 架构
医药医疗行业数字化转型数据架构设计方法论及典型案例医药医疗行业数字化转型数据架构设计方法论及典型案例数字化转型背景与趋势医药行业现状及挑战数字化转型必要性发展趋势与前景展望数据架构设计方法论数据架构概述及重要性设计原则与策略制定实施步骤与关键技术典型案例分析:某大型药企数据架构实践项目背景与目标设定数据架构规划与设计过程实施效果及经验总结面临的挑战与解决方案数据质量管理问题及对策数据安全防护策略部
迪米特法则
pumpkin84514
架构设计 迪米特法则 系统架构
什么是迪米特法则?迪米特法则,也叫“最少知识原则”(LawofDemeter),是一种编程设计原则。它的核心思想是:一个对象应该尽量少地了解其他对象,特别是它的内部细节。通俗解释想象一下,你在家里请了一个清洁工来打扫房间。你只需要告诉他“去打扫客厅”,而不是告诉他如何使用每一件工具、在哪儿找到抹布、以及每个角落怎么清理。如果你告诉清洁工太多细节,这不仅让事情变得复杂,还可能会让清洁工因为不熟悉而做
Spring中常见的设计模式
苓风星河
设计模式 java spring
Spring中常见的设计模式1、Java设计模式设计模式(DesignPattern)是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。早在1995年,GOF合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了23种设计模式,人称「GoF设计模式」。这23种设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继
Hadoop(一)
朱辉辉33
hadoop linux
今天在诺基亚第一天开始培训大数据,因为之前没接触过Linux,所以这次一起学了,任务量还是蛮大的。
首先下载安装了Xshell软件,然后公司给了账号密码连接上了河南郑州那边的服务器,接下来开始按照给的资料学习,全英文的,头也不讲解,说锻炼我们的学习能力,然后就开始跌跌撞撞的自学。这里写部分已经运行成功的代码吧.
在hdfs下,运行hadoop fs -mkdir /u
maven An error occurred while filtering resources
blackproof
maven 报错
转:http://stackoverflow.com/questions/18145774/eclipse-an-error-occurred-while-filtering-resources
maven报错:
maven An error occurred while filtering resources
Maven -> Update Proje
jdk常用故障排查命令
daysinsun
jvm
linux下常见定位命令:
1、jps 输出Java进程
-q 只输出进程ID的名称,省略主类的名称;
-m 输出进程启动时传递给main函数的参数;
&nb
java 位移运算与乘法运算
周凡杨
java 位移 运算 乘法
对于 JAVA 编程中,适当的采用位移运算,会减少代码的运行时间,提高项目的运行效率。这个可以从一道面试题说起:
问题:
用最有效率的方法算出2 乘以8 等於几?”
答案:2 << 3
由此就引发了我的思考,为什么位移运算会比乘法运算更快呢?其实简单的想想,计算机的内存是用由 0 和 1 组成的二
java中的枚举(enmu)
g21121
java
从jdk1.5开始,java增加了enum(枚举)这个类型,但是大家在平时运用中还是比较少用到枚举的,而且很多人和我一样对枚举一知半解,下面就跟大家一起学习下enmu枚举。先看一个最简单的枚举类型,一个返回类型的枚举:
public enum ResultType {
/**
* 成功
*/
SUCCESS,
/**
* 失败
*/
FAIL,
MQ初级学习
510888780
activemq
1.下载ActiveMQ
去官方网站下载:http://activemq.apache.org/
2.运行ActiveMQ
解压缩apache-activemq-5.9.0-bin.zip到C盘,然后双击apache-activemq-5.9.0-\bin\activemq-admin.bat运行ActiveMQ程序。
启动ActiveMQ以后,登陆:http://localhos
Spring_Transactional_Propagation
布衣凌宇
spring transactional
//事务传播属性
@Transactional(propagation=Propagation.REQUIRED)//如果有事务,那么加入事务,没有的话新创建一个
@Transactional(propagation=Propagation.NOT_SUPPORTED)//这个方法不开启事务
@Transactional(propagation=Propagation.REQUIREDS_N
我的spring学习笔记12-idref与ref的区别
aijuans
spring
idref用来将容器内其他bean的id传给<constructor-arg>/<property>元素,同时提供错误验证功能。例如:
<bean id ="theTargetBean" class="..." />
<bean id ="theClientBean" class=&quo
Jqplot之折线图
antlove
js jquery Web timeseries jqplot
timeseriesChart.html
<script type="text/javascript" src="jslib/jquery.min.js"></script>
<script type="text/javascript" src="jslib/excanvas.min.js&
JDBC中事务处理应用
百合不是茶
java JDBC编程 事务控制语句
解释事务的概念; 事务控制是sql语句中的核心之一;事务控制的作用就是保证数据的正常执行与异常之后可以恢复
事务常用命令:
Commit提交
[转]ConcurrentHashMap Collections.synchronizedMap和Hashtable讨论
bijian1013
java 多线程 线程安全 HashMap
在Java类库中出现的第一个关联的集合类是Hashtable,它是JDK1.0的一部分。 Hashtable提供了一种易于使用的、线程安全的、关联的map功能,这当然也是方便的。然而,线程安全性是凭代价换来的――Hashtable的所有方法都是同步的。此时,无竞争的同步会导致可观的性能代价。Hashtable的后继者HashMap是作为JDK1.2中的集合框架的一部分出现的,它通过提供一个不同步的
ng-if与ng-show、ng-hide指令的区别和注意事项
bijian1013
JavaScript AngularJS
angularJS中的ng-show、ng-hide、ng-if指令都可以用来控制dom元素的显示或隐藏。ng-show和ng-hide根据所给表达式的值来显示或隐藏HTML元素。当赋值给ng-show指令的值为false时元素会被隐藏,值为true时元素会显示。ng-hide功能类似,使用方式相反。元素的显示或
【持久化框架MyBatis3七】MyBatis3定义typeHandler
bit1129
TypeHandler
什么是typeHandler?
typeHandler用于将某个类型的数据映射到表的某一列上,以完成MyBatis列跟某个属性的映射
内置typeHandler
MyBatis内置了很多typeHandler,这写typeHandler通过org.apache.ibatis.type.TypeHandlerRegistry进行注册,比如对于日期型数据的typeHandler,
上传下载文件rz,sz命令
bitcarter
linux命令rz
刚开始使用rz上传和sz下载命令:
因为我们是通过secureCRT终端工具进行使用的所以会有上传下载这样的需求:
我遇到的问题:
sz下载A文件10M左右,没有问题
但是将这个文件A再传到另一天服务器上时就出现传不上去,甚至出现乱码,死掉现象,具体问题
解决方法:
上传命令改为;rz -ybe
下载命令改为:sz -be filename
如果还是有问题:
那就是文
通过ngx-lua来统计nginx上的虚拟主机性能数据
ronin47
ngx-lua 统计 解禁ip
介绍
以前我们为nginx做统计,都是通过对日志的分析来完成.比较麻烦,现在基于ngx_lua插件,开发了实时统计站点状态的脚本,解放生产力.项目主页: https://github.com/skyeydemon/ngx-lua-stats 功能
支持分不同虚拟主机统计, 同一个虚拟主机下可以分不同的location统计.
可以统计与query-times request-time
java-68-把数组排成最小的数。一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的。例如输入数组{32, 321},则输出32132
bylijinnan
java
import java.util.Arrays;
import java.util.Comparator;
public class MinNumFromIntArray {
/**
* Q68输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。
* 例如输入数组{32, 321},则输出这两个能排成的最小数字32132。请给出解决问题
Oracle基本操作
ccii
Oracle SQL总结 Oracle SQL语法 Oracle基本操作 Oracle SQL
一、表操作
1. 常用数据类型
NUMBER(p,s):可变长度的数字。p表示整数加小数的最大位数,s为最大小数位数。支持最大精度为38位
NVARCHAR2(size):变长字符串,最大长度为4000字节(以字符数为单位)
VARCHAR2(size):变长字符串,最大长度为4000字节(以字节数为单位)
CHAR(size):定长字符串,最大长度为2000字节,最小为1字节,默认
[强人工智能]实现强人工智能的路线图
comsci
人工智能
1:创建一个用于记录拓扑网络连接的矩阵数据表
2:自动构造或者人工复制一个包含10万个连接(1000*1000)的流程图
3:将这个流程图导入到矩阵数据表中
4:在矩阵的每个有意义的节点中嵌入一段简单的
给Tomcat,Apache配置gzip压缩(HTTP压缩)功能
cwqcwqmax9
apache
背景:
HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML ,CSS,Javascript , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等输出的网页也能进行压缩,
SpringMVC and Struts2
dashuaifu
struts2 springMVC
SpringMVC VS Struts2
1:
spring3开发效率高于struts
2:
spring3 mvc可以认为已经100%零配置
3:
struts2是类级别的拦截, 一个类对应一个request上下文,
springmvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应
所以说从架构本身上 spring3 mvc就容易实现r
windows常用命令行命令
dcj3sjt126com
windows cmd command
在windows系统中,点击开始-运行,可以直接输入命令行,快速打开一些原本需要多次点击图标才能打开的界面,如常用的输入cmd打开dos命令行,输入taskmgr打开任务管理器。此处列出了网上搜集到的一些常用命令。winver 检查windows版本 wmimgmt.msc 打开windows管理体系结构(wmi) wupdmgr windows更新程序 wscrip
再看知名应用背后的第三方开源项目
dcj3sjt126com
ios
知名应用程序的设计和技术一直都是开发者需要学习的,同样这些应用所使用的开源框架也是不可忽视的一部分。此前《
iOS第三方开源库的吐槽和备忘》中作者ibireme列举了国内多款知名应用所使用的开源框架,并对其中一些框架进行了分析,同样国外开发者
@iOSCowboy也在博客中给我们列出了国外多款知名应用使用的开源框架。另外txx's blog中详细介绍了
Facebook Paper使用的第三
Objective-c单例模式的正确写法
jsntghf
单例 ios iPhone
一般情况下,可能我们写的单例模式是这样的:
#import <Foundation/Foundation.h>
@interface Downloader : NSObject
+ (instancetype)sharedDownloader;
@end
#import "Downloader.h"
@implementation
jquery easyui datagrid 加载成功,选中某一行
hae
jquery easyui datagrid 数据加载
1.首先你需要设置datagrid的onLoadSuccess
$(
'#dg'
).datagrid({onLoadSuccess :
function
(data){
$(
'#dg'
).datagrid(
'selectRow'
,3);
}});
2.onL
jQuery用户数字打分评价效果
ini
JavaScript html jquery Web css
效果体验:http://hovertree.com/texiao/jquery/5.htmHTML文件代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>jQuery用户数字打分评分代码 - HoverTree</
mybatis的paramType
kerryg
DAO sql
MyBatis传多个参数:
1、采用#{0},#{1}获得参数:
Dao层函数方法:
public User selectUser(String name,String area);
对应的Mapper.xml
<select id="selectUser" result
centos 7安装mysql5.5
MrLee23
centos
首先centos7 已经不支持mysql,因为收费了你懂得,所以内部集成了mariadb,而安装mysql的话会和mariadb的文件冲突,所以需要先卸载掉mariadb,以下为卸载mariadb,安装mysql的步骤。
#列出所有被安装的rpm package rpm -qa | grep mariadb
#卸载
rpm -e mariadb-libs-5.
利用thrift来实现消息群发
qifeifei
thrift
Thrift项目一般用来做内部项目接偶用的,还有能跨不同语言的功能,非常方便,一般前端系统和后台server线上都是3个节点,然后前端通过获取client来访问后台server,那么如果是多太server,就是有一个负载均衡的方法,然后最后访问其中一个节点。那么换个思路,能不能发送给所有节点的server呢,如果能就
实现一个sizeof获取Java对象大小
teasp
java HotSpot 内存 对象大小 sizeof
由于Java的设计者不想让程序员管理和了解内存的使用,我们想要知道一个对象在内存中的大小变得比较困难了。本文提供了可以获取对象的大小的方法,但是由于各个虚拟机在内存使用上可能存在不同,因此该方法不能在各虚拟机上都适用,而是仅在hotspot 32位虚拟机上,或者其它内存管理方式与hotspot 32位虚拟机相同的虚拟机上 适用。
SVN错误及处理
xiangqian0505
SVN提交文件时服务器强行关闭
在SVN服务控制台打开资源库“SVN无法读取current” ---摘自网络 写道 SVN无法读取current修复方法 Can't read file : End of file found
文件:repository/db/txn_current、repository/db/current
其中current记录当前最新版本号,txn_current记录版本库中版本