半日闲

因过竹院逢僧话,又得浮生半日闲

0%

一、前言

文章主要记录容器化环境下的gitlab-runner的安装和使用,即执行器采用docker。
由于在实战过程中,搜集的各方面的资料比较零散,所以对这些资料进行整理,并在过程中遇到的问题进行记录。

阅读全文 »

一、基础配置

节点 IP 端口 备注
sentinel1 127.0.0.1 26379 哨兵1
sentinel2 127.0.0.1 26380 哨兵2
sentinel3 127.0.0.1 26381 哨兵3
redis-master 127.0.0.1 6379 默认主redis
redis-slave1 127.0.0.1 6380 默认从redis1
redis-slave2 127.0.0.1 6381 默认从redis2
阅读全文 »

  • 一天内核发学习驾驶证明,3天受理,10天调节,15天缴费
  • 出国,服兵役 过期延审 不超过3年
  • 驾驶拼装机动车上路,处以200-2000罚款,并吊销驾驶证
  • 饮酒驾驶机动车: 暂扣6个月驾驶证,罚款1000-2000.再犯拘留10日,罚款1000-2000,吊销驾照。醉酒驾驶机动车,吊销驾照,追究刑事责任,5年不得重新获取驾照
  • 饮酒驾驶运营机动车: 出15日拘留,罚款5000,吊销驾照,5年不得重新获取驾照。醉酒驾驶运营机动车,吊销驾照,10年不得重新获取驾照。饮酒后或者追究驾驶机动车,造成重大交通事故,终生不得获取驾照。

  • 《机动车驾驶证申领和使用规定》–身体条件证明相关

    办理残疾人专用小型自动挡载客汽车驾驶证业务时,提交的身体条件证明应当由经省级卫生健康行政部门认定的专门医疗机构出具。
    办理其他机动车驾驶证业务时,提交的身体条件证明应当由县级、部队团级以上医疗机构,或者经地市级以上卫生健康行政部门认定的具有健康资质的二级以上医院、乡镇卫生院、社区卫生服务中心、健康体检中心等医疗机构出具。
    身体条件证明自出具起六个月有效。
    公安机关交通管理部门应当会同健康行政部门在办公场所和互联网公示辖区内可以出具有关身体条件证明的医疗机构名称、地址以及联系方式

  • 《机动车驾驶证申领与使用规定》–科目二

    大型客车、重型牵引挂车、城市公交车、中型客车、大型货车: 桩考、坡道定点停车和起步、侧方位停车、通过单边桥、曲线行驶、直角转弯、通过限宽门、窄路掉头。以及模拟高速公路、连续急弯山区路、隧道、雨雾天、湿滑路、紧急情况处理。
    小型汽车、低俗载货汽车: 倒车入库、坡道定点停车和起步、侧方位停车、曲线行驶、直角转弯
    小型自动挡骑车、残疾人专用小型自动挡载客汽车:倒车入库、侧方位停车、曲线行驶、直角转弯
    轻型牵引挂车: 曲线行驶、直角转弯
    三轮骑车、普通三轮摩托、普通二轮摩托、轻便摩托车: 桩考、坡道定点停车和起步、通过单边桥
    轮式专用机械车、无轨电车、有轨电车:由省级公安机关交通管理部门确定
    以上第一款第一项和第三项规定的准驾车型,省级公安机关交通管理部门可以根据实际增加考试内容

  • 已知准驾车型更改

    科目一(道路交通安全法律、法规和相关考试科目)、科目二(场地驾驶技能考试科目)、科目三(道路驾驶技能和安全文明驾驶尝试考试科目)。
    小型自动挡骑车准驾车型驾驶证申请小型骑车准驾车型的: 考试科目二、科目三
    大型客车、城市公交车、中型客车、大型货车、小型汽车、小型自动挡汽车准驾车型申请增加轻型牵引挂车准驾车型的,科目二和科目三文明驾驶常识
    轻便摩托->普通三轮摩托、普通二轮摩托。普通二轮摩托->普通三轮摩托,考试科目2和科目3
    一般车型车主身体条件发生变化,不符合所持机动车准驾车型条件,但符合残疾人条件的,应当考试科目2和科目3

  • 《机动车驾驶证申领和使用规定》–申请准驾车型条件

    本记分周期和申请前最近一个记分周期没有记满12分,申请牵引挂车车型,C1和C2需要具备1年准驾车型资格

  • 《机动车驾驶证申领和使用规定》–机动车驾驶证申请条件

    1. 有器质性新增病、癫痫病、美尼尔氏症、眩晕症、癔病、震颤麻痹、精神病、痴呆以及影响肢体活动的神经系统疾病等妨碍驾驶疾病的
    2. 三年内有吸毒或者解除强制隔离戒毒措施未满三年,以及长期服用依赖型精神药品成瘾尚未解除的。
    3. 造成交通事故逃逸构成犯罪的
    4. 饮酒或者醉酒驾车引起重大交通事故构成犯罪的
    5. 酒驾或者醉驾运营机动车依法被吊销驾驶证未满5年的
    6. 醉驾营运客车依法被吊销驾照未满10年的
    7. 追逐、超员、超速、运输违禁药品和化学药品依法被吊销驾照未满5年的
    8. 醉驾或者酒驾以外的违反其他交通规则发生交通事故被吊销驾照未满10年的
    9. 其他情形驾驶许可被撤销未满2年的。
    10. 驾驶许可被撤销未满3年的。
    11. 未得驾照,发生交通事故致人重伤或者死亡未满10年的。
    12. 三年内替代他人参加机动车驾驶人考试行为的。
    13. 法律、行政法规规定的其他情形。
  • 《机动车驾驶证申领和使用规定》c6: 一般20-60,60-70需要判断记忆力、判断力和反应力


阅读全文 »

城市速度机动车在道路上行驶不得超过限速标志、标线标明的速度。在没有限速标志、标线的道路上,机动车不得超过下列最高行驶速度:

  • 没有道路中心线的道路,城市道路为每小时30公里,公路为每小时40公里。
  • 同方向只有1条机动车道的道路,城市道路为每小时50公里,公路为每小时70公里。
  • 高速公路速度(- -)2条道路的右边是60-100km/时,最低是60km/时,左边是最低100km/时,3条道路的最右边是60-90km/时,中间是90~110km/时;最左边是最低110km/时。
阅读全文 »

框架版本

dubbo 3.0.5
3.0版本中,在原有的ExtensionLoader之上,设计了ExtensionDirector类,用于构建类似ClassLoader一样的父子级管理器。
至此,所有Dubbo接口扩展点将使用ExtensionDirector类的getExtensionLoader(Class type)方法来获取,用于替代ExtensionLoader.getExtensionLoader(Class type)(该接口目前还存在,但标记为过时调用,未来可能遗弃)。

阅读全文 »

逻辑解析

  1. 根据名称来获取扩展名, 先从缓存实例中去查找,如果查找,则进行下一步,否则,在从缓存类中去查找并实例化,如果缓存中不存在,则抛出异常。
  2. 如果wrap为true,则查找包装类,从cachedWrapperClasses中加载,并进行排序,然后判定类是否被@Wrapper注解修饰(貌似没用), 然后通过顺序将实例注入到包装类中,并返回。

    相关代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    public T getDefaultExtension() {
    getExtensionClasses();
    if (StringUtils.isBlank(cachedDefaultName) || "true".equals(cachedDefaultName)) {
    return null;
    }
    return getExtension(cachedDefaultName);
    }
    public T getExtension(String name) {
    return getExtension(name, true);
    }
    public T getExtension(String name, boolean wrap) {
    if (StringUtils.isEmpty(name)) {
    throw new IllegalArgumentException("Extension name == null");
    }
    if ("true".equals(name)) {
    return getDefaultExtension();
    }
    final Holder<Object> holder = getOrCreateHolder(name);
    Object instance = holder.get();
    if (instance == null) {
    synchronized (holder) {
    instance = holder.get();
    if (instance == null) {
    instance = createExtension(name, wrap);
    holder.set(instance);
    }
    }
    }
    return (T) instance;
    }
    private T createExtension(String name, boolean wrap) {
    Class<?> clazz = getExtensionClasses().get(name);
    if (clazz == null || unacceptableExceptions.contains(name)) {
    throw findException(name);
    }
    try {
    T instance = (T) EXTENSION_INSTANCES.get(clazz);
    if (instance == null) {
    EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
    instance = (T) EXTENSION_INSTANCES.get(clazz);
    }
    injectExtension(instance);
    if (wrap) {
    List<Class<?>> wrapperClassesList = new ArrayList<>();
    if (cachedWrapperClasses != null) {
    wrapperClassesList.addAll(cachedWrapperClasses);
    wrapperClassesList.sort(WrapperComparator.COMPARATOR);
    Collections.reverse(wrapperClassesList);
    }
    if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
    for (Class<?> wrapperClass : wrapperClassesList) {
    Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
    if (wrapper == null
    || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
    }
    }
    }
    }
    initExtension(instance);
    return instance;
    } catch (Throwable t) {
    throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
    type + ") couldn't be instantiated: " + t.getMessage(), t);
    }
    }
阅读全文 »

逻辑解析

  1. 根据类加载策略来进行SPI扩展点配置文件的存放位置查找。
  2. 将类全路径报名作为文件名称对配置文件进行检索,得到若干个文件路径。
  3. 解析配置文件中的name和实现类全路径键值对,从虚拟机中加载该类。
  4. 加载类过程中,如果该实现类是否被@Adaptive修饰,则表示该实现类是SPI接口的静态适配类,用作getAdaptiveExtension返回。如果该实现类是包装类(通过判断构造方法是否有自身SPI接口注入), 如果存在,则添加到cachedWrapperClasses变量中。第三种情况则在分为两步操作,先判定改实现类是否被@Activate注解修饰,如果是,则将信息保存到cachedActivates变量中,如果不是,则在查找是否被alibaba包下面的@Activate注解修饰,如果是,则在保存到cachedActivates中,如果不是,跳过。第二步在进行名称缓存,并进行实现类信息保存到Map<String, Class<?>>并返回,最终保存到cachedClasses变量中。

    相关代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    private Map<String, Class<?>> loadExtensionClasses() {
    cacheDefaultExtensionName();
    Map<String, Class<?>> extensionClasses = new HashMap<>();
    for (LoadingStrategy strategy : strategies) {
    loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(),
    strategy.overridden(), strategy.excludedPackages());
    loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"),
    strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
    }
    return extensionClasses;
    }
    private void cacheDefaultExtensionName() {
    final SPI defaultAnnotation = type.getAnnotation(SPI.class);
    if (defaultAnnotation == null) {
    return;
    }
    String value = defaultAnnotation.value();
    if ((value = value.trim()).length() > 0) {
    String[] names = NAME_SEPARATOR.split(value);
    if (names.length > 1) {
    throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
    + ": " + Arrays.toString(names));
    }
    if (names.length == 1) {
    cachedDefaultName = names[0];
    }
    }
    }
    private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
    boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
    String fileName = dir + type;
    try {
    Enumeration<java.net.URL> urls = null;
    ClassLoader classLoader = findClassLoader();
    // try to load from ExtensionLoader's ClassLoader first
    if (extensionLoaderClassLoaderFirst) {
    ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
    if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
    urls = extensionLoaderClassLoader.getResources(fileName);
    }
    }
    if (urls == null || !urls.hasMoreElements()) {
    if (classLoader != null) {
    urls = classLoader.getResources(fileName);
    } else {
    urls = ClassLoader.getSystemResources(fileName);
    }
    }
    if (urls != null) {
    while (urls.hasMoreElements()) {
    java.net.URL resourceURL = urls.nextElement();
    loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages);
    }
    }
    } catch (Throwable t) {
    logger.error("Exception occurred when loading extension class (interface: " +
    type + ", description file: " + fileName + ").", t);
    }
    }
    private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
    java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
    try {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
    String line;
    String clazz = null;
    while ((line = reader.readLine()) != null) {
    final int ci = line.indexOf('#');
    if (ci >= 0) {
    line = line.substring(0, ci);
    }
    line = line.trim();
    if (line.length() > 0) {
    try {
    String name = null;
    int i = line.indexOf('=');
    if (i > 0) {
    name = line.substring(0, i).trim();
    clazz = line.substring(i + 1).trim();
    } else {
    clazz = line;
    }
    if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)) {
    loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden);
    }
    } catch (Throwable t) {
    IllegalStateException e = new IllegalStateException(
    "Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL +
    ", cause: " + t.getMessage(), t);
    exceptions.put(line, e);
    }
    }
    }
    }
    } catch (Throwable t) {
    logger.error("Exception occurred when loading extension class (interface: " +
    type + ", class file: " + resourceURL + ") in " + resourceURL, t);
    }
    }
    private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,
    boolean overridden) throws NoSuchMethodException {
    if (!type.isAssignableFrom(clazz)) {
    throw new IllegalStateException("Error occurred when loading extension class (interface: " +
    type + ", class line: " + clazz.getName() + "), class "
    + clazz.getName() + " is not subtype of interface.");
    }
    if (clazz.isAnnotationPresent(Adaptive.class)) {
    cacheAdaptiveClass(clazz, overridden);
    } else if (isWrapperClass(clazz)) {
    cacheWrapperClass(clazz);
    } else {
    clazz.getConstructor();
    if (StringUtils.isEmpty(name)) {
    name = findAnnotationName(clazz);
    if (name.length() == 0) {
    throw new IllegalStateException(
    "No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
    }
    }
    String[] names = NAME_SEPARATOR.split(name);
    if (ArrayUtils.isNotEmpty(names)) {
    cacheActivateClass(clazz, names[0]);
    for (String n : names) {
    cacheName(clazz, n);
    saveInExtensionClass(extensionClasses, clazz, n, overridden);
    }
    }
    }
    }
阅读全文 »