简栈

拥抱AI,持续成长

http://static.cyblogs.com/macispopular.jpg

Mac 在国外很受欢迎,尤其是在 设计/web开发/IT 人员圈子里。普通用户喜欢 Mac 可以理解,毕竟 Mac 设计美观,简单好用,没有病毒。那么为什么专业人士也对 Mac 情有独钟呢?从个人使用经验来看我想有下面几个原因:

1、Mac OS X 是基于 Unix 的。这一点太重要了,尤其是对开发人员,至少对于我来说很重要,这意味着Unix 下一堆好用的工具都可以随手捡到。如果你是个 windows 开发人员,我想你会在 windows 上装一套cygwin 环境吧?你不用 flex/yacc,grep,screen,ssh,make?好多 open source 的项目只提供cygwin/gcc/make 的编译环境。Mac 就是基于 BSD Unix 的,所有这些都是 built in 的。

2、开发环境。c/c++/java/perl/python/php/ruby/lisp,各种 shell,应有尽有,直接支持,非常方便。你要在 windows 上开发 C++,要装个 Visual Studio 编译器吧?或者其他的 C++ 编译器;你要开发 Java,你要下载 Java SDK 吧,说不定还要一个 Elipse 或者 Netbean;你要用 Perl,要安装一个 Perl 解释器吧,Active Perl?你要 python/php/ruby,你要安装……?开发程序需要库,图像处理,视频处理,人工智能之类大部分库都是只支持 Unix/Linux 的。Mac 基于 Unix,所以这些通通都和 Mac 能很好和睦相处。

3、编辑器 Vi/Emac。作为 程序员/IT 人员一个好用的编辑器太重要了,因为写程序/改系统配置都需要编辑器。我在 Mac 上差不多1/2的时间是 browser/email,另外1/2时间差不多就是 Vi 了。

4、没有病毒/木马。用了5年多的 Mac 就没看到病毒长成什么样,我还看不到 Mac 上装杀毒软件的需要。

5、不需要维护。Mac 买来就直接用,磁盘碎片整理?不需要。装驱动?Mac 装好了,驱动就好了。重装系统?我5年没有重装过一次(期间换了几次不同的 Mac)。

6、简洁。Mac 上所有的操作都简洁到了极致,尽量避免干扰用户,增加了程序员的生产力。比如切换无线网功能,在 Mac 上切换只需要1次鼠标点击就可以完成,在 windows 上需要点击多次鼠标(包括一些很愚蠢的确认对话框);再比如卸载 USB 盘,Mac 只需要1次鼠标点击,windows 至少需要点击右下角图标、停止设备、确认对话框等多次点击。

7、多窗口切换。这个很方便管理打开的程序/文档。我经常要在多个虚拟窗口切换,比如看浏览网页/邮件一个窗口,写程序/文档一个窗口。

8、程序员文化。国外程序员是以 Unix 为主流成长起来的。这一点和国内不同,中国程序员/开发人员大都是从90年代的 DOS 开始的,随着 Windows 的壮大,成长了一批使用 Microsoft 工具的程序员。这也解释了为什么自从 Mac 切换到 Unix 阵营后,Mac 会发展这么快。基于 Unix 的 Mac 一经推出后,迅速赢得了一大批老 Unix hacker 和新 Web 2.0/Linux hacker 的关注,正是因为这些忠实的 fans 影响了他们的人际网络,圈子,博客,从而影响了整个程序员文化。有点像 Ruby on Rails,开始是一小部分人(精英人士)试用,这些人感觉不错就在博客,研讨会等各种场合鼓吹,从而在 Web 开发领域刮起一阵 Ruby 风。

阅读全文 »

背景

迁移了一年,这话真的丝毫没有夸张~

1、从2018年底开始从阿里的HSF迁移到SpringCloud,全面拥抱Spring开源框架;

2、然后就是项目组上海、北京、深圳的项目交接,全部由深圳这边来做业务;

3、后面就是全平台的迁移与整合,包括代码、中间件、数据库、网络等;

4、包括中途发布系统迁移了3~4次,网络从阿里云的经典网络迁移到阿里云的VPC网络;

做这一切都是为了(降本增效):提高我们的对接效率,节约我们的成本,对接的人员更加的专业与熟练。我个人觉得做这些还是挺有意义的,只是要尽快的结束掉。

项目如何迁移?

如何建设一个标准统一平台?
配置中心
阅读全文 »

lambda表达式实战

从例子引出lambda

传递Runnable创建Thread

  • java8之前
1
2
3
4
5
6
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
// do something
}
});
  • java 8 之后
1
new Thread(()->{});

上边的例子比较简单,但是有两个疑问。什么是Lambda表达式?怎么使用lambda表达式?

什么是Lambda表达式?

从上述例子入手,首先我们知道Lambda一般代表的是一个匿名对象;其次我们点击“->”,IDE会帮助我们进入到符合Lambda规范的函数接口。我们来观察下这个符合规范的类的变化。

阅读全文 »

Nginx 是优秀的 HTTP 和反向代理服务器,京东各部门都在广泛使用,但普遍都面临着一些问题:

  1. 配置复杂,专业性强。
  2. 配置文件无法批量修改且配置变更依赖重启操作。
  3. 不同应用依赖不同模块、配置项,管理混乱。
  4. 同一应用的 Nginx 无法批量、快速扩容。

所有问题的根源在于 Nginx 是一个单机系统,虽然模块化、高性能,但在互联网高速发展的今天,像京东这样拥有大规模 Nginx、业务集群的场景下,所有问题都有可能被无限放大,针对这种现状我们设计研发了 JEN(JD EXTENDED NGINX),截止目前 JEN 已覆盖京东金融大部分核心业务,如夺宝吧,卡超市,白条等。

一、整体结构

京东Nginx平台化实践

图 1:JEN 结构图

如上图,运维通过 Web 控制台做相应的配置操作,若是分流、限流等配置,则信息入库等待 Nginx 通过 Restful API 同步规则后开始生效;若是平滑升级、重启等强运维性操作,则 Web 控制台通过控制 Ansible 对 Nginx 进行相应操作。

京东Nginx平台化实践

图 2:Nginx 和 Web 控制台多机房部署图

JEN 特点:

阅读全文 »

不仅简化了 Dubbo 基于 xml 配置的方式,也提高了日常开发效率,甚至提升了工作幸福感。

为了节省亲爱的读者您的时间,请根据以下2点提示来阅读本文,以提高您的阅读收获效率哦。

  • 如果您只有简单的 Java 基础和 Maven 经验,而不熟悉 Dubbo,本文档将帮助您从零开始使用 Spring Boot 开发 Dubbo 服务,并使用 EDAS 服务注册中心实现服务注册与发现。
  • 如果您熟悉 Dubbo,可以选择性地阅读相关章节。

为什么使用 Spring Boot 开发 Dubbo 应用

Spring Boot 使用极简的一些配置,就能快速搭建一个基于 Spring 的应用,提高的日常的开发效率。因此,如果您使用 Spring Boot 来开发基于 Dubbo 的应用,简化了 Bubbo 基于 xml 配置的方式,提高了日常开发效率,提升了工作幸福感。

为什么使用 EDAS 服务注册中心

EDAS 服务注册中心实现了 Dubbo 所提供的 SPI 标准的注册中心扩展,能够完整地支持 Dubbo 服务注册、路由规则配置规则功能

EDAS 服务注册中心能够完全代替 ZooKeeper 和 Redis,作为您 Dubbo 服务的注册中心。同时,与 ZooKeeper 和 Redis 相比,还具有以下优势:

  • EDAS 服务注册中心为共享组件,节省了您运维、部署 ZooKeeper 等组件的机器成本。
  • EDAS 服务注册中心在通信过程中增加了鉴权加密功能,为您的服务注册链路进行了安全加固。
  • EDAS 服务注册中心与 EDAS 其他组件紧密结合,为您提供一整套的微服务解决方案。

本地开发

阅读全文 »

环境与背景

Ext1:本文源码解析基于 mybatis-spring-boot-starter 2.1.1,即 mybatis 3.5.3 版本。

Ext2:本文主要是对源码的讲解,着重点会是在源码上。

Ext3:阅读本文前,最好对 mapperProxy、 sqlSession 有一定的了解

一、 XMLMapperBuilder、mapperProxy 与 mapperMethod

上篇文章 讲了 mapper 文件是怎么解析的,在文章开头提到了 SqlSessionFactory 这个重要的对象,是的就是我们经常需要配置的:

1
2
3
4
5
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
// 略
}

这里面做了很多自动化的配置,当然我们可以通过重写它来自定义我们自己的 sqlSessionFactory,借用一下上篇文章的图片: img

spring 借助 SqlSessionFactoryBean 来创建 sqlSessionFactory,这可以视作是一个典型的建造者模式,来创建 SqlSessionFactory

上篇文章说到,spring 拿到我们配置的 mapper 路径去扫描我们 mapper.xml 然后进行一个循环进行解析(上篇文章第二章节:二、SqlSessionFactory 的初始化与 XMLMapperBuilder):

阅读全文 »

背景

前不久《深入理解Java虚拟机》第三版发布了,赶紧买来看了看新版的内容,这本书更新了很多新版本虚拟机的内容,还对以前的部分内容进行了重构,还是值得去看的。本着复习和巩固的态度,我决定来编译一个简单的类文件来分析Java的字节码内容,来帮助理解和巩固Java字节码知识,希望也对阅读本文的你有所帮助。

说明:本次采用的环境是OpenJdk12

编译“1+1”代码

首先我们需要写个简单的小程序,1+1的程序,学习就要从最简单的1+1开始,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
package top.luozhou.test;

/**
* @description:
* @author: luozhou
* @create: 2019-12-25 21:28
**/
public class TestJava {
public static void main(String[] args) {
int a=1+1;
System.out.println(a);
}
}

写好java类文件后,首先执行命令javac TestJava.java 编译类文件,生成TestJava.class。 然后执行反编译命令javap -verbose TestJava,字节码结果显示如下:

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
  Compiled from "TestJava.java"
public class top.luozhou.test.TestJava
minor version: 0
major version: 56
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #5.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #17.#18 // java/io/PrintStream.println:(I)V
#4 = Class #19 // top/luozhou/test/TestJava
#5 = Class #20 // java/lang/Object
#6 = Utf8 <init>
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 main
#11 = Utf8 ([Ljava/lang/String;)V
#12 = Utf8 SourceFile
#13 = Utf8 TestJava.java
#14 = NameAndType #6:#7 // "<init>":()V
#15 = Class #21 // java/lang/System
#16 = NameAndType #22:#23 // out:Ljava/io/PrintStream;
#17 = Class #24 // java/io/PrintStream
#18 = NameAndType #25:#26 // println:(I)V
#19 = Utf8 top/luozhou/test/TestJava
#20 = Utf8 java/lang/Object
#21 = Utf8 java/lang/System
#22 = Utf8 out
#23 = Utf8 Ljava/io/PrintStream;
#24 = Utf8 java/io/PrintStream
#25 = Utf8 println
#26 = Utf8 (I)V
{
public top.luozhou.test.TestJava();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 8: 0

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_2
1: istore_1
2: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
5: iload_1
6: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
9: return
LineNumberTable:
line 10: 0
line 11: 2
line 12: 9
}

解析字节码

1.基础信息

阅读全文 »

获取镜像

在实际的投产中,公司一般所有企业的私有镜像:我们公司选择的是:https://goharbor.io/。

首先获取一个nginx的镜像,待会儿需要直接启动这个镜像

1
docker pull nginx

确认镜像已经在列表中:

1
2
3
[root@CentOS7-Node1 parallels]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 231d40e811cd 2 weeks ago 126MB

创建Pod

直接在master节点上运行一个镜像,并且启动2台机器。

1
2
3
4
5
6
7
[root@CentOS7-Node1 parallels]# kubectl run my-nginx --image=nginx --replicas=2 --port=80
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/my-nginx created
[root@CentOS7-Node1 parallels]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-75897978cd-87dnh 1/1 Running 0 4m36s
my-nginx-75897978cd-nwnrm 1/1 Running 0 4m36s

这里需要等待一定的时间,容器的状态由ContainerCreating变为Running

阅读全文 »

kube-apiserver默认配置

查看一下kube-apiserver的一些启动配置项,确认存放地址。

1
2
3
4
5
6
7
8
[root@CentOS7-Node1 manifests]# ll
total 16
-rw-------. 1 root root 1759 Dec 10 12:15 etcd.yaml
-rw-------. 1 root root 2602 Dec 10 12:15 kube-apiserver.yaml
-rw-------. 1 root root 2531 Dec 10 12:15 kube-controller-manager.yaml
-rw-------. 1 root root 1119 Dec 10 12:15 kube-scheduler.yaml
[root@CentOS7-Node1 manifests]# pwd
/etc/kubernetes/manifests

可以通过查看yaml文件的方式查看

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
[root@CentOS7-Node1 manifests]# cat kube-apiserver.yaml 
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=10.211.55.7
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt #指定CA根证书文件
- --enable-admission-plugins=NodeRestriction
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
- --etcd-servers=https://127.0.0.1:2379
- --insecure-port=0
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
- --requestheader-allowed-names=front-proxy-client
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
- --requestheader-extra-headers-prefix=X-Remote-Extra-
- --requestheader-group-headers=X-Remote-Group
- --requestheader-username-headers=X-Remote-User
- --secure-port=6443
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
- --service-cluster-ip-range=10.96.0.0/12
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt #指定ApiServer证书文件
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key #指定ApiServer私钥文件
image: k8s.gcr.io/kube-apiserver:v1.16.0
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 10.211.55.7
path: /healthz
port: 6443
scheme: HTTPS
initialDelaySeconds: 15
timeoutSeconds: 15
name: kube-apiserver
resources:
requests:
cpu: 250m
volumeMounts:
- mountPath: /etc/ssl/certs
name: ca-certs
readOnly: true
- mountPath: /etc/pki
name: etc-pki
readOnly: true
- mountPath: /etc/kubernetes/pki
name: k8s-certs
readOnly: true
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /etc/ssl/certs
type: DirectoryOrCreate
name: ca-certs
- hostPath:
path: /etc/pki
type: DirectoryOrCreate
name: etc-pki
- hostPath:
path: /etc/kubernetes/pki
type: DirectoryOrCreate
name: k8s-certs
status: {}

我们注意到有如下三个启动参数:

  • --client-ca-file: 指定CA根证书文件为/etc/kubernetes/pki/ca.pem,内置CA公钥用于验证某证书是否是CA签发的证书
  • --tls-private-key-file: 指定ApiServer私钥文件为/etc/kubernetes/pki/apiserver-key.pem
  • --tls-cert-file:指定ApiServer证书文件为/etc/kubernetes/pki/apiserver.pem
直接获取nodes节点

用默认的CA认证尝试一下从其他节点查看pods的信息,直接来获取master节点的pods信息。

1
2
[root@CentOS7-Node2 Workspace]# kubectl --server=https://10.211.55.7:6443 get nodes
Please enter Username: # 这里会提示需要输入用户名,但我们并不知道用户名是什么?
阅读全文 »

定义

**数据结构(Data Structure)**是带有结构特性的数据元素的集合,它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系,并对这种结构定义相适应的运算,设计出相应的算法,并确保经过这些运算以后所得到的新结构仍保持原来的结构类型。简而言之,数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结构。

分类:

  • 数组(英语:Array),是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)可以计算出该元素对应的存储地址。

  • (英语:stack)又称为堆叠,是计算机科学中的一种抽象数据类型,只允许在有序的线性数据集合的一端(称为堆栈顶端,英语:top)进行加入数据(英语:push)和移除数据(英语:pop)的运算。因而按照后进先出(LIFO, Last In First Out)的原理运作。

  • 队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。

  • 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。最常见的三种链表结构有:单链表、双向链表、循环链表。

  • (英语:tree)是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

    • 每个节点都只有有限个子节点或无子节点;
    • 没有父节点的节点称为根节点;
    • 每一个非根节点有且只有一个父节点;
    • 除了根节点外,每个子节点可以分为多个不相交的子树;
    • 树里面没有环路(cycle)
  • 散列表Hash table,也叫哈希表),是根据(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表

  • (英语:Heap)是计算机科学中的一种特别的树状数据结构。若是满足以下特性,即可称为堆:“给定堆中任意节点P和C,若P是C的母节点,那么P的值会小于等于(或大于等于)C的值”。若母节点的值恒小于等于子节点的值,此堆称为最小堆(min heap);反之,若母节点的值恒大于等于子节点的值,此堆称为最大堆(max heap)。在堆中最顶端的那一个节点,称作根节点(root node),根节点本身没有母节点(parent node)。

  • (Graph)是由顶点的有穷非空集合和顶点之间的边的集合组成,通常表示为:G(V,E)。其中,G 表示一个图,V是图G中顶点的集合,E是图G中边的集合。

    • 图中数据元素叫做顶点(Vertext)。

    • 在图中,不允许没有顶点。若 V 是图的顶点的集合,那么,V 是非空
      有穷集合。

    • 图的任意两个顶点之间都可能有关系,它们的关系用边来表示。边集可
      以是空的。

http://static.cyblogs.com/WX20191219-151801@2x.png

再了解树之前,我们对一些专业术语普及一下:度、阶、高度、深度、根、叶子、兄弟节点、关键字。

参考地址:

0%