Jenkins使用痛点小析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jenkins使用痛点小析相关的知识,希望对你有一定的参考价值。
参考技术AJenkins 刚开始搭建的时候,我们惊叹,这也太方便了吧?功能还这么强,慢慢的,我们会发现对方的缺点了,嗯,恋爱的味道,不对,似乎扯远了,还是说回来 Jenkins 了。
我们很难想象 Jenkins ,这么庞大的一个应用,居然没有数据库。那配置在哪保存呢?运行日志了?构建数据了?等等这些都是需要保存的啊。
当jenkins job数量达到一定量级,访问量大时候,会非常卡顿,仿佛回到了零几年的时候,网页那么卡。
查原因我们会发现瓶颈在 I/O 。因为jenkins每次访问,都需要读取配置,都需要读写日志,这些都是以文件方式写入磁盘的,是 所有slave 节点和 一台master 通信。
可是我们是没有办法做负载均衡的
当我们部署后端服务时候,肯定做 LB(负载均衡) , Jenkins master 因为只能单节点,啊,挂了master,所有slave都掉链子了。
配置 存储 master节点磁盘,嗯,还好,比较小
构建日志 存储在master节点磁盘,这个,百万行代码的编译日志几百M大小,每天N个业务构建M次,存储在master,哈哈,每天上班第一件事清磁盘?
构建产物 存储在master节点磁盘,这个,占磁盘,不安全
针对这种情况了,日志用 ELK ,产物放到到 对象存储
调度,一个好高深的话题,教材上学过操作系统对进程的各种调度算法,什么 先入先出 , 最短耗时 , 最高优先级(PRI,NI) 等等,而类似的集群调度, k8s 可能是最常见的了,但是 Jenkins 对于任务调度这块,实际来讲,确实很弱, 虽然 调度 也是 Jenkins 的核心能力之一
k8s 里面有 node节点 概念, Jenkins 也有
k8s 里面有 pod 概念, Jenkins 没有,类似的, Jenkins 是限制 node 的最大并行个数
k8s 里面有调度器, 进行 Predicates 和 Priorities 两个过程, Jenkins 算法很简单,默认就是调度到 最近一次成功节点 上。
这样会带来一个比较严重的问题,会导致 部分机器处于极度打满,部分机器确空转,资源利用率严重两级分化 。
针对这点,我们其实有两种小的补救。
一种是降低node节点并行数量,比如原来是最大限制是10,下降到2后,第三个任务,比如调度另一个节点了,缺点就是可能造成更多排队情况
一种就是利用插件了,比如插件 throttle-concurrents 会比较均匀分配 https://plugins.jenkins.io/throttle-concurrents
总体而言,调度这块,Jenkins确实有很长路走
微服务 相比 单体应用 似乎高大上了很多,我们把服务抽象出来,只专注于某一部分,然后各个部分串联起来。
Jenkins 里面,一次构建,我们可能会写一个长长的脚本,举例子来说,我们需要构建一个移动端产物apk/ipa, 我们需要
clone code -> 更新依赖库 -> 编译 -> 产物保存 -> 分发到商店
传统上,我们可以把这一串代码都写到 job 配置里面,但更好的做法,我们是把每一步抽象出来,每一步都是一个服务(一个job)
怎么串联起来呢? 没有流水线之前,是 Jenkins 上下游任务关联 , 哈哈,当任务量多了,我们发现,调用链很难捋清楚了,当然微服务里面有自己的解决办法 - 链路追踪,网关
流水线 ,可以帮我们把这些串联起来,我们最后需要管理的只是流水线
小思考,不足之处,欢迎交流
Android Hook Dexposed原理小析
dexposed是阿里巴巴在xposed框架上面开发的hotpatch一套框架
当然hotpatch的方式有很多,这里先介绍下dexposed原理
Demo中有个test函数, 在调用hook之前正常返回”11111”; 调用hook之后, 却返回”newTestMethod”, 被我们给修改
了
public class Demo
{
String TAG = "===[hookdemo]===";
public static String staticTest(String param1)
{
return "staticTest";
}
public String test(String param1)
{
return "11111";
}
public void demo()
{
String param1 = "param1";
Log.d(TAG, "===========before hook test:" + this.test(param1));
hook(Demo1.class, "test", "(Ljava/lang/String;)Ljava/lang/String;");
Log.d(TAG, "===========after hook test:" + this.test(param1));
Log.d(TAG, "===========before hook staticTest:" + this.staticTest(param1));
hook(Demo1.class, "staticTest", "(Ljava/lang/String;)Ljava/lang/String;");
Log.d(TAG, "===========after hook staticTest:" + this.staticTest(param1));
}
private native void hook(Class<?> clazzToHook, String methodName, String methodSig);
}
ndk 中的部分
#include <jni.h>
#include "log.h"
#include "Dalvik.h"
static void showMethodInfo(const Method* method)
{
//看看method的各个属性都是啥:
LOGD("accessFlags:%d",method->accessFlags);
LOGD("clazz->descriptor:%s",method->clazz->descriptor);
LOGD("clazz->sourceFile:%s",method->clazz->sourceFile);
LOGD("methodIndex:%d",method->methodIndex);
LOGD("name:%s",method->name);
LOGD("shorty:%s",method->shorty);
}
/**
* 使用jni GetMethodID 方法获取jmethodID 强制转为 Method 的hook 方法 示例
*/
static void newTestMethod(const u4* args, JValue* pResult,
const Method* method, struct Thread* self) {
// args 是原来函数的参数数组, 原来test函数只有一个String型参数
// 并且要注意, 如果是不是static函数, 下标0 是函数所在类的实例obj
// 在dvm中Object, jni 中的jobject 和 java 中的 Object类 都不是同一个东西
// String类对应StringObject
// 取出参数打印出来看看
StringObject* param1 = NULL;
if(dvmIsStaticMethod(method))
param1 = (StringObject*)args[0];
else
param1 = (StringObject*)args[1];
LOGD("param1:%s",dvmCreateCstrFromString(param1));
//JValue 是个union ,要返回int 就 pResult->i=1; 返回Object对象就 pResult->l = ojb;
// 但是, 在dvm中的Object, jni 中的jobject 和 java 中的 Object类 都不是同一个东西
// 所以, 我们这里使用dvm的函数来创建一个StringObject*
pResult->l = dvmCreateStringFromCstr("newTestMethod");
// 一般情况应该使用宏 : RETURN_XXX(result);
return;
}
extern "C" JNIEXPORT void JNICALL
Java_com_zhaoxiaodan_hookdemo_Demo1_hook(JNIEnv *env, jobject instance, jobject clazzToHook,
jstring methodName_, jstring methodSig_) {
const char *methodName = env->GetStringUTFChars(methodName_, 0);
const char *methodSig = env->GetStringUTFChars(methodSig_, 0);
jmethodID methodIDToHook = env->GetMethodID((jclass) clazzToHook,methodName,methodSig);
// 找不到有可能是个static
if(nullptr == methodIDToHook){
env->ExceptionClear();
methodIDToHook = env->GetStaticMethodID((jclass) clazzToHook,methodName,methodSig);
}