首页 文章 精选 留言 我的

精选列表

搜索[安全机制],共10000篇文章
优秀的个人博客,低调大师

Docker multi-stage build机制

随着17.05版本的发布,Docker对于镜像构建这块也作了一项重要更新,那就是 multi-stage build(多阶段构建),这对于长期因为构建镜像太大而困扰的小伙伴们来说真是雪中送炭。 不支持多阶段构建 在17.05版本之前,我们构建Docker镜像时,通常会采用两种方式: 将所有的构建过程编写在同一个Dockerfile中,包括项目及其依赖库的编译、测试、打包等流程,这里可能会带来的一些问题: Dockerfile特别臃肿 镜像层次特别深 存在源码泄露的风险 稍微优雅的一种方式,就是我们事先在外部将项目及其依赖库编译测试打包好后,再将其拷贝到构建目录中,这种虽然可以很好地规避第一种方式存在的风险点,但仍需要我们编写两套Dockerfile或者一些脚本才能将其两个阶段自动整合起来 这里以一个简单的JAVA项目镜像构建为例来说明这两种构建方

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

logstash处理文件进度记录机制

假如使用如下配置处理日志 input { file { path => "/home/vagrant/logstash/logstash-2.2.2/dbpool-logs/dev/common-sql-*.log" start_position => "beginning" type => "sql" codec => json { charset => "UTF-8" } } } output { if "_grokparsefailure" in [tags] { }else{ if [type] == "sql"{ elasticsearch { hosts => ["http://192.168.33.10:9200"] index => "common-sql-%{+YYYY.MM.dd}" } } } } 所有匹配common-sql-*.log的文件都将被处理 第一次从头开始处理文件 处理后以json格式输出到elasticsearch logstash如何记录处理进度? 第一次运行logstash时从头处理文件,假如此时有两个文件匹配上则按顺序开始处理文件。 logstash处理过程中不断将每个文件处理的进度写入到某个地方,这就是sincedb。 sincedb一般以隐藏文件默认写到home目录下面,文件名类似.sincedb_6268051ae572b42bd86b7f9e8c1e004b。 sincedb的格式为inode majorNumber minor Number pos。每行记录每个文件处理进度,比如下面的例子,表示inode为177037的文件处理到25951716位置、inode为176956的文件处理到32955178位置。 177037 0 64768 25951716 176956 0 64768 32955178 用stat看看这两个文件inode信息。可以看到两个文件都已经处理完了。如果没处理完关闭了logstash则会在下次启动时继续处理。 [vagrant@hb-localhost ~]$ stat logstash/logstash-2.2.2/dbpool-logs/dev/common-sql-2016-11-24.log File: `logstash/logstash-2.2.2/dbpool-logs/dev/common-sql-2016-11-24.log' Size: 32955178 Blocks: 64368 IO Block: 4096 regular file Device: fd00h/64768d Inode: 176956 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 501/ vagrant) Gid: ( 501/ vagrant) Access: 2016-11-24 02:08:19.058506565 +0000 Modify: 2016-11-24 01:46:14.000000000 +0000 Change: 2016-11-24 02:05:06.194122690 +0000 [vagrant@hb-localhost ~]$ stat logstash/logstash-2.2.2/dbpool-logs/dev/common-sql-2016-11-23.log File: `logstash/logstash-2.2.2/dbpool-logs/dev/common-sql-2016-11-23.log' Size: 25951716 Blocks: 50688 IO Block: 4096 regular file Device: fd00h/64768d Inode: 177037 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 501/ vagrant) Gid: ( 501/ vagrant) Access: 2016-11-24 02:15:28.217978771 +0000 Modify: 2016-11-23 13:19:16.000000000 +0000 Change: 2016-11-24 02:15:27.913826772 +0000 如果往这两个文件追加日志则将往下继续处理,而且也会将进度更新到sincedb文件中。 如果处理完了关闭logstash,下次再启动时则不会再从头开始处理,因为sincedb已经记录了进度,不要以为start_position => “beginning”就是每次都从头处理,如果把sincedb文件删了又会从头开始处理。 ========广告时间======== 鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。 为什么写《Tomcat内核设计剖析》 =========================

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

android log机制——输出log【转】

转自:http://blog.csdn.net/tdstds/article/details/19084327 目录(?)[-] 在android Java code中输出log Logprintln_native方法 本地层代码Log输出 转自: http://my.oschina.net/wolfcs/blog/164624 Androidlog系统。 在android Java code中输出log android系统有4种类型、6个优先级的log,有一些常量用于标识这些信息,相关的定义在frameworks/base/core/Java/android/util/Log.java中可以看到: 01 /** 02 * Priority constant for the println method; use Log.v. 03 */ 04 publicstaticfinalintVERBOSE =2; 05 06 /** 07 * Priority constant for the println method; use Log.d. 08 */ 09 publicstaticfinalintDEBUG =3; 10 11 /** 12 * Priority constant for the println method; use Log.i. 13 */ 14 publicstaticfinalintINFO =4; 15 16 /** 17 * Priority constant for the println method; use Log.w. 18 */ 19 publicstaticfinalintWARN =5; 20 21 /** 22 * Priority constant for the println method; use Log.e. 23 */ 24 publicstaticfinalintERROR =6; 25 26 /** 27 * Priority constant for the println method. 28 */ 29 publicstaticfinalintASSERT =7; 30 31 /** @hide */publicstaticfinalintLOG_ID_MAIN =0; 32 /** @hide */publicstaticfinalintLOG_ID_RADIO =1; 33 /** @hide */publicstaticfinalintLOG_ID_EVENTS =2; 34 /** @hide */publicstaticfinalintLOG_ID_SYSTEM =3; Java层可以通过三个class来输出其中三种类型的log,三种类型分别为MAIN、RADIO和SYSTEM,三个class分别为Log、Rlog和Slog,其package则分别为android.util、android.telephony和android.util。这些用于打印log的classes,其构造函数都为private,因而都不能创建其对象,但它们都提供了静态方法来给用户打印log。各个log打印class的实现都大同小异,可以看一下Log这个class中的一些: 01 publicstaticintv(String tag, String msg, Throwable tr) { 02 returnprintln_native(LOG_ID_MAIN, VERBOSE, tag, msg +'\n'+ getStackTraceString(tr)); 03 } 04 05 /** 06 * Send a {@link #DEBUG} log message. 07 * @param tag Used to identify the source of a log message. It usually identifies 08 * the class or activity where the log call occurs. 09 * @param msg The message you would like logged. 10 */ 11 publicstaticintd(String tag, String msg) { 12 returnprintln_native(LOG_ID_MAIN, DEBUG, tag, msg); 13 } 最终都会是调用Log.println_native()静态native方法来打印log,各个类中各个方法的不同之处也仅在于参数的差异。 Log.println_native()方法 这个方法的code在/frameworks/base/core/jni/android_util_Log.cpp,为: 01 staticjint android_util_Log_println_native(JNIEnv* env, jobject clazz, 02 jint bufID, jint priority, jstring tagObj, jstring msgObj) 03 { 04 constchar* tag = NULL; 05 constchar* msg = NULL; 06 07 if(msgObj == NULL) { 08 jniThrowNullPointerException(env,"println needs a message"); 09 return-1; 10 } 11 12 if(bufID < 0 || bufID >= LOG_ID_MAX) { 13 jniThrowNullPointerException(env,"bad bufID"); 14 return-1; 15 } 16 17 if(tagObj != NULL) 18 tag = env->GetStringUTFChars(tagObj, NULL); 19 msg = env->GetStringUTFChars(msgObj, NULL); 20 21 intres = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg); 22 23 if(tag != NULL) 24 env->ReleaseStringUTFChars(tagObj, tag); 25 env->ReleaseStringUTFChars(msgObj, msg); 26 27 returnres; 28 } 29 30 /* 31 * JNI registration. 32 */ 33 staticJNINativeMethod gMethods[] = { 34 /* name, signature, funcPtr */ 35 {"isLoggable","(Ljava/lang/String;I)Z", (void*) android_util_Log_isLoggable }, 36 {"println_native","(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native }, 37 }; 可以看到,干的都是转换参数的事情,最终再call到__android_log_buf_write()函数,这个函数的定义在system/core/liblog/logd_write.c,为: 01 int__android_log_buf_write(intbufID,intprio,constchar*tag,constchar*msg) 02 { 03 structiovec vec[3]; 04 chartmp_tag[32]; 05 06 if(!tag) 07 tag =""; 08 09 /* XXX: This needs to go! */ 10 if((bufID != LOG_ID_RADIO) && 11 (!strcmp(tag,"HTC_RIL") || 12 !strncmp(tag,"RIL", 3) ||/* Any log tag with "RIL" as the prefix */ 13 !strncmp(tag,"IMS", 3) ||/* Any log tag with "IMS" as the prefix */ 14 !strcmp(tag,"AT") || 15 !strcmp(tag,"GSM") || 16 !strcmp(tag,"STK") || 17 !strcmp(tag,"CDMA") || 18 !strcmp(tag,"PHONE") || 19 !strcmp(tag,"SMS"))) { 20 bufID = LOG_ID_RADIO; 21 // Inform third party apps/ril/radio.. to use Rlog or RLOG 22 snprintf(tmp_tag,sizeof(tmp_tag),"use-Rlog/RLOG-%s", tag); 23 tag = tmp_tag; 24 } 25 26 vec[0].iov_base = (unsignedchar*) &prio; 27 vec[0].iov_len = 1; 28 vec[1].iov_base = (void*) tag; 29 vec[1].iov_len =strlen(tag) + 1; 30 vec[2].iov_base = (void*) msg; 31 vec[2].iov_len =strlen(msg) + 1; 32 33 returnwrite_to_log(bufID, vec, 3); 34 } 做了三件事情,一是根据log的tag,转换bufID,二是用传进来的参数构造一个struct iovec数组,三是将前一步构造的数组作为参数调用write_to_log()。write_to_log()是一个函数指针,在开始时,它指向了__write_to_log_init(): 1 staticint(*write_to_log)(log_id_t,structiovec *vec,size_tnr) = __write_to_log_init; __write_to_log_init()的实现如下: 01 staticint__write_to_log_init(log_id_t log_id,structiovec *vec,size_tnr) 02 { 03 #ifdef HAVE_PTHREADS 04 pthread_mutex_lock(&log_init_lock); 05 #endif 06 07 if(write_to_log == __write_to_log_init) { 08 log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY); 09 log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY); 10 log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY); 11 log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY); 12 13 write_to_log = __write_to_log_kernel; 14 15 if(log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 || 16 log_fds[LOG_ID_EVENTS] < 0) { 17 log_close(log_fds[LOG_ID_MAIN]); 18 log_close(log_fds[LOG_ID_RADIO]); 19 log_close(log_fds[LOG_ID_EVENTS]); 20 log_fds[LOG_ID_MAIN] = -1; 21 log_fds[LOG_ID_RADIO] = -1; 22 log_fds[LOG_ID_EVENTS] = -1; 23 write_to_log = __write_to_log_null; 24 } 25 26 if(log_fds[LOG_ID_SYSTEM] < 0) { 27 log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN]; 28 } 29 } 30 31 #ifdef HAVE_PTHREADS 32 pthread_mutex_unlock(&log_init_lock); 33 #endif 34 35 returnwrite_to_log(log_id, vec, nr); 36 } 这个地方,会检查write_to_log是否指向了__write_to_log_init,也就是是否是第一次打印log,如果是,则打开几个用于输出log的设备文件,然后使write_to_log函数指针指向__write_to_log_kernel,或者在打开输出log设备文件出现异常时,使write_to_log指向__write_to_log_null,最后再次调用经过了重定向的write_to_log,也就是__write_to_log_kernel或者__write_to_log_null函数。我们可以看一下那几个设备文件究竟是什麽(在system/core/include/cutils/logger.h): 1 #define LOGGER_LOG_MAIN "log/main" 2 #define LOGGER_LOG_RADIO "log/radio" 3 #define LOGGER_LOG_EVENTS "log/events" 4 #define LOGGER_LOG_SYSTEM "log/system" 接着继续来看__write_to_log_kernel或者__write_to_log_null函数: 01 staticint__write_to_log_null(log_id_t log_fd,structiovec *vec,size_tnr) 02 { 03 return-1; 04 } 05 06 staticint__write_to_log_kernel(log_id_t log_id,structiovec *vec,size_tnr) 07 { 08 ssize_t ret; 09 intlog_fd; 10 11 if(/*(int)log_id >= 0 &&*/(int)log_id < (int)LOG_ID_MAX) { 12 log_fd = log_fds[(int)log_id]; 13 }else{ 14 returnEBADF; 15 } 16 17 do{ 18 ret = log_writev(log_fd, vec, nr); 19 }while(ret < 0 &&errno== EINTR); 20 21 returnret; 22 } 由log_id获取到对应的log_fd,然后调用log_writev()打印log。可以看一下log_writev()的定义,它是一个宏: 01 #if FAKE_LOG_DEVICE 02 // This will be defined when building for the host. 03 #define log_open(pathname, flags) fakeLogOpen(pathname, flags) 04 #define log_writev(filedes, vector, count) fakeLogWritev(filedes, vector, count) 05 #define log_close(filedes) fakeLogClose(filedes) 06 #else 07 #define log_open(pathname, flags) open(pathname, (flags) | O_CLOEXEC) 08 #define log_writev(filedes, vector, count) writev(filedes, vector, count) 09 #define log_close(filedes) close(filedes) 10 #endif 这些就都是标准的unix系统调用了。 本地层代码Log输出 以一些比较典型的native代码打印log的case为例。先来看一下,在JNI的code中打印log的方法。在JNI中,比较常见到用ALOGx这一组宏来打印log,比如在frameworks/base/core/jni/android/graphics/TextLayoutCache.cpp这个文件中的dumpCacheStats()函数: 01 voidTextLayoutCache::dumpCacheStats() { 02 floatremainingPercent = 100 * ((mMaxSize - mSize) / ((float)mMaxSize)); 03 floattimeRunningInSec = (systemTime(SYSTEM_TIME_MONOTONIC) - mCacheStartTime) / 1000000000; 04 05 size_tcacheSize = mCache.size(); 06 07 ALOGD("------------------------------------------------"); 08 ALOGD("Cache stats"); 09 ALOGD("------------------------------------------------"); 10 ALOGD("pid : %d", getpid()); 11 ALOGD("running : %.0f seconds", timeRunningInSec); 12 ALOGD("entries : %d", cacheSize); 13 ALOGD("max size : %d bytes", mMaxSize); 14 ALOGD("used : %d bytes according to mSize", mSize); 15 ALOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent); 16 ALOGD("hits : %d", mCacheHitCount); 17 ALOGD("saved : %0.6f ms", mNanosecondsSaved * 0.000001f); 18 ALOGD("------------------------------------------------"); 19 } 使用这组宏,需要定义另外一个宏来作为所打印log的tag: 1 #define LOG_TAG "TextLayoutCache" 此外,还要include头文件<cutils/log.h>。来看一下这些宏中的一些的定义: 01 /* 02 * Simplified macro to send a debug log message using the current LOG_TAG. 03 */ 04 #ifndef ALOGD 05 #define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) 06 #endif 07 08 /* 09 * Simplified macro to send a warning log message using the current LOG_TAG. 10 */ 11 #ifndef ALOGW 12 #define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) 13 #endif 14 15 /* 16 * Basic log message macro. 17 * 18 * Example: 19 * ALOG(LOG_WARN, NULL, "Failed with error %d", errno); 20 * 21 * The second argument may be NULL or "" to indicate the "global" tag. 22 */ 23 #ifndef ALOG 24 #define ALOG(priority, tag, ...) \ 25 LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) 26 #endif 27 28 /* 29 * Log macro that allows you to specify a number for the priority. 30 */ 31 #ifndef LOG_PRI 32 #define LOG_PRI(priority, tag, ...) \ 33 android_printLog(priority, tag, __VA_ARGS__) 34 #endif 35 36 #define android_printLog(prio, tag, fmt...) \ 37 __android_log_print(prio, tag, fmt) 先来看一下,在native层中定义的priority(在system/core/include/android/log.h中): 01 /* 02 * Android log priority values, in ascending priority order. 03 */ 04 typedefenumandroid_LogPriority { 05 ANDROID_LOG_UNKNOWN = 0, 06 ANDROID_LOG_DEFAULT,/* only for SetMinPriority() */ 07 ANDROID_LOG_VERBOSE, 08 ANDROID_LOG_DEBUG, 09 ANDROID_LOG_INFO, 10 ANDROID_LOG_WARN, 11 ANDROID_LOG_ERROR, 12 ANDROID_LOG_FATAL, 13 ANDROID_LOG_SILENT,/* only for SetMinPriority(); must be last */ 14 } android_LogPriority; 另外,这些宏最终都会call到__android_log_print(),也是在system/core/liblog/logd_write.c中: 01 int__android_log_print(intprio,constchar*tag,constchar*fmt, ...) 02 { 03 va_listap; 04 charbuf[LOG_BUF_SIZE]; 05 06 va_start(ap, fmt); 07 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 08 va_end(ap); 09 10 return__android_log_write(prio, tag, buf); 11 } 先是格式化参数,然后就是调用__android_log_write()函数。这个函数的code如下: 01 int__android_log_write(intprio,constchar*tag,constchar*msg) 02 { 03 structiovec vec[3]; 04 log_id_t log_id = LOG_ID_MAIN; 05 chartmp_tag[32]; 06 07 if(!tag) 08 tag =""; 09 10 /* XXX: This needs to go! */ 11 if(!strcmp(tag,"HTC_RIL") || 12 !strncmp(tag,"RIL", 3) ||/* Any log tag with "RIL" as the prefix */ 13 !strncmp(tag,"IMS", 3) ||/* Any log tag with "IMS" as the prefix */ 14 !strcmp(tag,"AT") || 15 !strcmp(tag,"GSM") || 16 !strcmp(tag,"STK") || 17 !strcmp(tag,"CDMA") || 18 !strcmp(tag,"PHONE") || 19 !strcmp(tag,"SMS")) { 20 log_id = LOG_ID_RADIO; 21 // Inform third party apps/ril/radio.. to use Rlog or RLOG 22 snprintf(tmp_tag,sizeof(tmp_tag),"use-Rlog/RLOG-%s", tag); 23 tag = tmp_tag; 24 } 25 26 vec[0].iov_base = (unsignedchar*) &prio; 27 vec[0].iov_len = 1; 28 vec[1].iov_base = (void*) tag; 29 vec[1].iov_len =strlen(tag) + 1; 30 vec[2].iov_base = (void*) msg; 31 vec[2].iov_len =strlen(msg) + 1; 32 33 returnwrite_to_log(log_id, vec, 3); 34 } 这个函数与我们前面看到的__android_log_buf_write()非常相似。所不同的就是这个函数没有log_id参数,因而它默认是输出MAIN log,当log的TAG为某些特殊字串时,则输出RADIO log。最后同样是调用write_to_log这个函数指针来输出log。 我们再来看一个skia里面打log的SkDebugf()函数的实现: 1 #include <android/log.h> 2 3 voidSkDebugf(constcharformat[], ...) { 4 va_listargs; 5 va_start(args, format); 6 __android_log_vprint(ANDROID_LOG_DEBUG, LOG_TAG, format, args); 7 va_end(args); 8 } call到了__android_log_vprint()来输出log,__android_log_vprint()的定义也在system/core/liblog/logd_write.c中: 1 int__android_log_vprint(intprio,constchar*tag,constchar*fmt,va_listap) 2 { 3 charbuf[LOG_BUF_SIZE]; 4 5 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 6 7 return__android_log_write(prio, tag, buf); 8 } 一样是__android_log_write()函数。 Done. 【作者】 张昺华 【出处】 http://www.cnblogs.com/sky-heaven/ 【博客园】 http://www.cnblogs.com/sky-heaven/ 【新浪博客】 http://blog.sina.com.cn/u/2049150530 【知乎】 http://www.zhihu.com/people/zhang-bing-hua 【我的作品---旋转倒立摆】 http://v.youku.com/v_show/id_XODM5NDAzNjQw.html?spm=a2hzp.8253869.0.0&from=y1.7-2 【我的作品---自平衡自动循迹车】 http://v.youku.com/v_show/id_XODM5MzYyNTIw.html?spm=a2hzp.8253869.0.0&from=y1.7-2 【新浪微博】 张昺华--sky 【twitter】 @sky2030_ 【facebook】 张昺华 zhangbinghua 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

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

PHP 引用计数机制深度解析

某位开发者正在排查一个问题:为什么 PHP 工作进程在处理大约 8000 个任务之后总是因"Allowed memory size exhausted"而崩溃。最终上线的修复方案是"每处理 1000 个任务就重启工作进程"。方案奏效了。真正导致泄漏的根因——一个带有双向指针的父子对象结构——从未被追查。工作进程现在每天重启十次,而背后的原因无人理解。两年后,一次不相关的重构意外破坏了重启逻辑,同一个缺陷演变为生产事故:工作进程在任务中途崩溃,用户看到错误,工程师们在没有心智模型的情况下进行排查,完全不知道内存最初为什么会增长。

资源下载

更多资源
Nacos

Nacos

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

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

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

用户登录
用户注册