hexo配置https
Hexo配置Https之前折腾过WordPress,想弄个SSL玩玩,所以就去申请了免费的证书,一顿操作也就搞定了,现在觉得Hexo也不错,所以就换到了Hexo上,也打算把SSL弄过来。 网上有人说去修改~/your_hexo/node_modules/hexo-server/lib/server.js ,引入express ,然后就修改默认的端口为443就可以,别说,还真的可以,但是也出现了一些其他的问题,比如hexo有些命令无法执行,报错:80端口被占用。 我对前端的内容不是很了解,也就不想再去调试源码了,但是换个思路一想,其实只需要一个nginx转发一下就可以满足我的需求了,所以,那就动手把。 安装nginx我目前的系统是Ubuntu 16.04,直接安装nginx,执行如下命令: 1apt install nginx 上传证书安装完毕之后,上传我们申请到的证书 12cd /etc/nginxmkdir ssl 之后将证书上传到新建的ssl文件夹下。 配置SSL并新增转发规则新建nginx配置文件,监听80和443端口,另外将80端口的访问转发到443端口来 12cd /...
Iterm2 proxy
Iterm2 设置代理Mac用户大多对Iterm2都不陌生,颜值不错,用起来也顺手,但是大家肯定也都遇到过这样的场景: 更新的时候,被墙了 无法使用Git命令从Github上clone代码 我自己搭了个梯子,从Chrome上访问Github是没有问题,如何能够让Iterm2中的Git命令也可以访问外网呢?如果Iterm2支持代理就好了,直接把配个代理服务器,但是Iterm2本身并不支持代理设置 我本地安装了Shadowsocks,打开『偏好设置』可以看到socks5和http代理分别监听了1086和1080端口,如果把Iterm2中的请求转发到这些端口上,是不是就可以满足我们想要的功能呢? 为了验证代理是否成功,先测试一下IP地址,在Iterm中输入: 1curl ip.sb 此时返回的是目前机器的IP地址,可以去搜索一下IP所在地。 接下来打开Shadowsocks,在Iterm中输入如下内容: 12345alias proxy_http='export http_proxy=http://127.0.0.1:1080;export https_proxy=...
数据库事物和MQ一致性问题
最近生产环境出现了一些NPE问题(微服务架构),上游保存了数据库之后,发送MQ消息通知下游,下游服务查询不到上游保存的数据,从而导致了NPE问题。 架构图大致如下: 怀疑一:数据库主从同步延时可以确定的是数据库是多实例的,如果下游服务在当时读取不到数据,很有可能是数据库主从同步延时,下游服务去从库查询的时候,主库的数据还没有同步到从库,这样就出现了NPE问题。处理这样的问题也简单,让下游读方法强制去读主库就可以了。 按照这个思路调整了代码之后,再次部署到生产环境,第二天没有出问题,但是第三天同样的问题又出现了,也就是说,并不是数据库主从同步延时引起的NPE问题(或者说引起NPE问题的不仅仅是数据库主从同步延时)。为了缩小问题的范围,我去找DBA了解生产环境的数据库架构,得到的答案是:我们生产环境的确有两个实例,但是读写都是一个实例上,另一个实例仅仅作为灾备使用。 怀疑二:下游服务MQ消费过快上游服务的伪代码如下: 123456@Transactional(rollbackFor = Exception.class)public void process{XXXDAO....
SpringBoot中线程池使用
最近接手的项目遇到一个这样的问题:我们服务的一个接口需要循环查询另一个服务的接口,这样如果数据量较多的时候,我们服务的接口响应时间可能就会超时,伪代码如下: 12345678List<String> listOfResult = new ArrayList<>();listOfData.stream().forEach(t -> {// 调用其他微服务查询数据String result = queryOtherServer(t);if (null != result){listOfResult.add(result);}}); 这里先不讨论为什么不能让对方服务提供一个批量查询接口,然后通过一次调用获取数据结果,历史原因就是这样,短期只能我们系统先优化。 好吧,头疼医头吧。 这里如果要提高性能,最直接的办法就是并发查询,然后汇总查询结果。 优化步骤: 在项目中增加线程池配置,如下: 12345678910111213141516171819202122232425262728293031/** * @des...
一文带你读懂AQS
在JAVA中大多数的同步类(比如ReentrantLock、CountDownLatch、Semaphore等)都是基于AbstractQueuedSynchronier(简称AQS)来实现的。AQS是一个提供了原子式的管理状态同步、线程阻塞以及线程唤醒的简单框架,他内部使用了模板方法模式,这就使得其他的同步类都可以有自己的实现(ReentrantLock、CountDownLatch等都是通过变相继承AQS来实现同步功能的,注意看源码的Sync的实现)。 AQS可以做什么借助于AQS,我们可以实现哪些功能呢? 比如我们可以自己写一个排他锁,可以自己实现公平锁和非公平锁,比如可以自己写一个共享读锁等等。 为什么AQS可以完成这些功能呢?它内部是如何实现的呢? 要回答上面的问题,我们需要了解AQS内部的几个重要的属性以及他们的数据存储结构。 在AQS内部,有三个特别重要的属性: state 源码如下(为了减少篇幅,删减了注释部分): 123456789101112/** * The synchronization state. */private volatile int s...
模板方法
功能描述封装了算法的骨架,让子类去做算法的实现。和建造者模式很像。 代码结构UML类图 代码示例假设需要做一份黄金蛋炒饭,鸡蛋和米饭怎么获取,这个由各个厨师自己决定,为了能够做出黄金蛋炒饭,厨师长控制了炒饭的制作步骤… 厨师长定义的做黄金蛋炒饭的步骤 123456789101112131415161718192021222324252627public abstract class FriedRice { abstract void getEgg(); abstract void getRice(); final void doFriedRice(){ System.out.println("准备制作黄金炒饭:先炒米饭,然后倒入鸡蛋液!"); this.getRice(); System.out.println("米饭下锅翻炒..."); this.getEgg(); System.out.println("将鸡蛋液倒入...
JAVA类的加载机制
把类的描述文件从class文件中加载到内存,并且完成数据的校验、转化解析和初始化,最终形成虚拟机可以直接使用的JAVA类型的过程叫类的加载。 一个类从加载到虚拟机内存中开始再到从内存中卸载为止,它一共会经历以下7个阶段:加载、验证、准备、解析、初始化、使用、卸载。其中『验证、准备、解析』三个部分统称为『连接』。 类加载时机《JAVA虚拟机规范》中并没有严格规定类的『加载』阶段何时开始(这点可以由虚拟机自己决定),但是严格规定了有且只有以下六种情况的时候,必须对类完成初始化(当然,加载、验证、准备需要在初始化前完成)。 遇到new、getstatic、putstatic或invokestatic这四条字节码指令时,如果发现类没有完成初始化,则需要首先触发其初始化阶段。下面几种情况会使用到上面四条字节码指令: 使用new关键字实例化对象的时候 读取或设置一个对象的静态字段的时候。(被final修饰的,已经在编译期被放入静态常量池的除外) 调用一个类的静态方法的时候 使用java.lang.reflect包的方法对类进行反射调用的时候,如果发现类没有进行初始化,则需要首先触...
JVM垃圾回收
分代收集理论现在大多数的垃圾回收都是基于分代理论设计的,不同厂商对于内存的操作细节都不太一样,所以这里不讨论具体垃圾回收算法的细节,只是介绍垃圾回收算法的一些思想。 分代收集虽然是一套理论,但是却是符合大多数程序运行的经验法则,它建立在以下两个假说之上: 弱分代假说绝大多数对象都是朝生夕灭的 强分代假说熬过了多次垃圾回收的对象,一般更难以消亡。 垃圾回收分类分代收集理论将内存(JAVA堆)分为了若干个区域,这样垃圾回收的时候就可以针对不同的区域进行回收,依据回收区域的不同,JAVA垃圾回收可以分为:Minor GC(Young GC)、Major GC(Old GC)和Full GC三种。由于不同区域存储对象的生存和消亡特征的不同,他们所使用的垃圾回收算法也不同,按垃圾回收算法划分,又可以分为以下几类:标记-删除算法、标记-复制算法、标记-整理算法。 按算法划分 标记-删除算法标记-删除算法是最基础的收集算法,他主要分为两个步骤:标记哪些活着的对象然后删除不用的对象(也可以反着来)。标记-删除算法有两个很明显的缺点,一个是随着标记对象的增多,效率会越来越低,第二个就是删除对象...
Java内存模型
本文是在《深入理解JAVA虚拟机》第三版的基础上整理出来的,强烈建议大家都去看看! 运行时数据区JAVA虚拟机在运行JAVA程序的过程中会把内存分成若干个数据区,这些数据区有各自不同的用途以及创建和销毁时机,有的区域伴随着JAVA虚拟机的进程启动而一直存在,有的区域则依赖用户的线程启动(创建)和停止(销毁),依据《JAVA虚拟机规范》的规定,JAVA虚拟机所管理的内存包括以下几个运行时数据区。 程序计数器程序计数器是一块比较小的内存空间,它可以看做是每个线程执行字节码指令的行号指示器。字节码解释器工作的时候,就是通过改变这个指示器的行号来选取下一条字节码指令的。线程的分支、循环、跳转、异常处理、线程恢复等功能都是依赖这个计数器来完成的。 如果虚拟机正在执行一个JAVA方法,那么计数器记录的就是JAVA虚拟机字节码指令的地址;如果执行的是本地方法(native),那么这里记录的内容就为空(undefined)。需要说明的是,这里是唯一不会抛出OutOfMemoryError的地方。 虚拟机栈和程序计数器一样,虚拟机栈也是线程私有的,它的生命周期和线程有一样。虚拟机栈描述的是执行J...
Docker MySQL单机安装
操作系统:Ubuntu 16.04 x64 docker版本:18.09.7 docker-compose版本:1.8.0 说明: 本次实验,docker和docker-compose均使用apt安装。 确定当前用户已经加入到docker组如果没有,执行如下命令sudo gpasswd -a ${USER} docker,然后退出当前用户重新登录。 开始安装在服务器适当位置新建mysql文件夹 1mkdir -p ~/docker/mysql 进入该文件夹,创建数据存放目录、备份目录、配置目录,然后编写docker-compose.yml文件。 123cd ~/docker/mysqlmdkir db backup confvi docker-compose.yml 由于我在开发环境常用的MySQL配置基本一样,所以特地将conf中的配置文件打包保存起来了,如果需要可以点击下载。下载到~/docker/mysql目录下,直接覆盖刚刚新建的conf目录即可。 文件内容如下: 1234567891011121314151617181920212223version: ...







