陈志军

物来顺应,未来不迎,当时不杂,既过不恋


  • 首页

  • 分类

  • 归档

  • 标签

  • 搜索

Docker修改默认存储空间

发表于 2019-05-24 | 分类于 Docker | 阅读次数

Docker 修改默认存储空间

最近碰到一个问题,由于需要下载很多的镜像文件,如果使用docker安装时候的默认存储空间,那肯定是不行的。默认的存储空间可以使用:docker info看到:在输出的信息里面会发现:Docker Root Dir: /var/lib/docker;这个目录其实就是在根目录下吗,如果下载的镜像数量过大并且又大,那么肯定是的完蛋的~~~

所以就需要修改docker的存储空间。

阅读全文 »

SpringBoot 文件处理接口

发表于 2019-05-24 | 阅读次数

Spingboot 下载文件

下载文件

有时候会遇到一些需求,需要给前端提供下载文件的接口。

1
2
3
4
5
6
7
8
9
10
11
12
    @GetMapping("/export")
@ResponseBody
public ResponseEntity<Resource> export() {
HSSFWorkbook workbook = new HSSFWorkbook();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
workbook.write(outputStream);
Resource file = new ByteArrayResource(outputStream.toByteArray());
String filename="app.txt";
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename="+filename).body(file);
}
//
阅读全文 »

Etcd 集群搭建

发表于 2019-05-23 | 分类于 Etcd | 阅读次数

Etcd 集群安装

本文参考:https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/clustering.md

不得不说etcd的安装真的非常容易。在https://github.com/etcd-io/etcd的release里面找到相应的版本。然后直接二进制启动,一个单节点就好。真的是太简单啊。

不过搭建集群版本的话还是需要做一些配置,下面就是我用集群搭建的环境并且真实可用的过程。

下载好相应版本的etcd,然后做如下配置。我们采用的方式是使用Linux的systemd服务:

阅读全文 »

Docker Registry 磁盘空间清理

发表于 2019-05-09 | 分类于 Docker | 阅读次数

Docker Registry 磁盘空间清理

使用 Docker 的时候用的是 Docker Registry 来存储镜像。一开始的时候给了500G数据盘,日积月累的累积的数据就开始变多了。
没办法只好想办法去清理。看了下官网的api文档:Docker Registry API

其实还挺简单的,主要是用http接口先将镜像和层删除,然后使用镜像仓库的garbage-collect。

默认HTTP接口是不支持DELETE方法的,需要修改配置文件中storage.delete.enabled: true,配置文件的解释可以在这里看到地址Registry 配置文件

1
2
3
storage:
delete:
enabled: true

镜像仓库的garbage-collection可以看下官网文档。主要看懂一个图就可以了:

1
2
3
A -----> a <----- B
\--> b |
c <--/
1
2
3
A -----> a     B
\--> b
c

这样c就要回收了。

然后我们使用HTTP的API。查到repo,tags,然后就可以删除相应的镜像。

但是在删除的时候要注意下,首先我们要通过接口获取digest的值,但是这个digest的值获取方式比较特别,首先我们访问:/v2/<name>/manifests/<reference>这个接口的时候,需要使用GET获取HEAD方法,然而在请求的时候需要加入Header:Accept: application/vnd.docker.distribution.manifest.v2+json这样才可以在返回的HEAD中才能获取到正式的digest。

使用golang写了一个demo代码:

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

package main

import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"strings"
)

type Tag struct {
Name string `json:"name"`
Tags []string `json:"tags"`
}

type Repo struct {
Repositories []string `json:"repositories"`
}

//registry garbage-collect /etc/docker/registry/config.yml
//registry garbage-collect --dry-run /etc/docker/registry/config.yml > test.log
//cat test.log | awk -F : '{print $1}' | sort | uniq -c | sort -rn -k1 | head -10
func main() {
registryUrl := flag.String("url", "http://registry.xxxxx.com:5000", "registry url")
pattern := flag.String("pattern", "", "删除镜像名中有pattern的镜像")
flag.Parse()
fmt.Println("registry url:", *registryUrl, ",pattern:", *pattern)
resp, _ := http.Get(*registryUrl + "/v2/_catalog?n=10000")
bytes, _ := ioutil.ReadAll(resp.Body)
r := Repo{}
json.Unmarshal(bytes, &r)
for _, v := range r.Repositories {
if *pattern == "" || len(*pattern) <= 0 {
*pattern = "2017"
}
fmt.Println("pattern:", *pattern)
if strings.Contains(v, *pattern) {
url := fmt.Sprintf(*registryUrl+"/v2/%s/tags/list", v)
fmt.Println("url" + url)
resp, _ := http.Get(url)
bytes, _ := ioutil.ReadAll(resp.Body)

var t = Tag{}
fmt.Println("byteStr:", string(bytes))
json.Unmarshal(bytes, &t)
fmt.Println("tag:", t)
client := http.DefaultClient
if len(t.Tags) > 0 {
for _, ti := range t.Tags {
mainfests := *registryUrl + "/v2/%s/manifests/%s"
url = fmt.Sprintf(mainfests, t.Name, ti)
request, _ := http.NewRequest(http.MethodGet, url, nil)
request.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v2+json")
response, _ := client.Do(request)
digest := response.Header.Get("docker-content-digest")
fmt.Println("digest:", digest)
fmt.Println("headers:", response.Header)
deleteUrl := fmt.Sprintf(mainfests, t.Name, digest)

fmt.Println("deleteUrl:", deleteUrl)
request, _ = http.NewRequest(http.MethodDelete, deleteUrl, nil)
response, _ = client.Do(request)
headers := response.Header
fmt.Println(response.Status, headers)

}
}
}

}

}


就算这样执行完,别忘记了,进入到registry的容器中,然后使用:

1
2
3

registry garbage-collect /etc/docker/registry/config.yml

/etc/docker/registry/config.yml文件要打开之前说的storage.delete.enabled: true

修改 Linux Core 文件目录

发表于 2019-05-08 | 分类于 Linux | 阅读次数

Linux Core 文件

一次线上的经历,一台现在主机突然磁盘根目录占到98%。我们其实是挂了数据盘的,不知道为啥突然会
在根目录下磁盘空空间不足报警。上到主机一看,原来是某个应用打了dump了个core文件。文件如:core.xxxx

用gdb调试了一下:

gdb core.14321

显示出是哪个进程dump的core文件。

之后我们就开始分析core文件怎么避免让根目录占满。

首先用ulimit -a查看到core文件的大小。然后用ulimit -c设置大小,单位是block,
1block=512bytes

然后修改core文件到数据盘的目录:

echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern

Restful 接口返回响应码

发表于 2019-05-05 | 分类于 Java | 阅读次数

Restful 接口返回响应码

最近用restful做接口,突然想想返回状态码该怎么返回给客户端或者调用者。毕竟那么多的状态码。

后来找到一个状态码解释:

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

1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求

100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本

200——交易成功
201——提示知道新文件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204——请求收到,但返回信息为空
205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206——服务器已经完成了部分用户的GET请求

300——请求的资源可在多处得到
301——删除请求数据
302——在其他地址发现了请求数据
303——建议客户访问其他URL或访问方式
304——客户端已经执行了GET,但文件未变化
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307——申明请求的资源临时性删除

400——错误请求,如语法错误
401——请求授权失败
402——保留有效ChargeTo头响应
403——请求不允许
404——没有发现文件、查询或URl
405——用户在Request-Line字段定义的方法不允许
406——根据用户发送的Accept拖,请求资源不可访问
407——类似401,用户必须首先在代理服务器上得到授权
408——客户端没有在用户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且无进一步的参考地址
411——服务器拒绝用户定义的Content-Length属性请求
412——一个或多个请求头字段在当前请求中错误
413——请求的资源大于服务器允许的大小
414——请求的资源URL长于服务器允许的长度
415——请求资源不支持请求项目格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段
417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求

500——服务器产生内部错误
501——服务器不支持请求的函数
502——服务器暂时不可用,有时是为了防止发生系统过载
503——服务器过载或暂停维修
504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长
505——服务器不支持或拒绝支请求头中指定的HTTP版本

nginx从docker容器的环境变量中获取值

发表于 2019-04-08 | 阅读次数

nginx从docker容器的环境变量中获取值

这篇接上一篇vuejs 从拷项目到开发上线

Docker 部署

另外一个问题就是如何制作成镜像了?可以看到我们在nginx.conf中有api服务的地址,这个地址可能在不同的环境(di,sit,prd)都不一样,那能否通过容器的env来改变nginx.conf中的值呢?

不查不知道,一查发现,我擦,还真有,nginx镜像本身就已经具备了。不过是李template的方式,来生成conf文件话不多说,直接上代码,先创建一个nginx.conf.template的文件:

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

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /app/html;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location / {
}

location /m-web/ {
root /app/html/dist;
}
location /m-web/m-api/ {
proxy_pass http://${M_API_SITE}/m-api/;
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

之后准备Dockerfile:

1
2
3
4
5
6
7
8

FROM nginx:latest
RUN rm -rf /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/nginx.conf
ENV M_API_SITE 192.168.1.19:8089
ADD nginx.conf.template /etc/nginx/conf.d/nginx.conf.template
ADD dist /app/html/dist
CMD ["/bin/bash", "-c", "envsubst < /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/nginx.conf && exec nginx -g 'daemon off;'"]

之后docker build -t xxx:latest .,之后我们就可以通过-e M_API_SITE=192.168.123.1:8080设置容器的环境变量来设置不同的api地址了。

vuejs 从拷项目到开发上线

发表于 2019-04-08 | 分类于 vuejs | 阅读次数

vuejs 从拷项目到开发上线

最近组里缺人手,我们都是一堆后端,却没有一个前端。所以你看到了一堆的后台接口,但就是没有一个页面。囧~
本着求人不如求己,活人不能被尿憋死不是~所以准备自己开始干。

前端选型

首先想了一下,我们应该怎么开发前端了?使用thymeleaf这种貌似是最合适的,毕竟类似于以前用jsp,对不对~当然有点不一样。
但后来想想,都前后端分离了,以后我们要真的做牛逼了。要是给我们分配个前端,那我们不又要改死啊。
然后觉得前后端不分离,逼格不够,也不好维护。那好咯,那就定好方向前端分离。

前后端分离的方向定好,那就先想想是自己完全自己弄一个,还是直接用模板套一个?一致觉得,自己从头写,费时费力,一群后端去弄不太现实,毕竟还是有很多要调的,适配啊,排版啊。所以投票决定,选模板。选了模板,那就好弄了,github上找了前十个优秀的模板。有一些是基于bootstrap,然后每个页面都是html,所以这种就相当于用jQuery或者javascript用ajax这种吧。想想就被以前写dom支配的恐惧。后来了解到有个vue,人家都说好用,其实公司还有很多都是vue,我们想了想,要是用bootstrap那种估计就是靠我们自己了。要是vue,要是我们实际搞不定,在公司也好请外援。想了想,那就找vue的模板吧。找来找去,找了个最简单实用的。毕竟我们需求很简单,列表显示,表格添加,搜索框就好了,后管管理页面是真的好搞啊。找了个最简单的功能又全的,感谢github,感谢可爱的爱分享的工程师们。

vue 使用

模板选好了,这下来到重头戏了。大家都不会啊,以前都是听说,我们前端用vue,特么到底怎么用啊。不过既然选好了方案,选好了模板,其实就很明确了,不会那就学啊。vue官网一翻,一遍浏览。大概的使用方式也是了解了。

vue 数据绑定

vue的模式感觉跟以前的不一样,看整个项目发现其实就一个html页面,也就是index.html,然后就是在里面有个APP.vue,通过不同的xx.vue来选择相应的页面,其实就是他们口中的单页式应用。就是一个html页面,然后根据不同的path来显示不同的内容。另外需要转换一个观点,vue不像传统的面向页面来编程,因为它的数据绑定感觉太好用了。如果是在html标签中只需要用{{ key }}就可以使用在js中定义的key的值。有几个好用的标签:

感觉吧,说的不太全,还是要实际用起来才有那种感觉。模板地址

使用中遇到的问题

在实际使用中遇到一些问题,一开始有点懵逼,不过到后来都解决了。

本地开发-跨域问题

这个一开始的时候有点蒙圈,本地是使用npm run dev启动的,启动后发现,跨域了。这个该怎么搞哦。后来在vue.config.js中发现一个文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
baseUrl: './',
productionSourceMap: false,
devServer: {
proxy: {
'/m-paas':{
target: 'http://localhost:8080/m-paas',
changeOrigin: true,
pathRewrite:{
'/m-paas': ''
}
}
}
}
}

其实可以看到只要打开changeOrigin 就可以了。其它的都不需要改动。

部署

开发完了,代码也写好了。重点来了,怎么部署到服务器?来跟我三步走

  1. step1,构建应用

使用npm run build先进行构建,完成后会在根路径下生成一个dist文件夹。

  1. step2,准备nginx服务器

下载一个nginx,现在都是使用nginx来做前端的服务器。将刚刚的dist文件夹的内容copy到服务器某个路径。
比如/app/html,或者就是nginx目录下的html。随自己开心就好

  1. step3,修改nginx配置

目录确定后,我们就需要修改nginx的配置了。如下:

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

server {
listen 127.0.0.1:6000;
#server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location /m-web/ {
root /app/html/dist;
index index.html index.htm;
}
location /m-api {
proxy_pass http://localhost:8080/m-api;
#proxy_pass http://api-m.chenzhijun.top/m-api;
}
#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}

然后启动 nginx 就好了。

Kubernetes 第一天

发表于 2019-04-03 | 分类于 Kubernetes | 阅读次数

Kubernetes day1

Kubernetes是什么?

Kubernetes简称k8s。最直观的解释它是用将资源进行整合,将应用与底层隔离。因此,搞业务开发的,专心搞好业务逻辑。搞底层机器,网络资源的安心搞好底层网络资源。而k8s就是这中间的一层,承上启下。也就是传说中的PaaS。现在可以说没有那个Paas或者Caas不是基于k8s搞的。不过我觉得理解的不深,k8s的作用其实还有很多,如果你用过docker或者直接开发业务就会有比较深的感知。

Kubernetes 关键组件

安装一个K8S集群需要哪些组件了?一个完整的小集群里面,需要有一个master,一个node,两台机器。master和node上分别有哪些组件了?master上有kube-apiserver,kube-scheduler,kube-controller-manager; node上有kubelet,kube-proxy,docker;另外需要在master上安装一个etcd数据库。如果是非二进制安装,master和node上都需要有kubeadm。安装完这些之后需要在master节点上使用’kubectl apply -f [kubelet-network].yaml’也就是如果你使用flannel网络,就可能需要安装flannel的网络插件。这个插件是已pod的方式创建的。

组件说明

Etcd

键值数据库,这个没有什么特别好说的。要在安装k8s集群前先启动,保存k8s所有资源对象数据

kube-apiserver

集群控制的入口进程,提供HTTP Rest接口的关键服务进程,是k8s里面所有资源操作的唯一入口。

kube-controller-manager

k8s所有资源对象的自动化控制中心

kube-scheduler

k8s的资源调度进程

kubelet

负责pod对应的容器的创建,启停等任务,同时与Maser节点密切协作,实现集群管理的基本功能

kube-proxy

实现kubernetes Service的通信与负载均衡机制的重要组件

Java 大数据中的敏感词汇处理

发表于 2019-03-31 | 分类于 Java | 阅读次数

Java 大数据中的敏感词汇处理

1…567…18

180 日志
41 分类
70 标签
RSS
GitHub GitEE
推荐阅读
  • 陈志军的个人站
© 2017 - 2023 陈志军
由 Hexo 强力驱动
主题 - NexT.Muse