打开科学上网后,打开链接 https://platform.openai.com/signup?launch ,使用准备好的邮箱,点击下面对应的登录按钮。
填写姓名和生日,公司可以不用填写
这一步就比较关键的一部,在上面https://sms-activate.org
注册的账号,购买虚拟号码等待短信。
选择国家,这里我使用的是巴西,比较便宜
购买成功后,会给你一个手机号码,并且等待手机验证码
填写手机号码
回到openai
网页,填写上面的手机号码,这里的手机号码,包含小括号里面的数字
这个时候,等个几秒钟,https://sms-activate.org/
苹果就会收到对应的验证码了。
不出意外的话,恭喜你,这个时候就注册成功了,https://chat.openai.com/ 这个就是聊天的地址了,接下来就开启ChatGPT的神秘之路吧
]]>如果实在懒得注册,我自己搞了个ChatGPT的微信小程序套壳,零门槛,还不收费,有兴趣的扫码体验一把,或者微搜索:糯糯AI
自2022年1月31日起,CentOS团队从官方镜像中移除CentOS 8的所有包,但软件包仍在官方镜像上保留一段时间。
现在被转移到https://vault.centos.org
。如需继续运行旧CentOS 8,可以在/etc/yum.repos中更新repos.d,使用vault.centos.org
代替mirror.centos.org
1 | cd /etc/yum.repos.d/ |
里面有很多源文件,打开文件,注释掉mirrorlist
一行,然后找到baseurl
一行解开注释,并且修改URL为最新地址。
例如:1
2
3
4
5
6
7
8
9vim CentOS-Base.repo
[BaseOS]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=BaseOS&infra=$infra
baseurl=http://vault.centos.org/$contentdir/$releasever/BaseOS/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
可以用一下方法批量替换:1
2sudo sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sudo sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
码云:https://gitee.com/qianxunclub/grpc2http-gateway
GITHUB:https://github.com/qianxunclub/grpc2http-gateway
该服务是基于 Grpc 反射 开发的一款 Grpc 换为 Http 请求的工具。
因为是基于反射开发,所以使用时无需修改 proto 及相关的代码实现,只需在启动服务时开启反射功能。
因为是基于反射开发,需要服务端开启反射功能,开启方式:
grpc-spring-boot-starter
1 | grpc.server.reflection-service-enabled=true |
1 | Server server = ServerBuilder.forPort(SERVER_PORT) |
1 | grpc.endpoint.服务名称=dev.coding.oa.com:9902 |
示例 proto1
2
3
4
5
6
7
8
9
10
11
12
13
14
15syntax = "proto3";
package com.qianxunclub.proto;
option java_outer_classname = "HelloProto";
message HelloRequest {
string fieldName = 1;
}
message HelloResponse {
}
service HelloService {
rpc HelloWorld (HelloRequest) returns (HelloResponse);
}
GET
请求 http://localhost:8080/api/服务名称/
1 | curl \ |
1 | # 这个配置是所部署的服务器地址的 IP 或者 域名,为了 swagger 执行调用 |
访问:http://localhost:8080/swagger-ui/index.html
OPENAPI 地址填写:http://localhost:8080/api/v3/api-docs/服务名称
1 | ./docker-build.sh |
构建完镜像名称为:grpc2http-gateway:latest
1 | cd docker-compose |
欢迎提交 PR 升级,有什么好建议或者想法的,可以添加QQ群一起讨论:852214454
]]>原地址:http://ftp.gnu.org/gnu/gcc/
国内使用:https://mirrors.ustc.edu.cn/gnu/gcc/
1 | wget http://ftp.gnu.org/gnu/gcc/gcc-9.1.0/gcc-9.1.0.tar.gz |
到这里不要直接编译安装的,先把下面的依赖检查一下有没有装好。
因为我这里都已经装好了,所以显示成功1
2
3
4
5
6
7
8
9cd gcc-9.1.0
./contrib/download_prerequisites
gmp-6.1.0.tar.bz2: 确定
mpfr-3.1.4.tar.bz2: 确定
mpc-1.0.3.tar.gz: 确定
isl-0.18.tar.bz2: 确定
All prerequisites downloaded successfully.
如果上面依赖缺少的,就需要安装:1
2
3
4
5yum install gmp-devel
yum install mpfr-devel
yum install libmpc-devel
安装 isl:1
2
3
4
5
6
7
8
9
10
11
12wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2
tar -jxvf isl-0.18.tar.bz2
cd isl-0.18
./configure
make
make install
安装完成,再检车一下:1
./contrib/download_prerequisites
安装开发环境依赖:1
2
3
4yum groupinstall "Development Tools"
yum install glibc-static libstdc++-static
安装gcc:1
2
3
4
5
6
7
8
9
10
11cd gcc-9.1.0
mkdir gcc-build-9
cd gcc-build-9
../configure --prefix=/usr/local/gcc9 --enable-languages=c,c++,go --disable-multilib
make -j4 (-j4选项是make对多核处理器的优化,如果不成功请使用 make,相关优化选项可以移步至参考文献[2]。建议不要使用make -j来编译,虽然可以缩短编译时间,但极大可能会编译失败)
make install
1 | rm -f /usr/bin/gcc |
1 | # 找到现有的版本 |
完成!
]]>前段时间在浏览开源社区的时候,不小心看到一个 12306抢票
系统,一下就被吸引住了,然后就动力歪念头😏,过年终于不用找黄牛了,哇哈哈哈,写了差不多一个星期,终于可以全自动抢票了,中间遇到的坑也是挺多的,在这里分享一下,供大家参考学习。
使用 Chrome
或者 Firefox
浏览器,我这里用的是 Firefox
,打开12306官网,然后打开开发者选项,点击网络
选项卡,就可以观察到所有的请求接口情况了。
然后按照正常的流程,开始下单,没点击一部,然后看下面的控制台的请求情况,和分析接口的意义,这是一个很苦逼的过程😭。
我这了整理了一些必要的一些接口,也是按照购票顺序写的。
购票一部分站点参数使用的是编码,并不是汉字,需要使用这个接口获取对应的值1
/https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9098
这个是为了获取必要的两个 cookie 的值的:RAIL_EXPIRATION
和 RAIL_EXPIRATION
。
这个接口就比较吊了,有特么好神奇,至今没搞懂后面的参数哪里来的,目前的是这俩 cookie 都是手动写死的,等研究出来,补充一下。
1 https://kyfw.12306.cn/otn/HttpZF/logdevice?algID=&hashCode=Ja4gW6Upz9XdOiA2-UBi5DjyNsB3Fmf3L0wxipiFro4&FMQw=0&q4f3=zh-CN&VySQ=FGEYxQuwmyAY0Gevguxv6Ch8vDiXELlH&VPIf=1&custID=133&VEek=unspecified&dzuS=32.0%20r0&yD16=0&EOQP=c227b88b01f5c513710d4b9f16a5ce52&lEnu=2886729839&jp76=b34839808806e7ff02df813671ec99b3&hAqN=MacIntel&platform=WEB&ks0Q=a103db222cd8296a50268c8f0355b741&TeRS=877x1440&tOHY=24xx900x1440&Fvje=i1l1s1&q5aJ=-8&wNLf=99115dfb07133750ba677d055874de87&0aew=Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010.14;%20rv:67.0)%20Gecko/20100101%20Firefox/67.0&E3gR=6c9c3674a3e453e368c3a0cc46f30eb8×tamp=1560399328000
1 | https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT |
这个接口就是为了查看登录是否需要验证码的1
https://kyfw.12306.cn/otn/login/conf
1 | https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&_=%s |
1 | https://kyfw.12306.cn/passport/captcha/captcha-check?answer=%s&rand=sjrand&login_site=E&_=%s |
1 | https://kyfw.12306.cn/passport/web/login |
1 | https://kyfw.12306.cn/passport/web/auth/uamtk-static?appid=otn |
uamtk
获取这个东西是为了后面获取用户 tk
做准备的。1
https://kyfw.12306.cn/passport/web/auth/uamtk
tk
这东西后面买票是必须使用的。1
https://kyfw.12306.cn/otn/uamauthclient
这个接口只是为了校验,没有实际意义。1
https://kyfw.12306.cn/otn/login/checkUser
1 | https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest |
token
这个接口会获取两个 token
。globalRepeatSubmitToken
:获取乘客信息、检查订单、获取排队情况、提交订单使用。key_check_isChange
:提交订单使用。1
https://kyfw.12306.cn/otn/confirmPassenger/initDc
1 | https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs |
1 | https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo |
1 | https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount |
1 | https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue |
这个获取订单接口必须成功,才能确定下单成功的。1
https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime
因为代码有部分敏感信息,所以我这就重新打包上传到QQ群了。加QQ群下载:852214454
1 | sudo yum install ansible |
Ubuntu使用apt-get安装
1 | sudo apt-get install ansible |
MAC使用pip安装
1 | sudo pip install ansible |
其他安装方式,参考官网安装文档吧。
官网配置文件介绍:https://docs.ansible.com/ansible/latest/installation_guide/intro_configuration.html
我自己的配合文件:1
2
3
4
5
6vim ~/.ansible.cfg
[defaults]
hostfile=$HOME/.ansible/hosts
deprecation_warnings=False
#host_key_checking=Falses
/etc/ansible/hosts
在上面配置信息hostfile
的路径找到hosts
文件编辑:1
2
3
4
5
6vim ~/.ansible/hosts
[test]
192.168.1.1
192.168.1.2
192.168.1.3
上面这种配置方式,是需要添加sshkey
才可以使用的,这种使用方式更爽一些。
如果想使用用户名密码来配置ansible,也是可以的,一样是需要在hostfile
的路径找到hosts
文件编辑:1
2
3
4
5
6vim ~/.ansible/hosts
[test]
192.168.1.1 ansible_ssh_user=用户名 ansible_ssh_pass=密码
192.168.1.2 ansible_ssh_user=用户名 ansible_ssh_pass=密码
192.168.1.3 ansible_ssh_user=用户名 ansible_ssh_pass=密码
无论是使用sshkey
还是使用sshpass
,都可以使用下面的测试:1
2
3
4
5
6
7
8
9
10
11
12
13
14ansible test -m ping
192.168.1.1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.3| SUCCESS => {
"changed": false,
"ping": "pong"
}
首先我想说一句“日了狗”了不知道过分不过分!
前段时间,七牛云发来下面的通知:
这意味着,我之前所有的使用七牛云的图片域名变了,要修改!要全部修改!!!算了,不说了。
消消气,接下来说怎么用抛弃七牛云,使用github吧。
xxx.io
,貌似现在不加.io
也行了,之前是要加的,我只是习惯了README.MD
按钮最好点上去,不然空项目,不方便上传图片用户名.github.io
CNAME
的文件,内容就是自己在阿里云设置解析的域名,提交就可以了:GitHub Pages
设置,可以看到域名已经设置成功:接下来上传一张图片感觉一下效果:
上传完成后,访问一下感觉感觉,访问地址是:https://自己的域名.com/文件名称.jpg
完美!
]]>一般面试官都是按照自己的简历面试的,下面的面试题当然也是依据我自己的简历的一些问题总结,我是对一些架构知识比较感兴趣,所以简历比较突出架构方面的。
别看人家问的问题很简单,但是你不能简单的回答的,依据自己的能力,能回答多深就多大多深。
然后就是看和面试官的缘分了,能碰触火花,那就恭喜了!
1、描述一下不同业务的架构方式和自己觉得比较牛逼的架构。
2、在公司自己的角色,工作内容和负责的事项。
3、自己觉得对自己提升最大的项目介绍一下,包括业务和技术和协调管理等各个方面。
4、jvm内存怎么设置,怎么调优,依据都有哪些。
5、threadlocal 介绍一下。
6、kafka原理,为什么性能高并且还稳定。
7、分布式使用集群的时候,其中一个节点断掉了,处理策略,比如 dubbo ,eureka,grpc等等,主要介绍处理原理。
8、分布式事务怎么处理。
9、服务器配置和数量怎么协调分配,部署的都是什么服务。
10、如何协调项目或者服务之间的关系。
11、服务崩溃的原因你都遇到过哪些。
12、如何保证服务正常运行,出现错误,怎么修复,监控和快速修复排错方面。
13、项目中,有没有遇到测试开发环境都是正常的,生产错误的情况?然后如何找到这个错误的问题,怎么解决这个问题。
14、分库分表是用什么工具,如何分的,数据量多少。
15、数据库单机还是主从,部署方案,如果宕机处理方式。
16、很多后台管理列表查询,没有分库分表字段,怎么处理,全库全表查询太慢。
17、读写分离的场景,读写分离不一定是mysql的读写分离,我回答的是mysql写,mongodb读。
18、项目中接口最大并发能承受多少。
19、如果你来规划淘宝双11,从哪些方面应对该活动。
20、做为一个架构师,一套架构怎么产生,流程是什么。
21、微服务优缺点,如何应对它的缺点。
22、微服务数量庞大起来,如何管理这些服务。
23、分布式配置中心的应用。
24、说一个自己比较熟悉技术,说说原理,自己能不能开发一个这个产品。
25、你的优点是什么,录用你的原因,优势是什么?缺点是什么。
26、开发中,有咩有遇到比较奇葩的问题,为什么会有这个问题,如何解决的。
27、你对简历上以外的技术还会哪些?对那些比较感兴趣,或者做过什么小demo之类的。
28、你对技术方面是如何学习,途径是什么。
29、自己觉得呆的这么几个公司,哪个对自己提升最大,为什么,为什么离职?再找工作的目标是什么。
30、你给公司带来的最大利益有哪些,或者提供了哪些技术等。
nginx.conf文件是放在conf目录下的一个配置文件。这个是Nginx服务器的主配置文件。通过指令来配置这个文件能达到控制nginx,实现反向代理,负载均衡,也是nginx入门的基础。读懂使用nginx.conf文件是这篇文章写作目的。
首先介绍文件的架构,整个conf文件分为 全局块、events块、http块、server块、location块。每个块有每个块的作用域,越外层的块作用域就包含内部块的作用域,如全局块作用域就包含events块、http块、server块和location块。而文件中的“#”代表注析,#后的代码是不会有效果的。修改nginx.conf后是必须重启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... #全局块
event{ #events块
...
}
http{ #http块
server{ #server块
... #server全局块
location{ #location块
...
}
location{ #location块
...
}
}
server{ #server块
...
}
... #http全局块
}
大致的nginx.conf文件如上,而下面讲解各块的作用。
名称 | 说明 |
---|---|
全局块 | 全局块是默认配置文件从开始到events块之间的一部分内容,主要是设置一些影响Nginx服务器整体运行的配置指令。因此,这些指令的作用域是Nginx服务器全局。作用:配置Ngnix服务器的用户组、worker process数、Nginx进程PID存放路径、日志的存放路径和类型已经配置文件引入等。 |
events块 | events块的指令主要影响Nginx服务器与用户的网络链接。 作用:是否开启多worker process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取那种事件驱动模型处连接请求,每个worker process可以同时支持的最大连接数等。 |
http块 | http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。 |
server块 | server块,虚拟主机(虚拟服务器)。作用:使得Nginx服务器可以在同一台服务器上至运行一组Nginx进程,就可以运行多个网站。 |
location块 | location块是server块的一个指令。作用:基于Nginx服务器接收到的请求字符串,虚拟主机名称(ip,域名)、url匹配,对特定请求进行处理。 |
日常我们使用到的配置如下,这些都是常用的指令。
1 | #### 全局块 开始 #### |
指令 | 说明 |
---|---|
user user [group] | 用于配置允许Nginx服务器用户(组)。user,指可以运行Nginx服务器的用户。group,指可以运行Nginx服务器的用户组。通常设置:user nobody nobody |
worker process number/auto | Nginx服务器实现并发处理服务关键,设置值越大并发处理量也就越多,但也受到软硬件制约。number,指Nginx进程最多可以产生worker process数。auto,Nginx进程自动检测。默认设置为1。 |
pid file | Nginx进程作为系统的守护进程运行,我们需要在某文件中保存当前运行程序的主进程号。Nginx支持对它的存放路径进行自定义配置,指令时pid。如pid sbin/web_nginx |
error_log file | 配置错误日志存放路径,全局块、http块和server块中都可以对日志进行相关配置。如:error_log logs/error.log error |
incloud file | 配置文件的引入,引入其他Nginx配置或者第三方模块的配置。如:include mime.types |
accept_mutex on/off | 设置网络连接的序列化,当某一个时刻只有一个网络连接来时,多个睡眠进程会被同时叫醒,但只有一个进程能接。如果每次呼醒的进程数目太多,会影响一部分系统性能。为了解决这个问题,Nginx配置accept_mutex,当开启的时候,对Nginx进程接收连接进行序列化,防止多个进程对连接的争强。只能在events块配置。 |
accept_accept on/off | 设置是否允许同时接收多个网络连接,这个是配置worker process是否允许同时接收多个连接。 |
use method | 事件驱动模型选择,强制Nginx服务器选择那种事件驱动模型进行消息处理。method:select、poll、kqueue、epoll、rtsig、/dev/poll 以及eventport。此指令智能在events块中配置。 |
woker_connections number | 配置最大连接数,设置允许每一个worker process同时开启的最大连接数。默认为512。只能在events块中配置。 |
default_type mime-type | 在浏览器中,显示内容HTML、XML、GIF和Flash等种类繁多的文本、媒体等资源,浏览器为了区分这些资源,需要使用MIME Type。MIME Type是网络资源的媒体类型。Nginx服务器作为Web服务器,必须能够识别前端请求的资源类型。配置如:include mime.types; default_type application/octet-stream;在http块、server块或者location块进行配置。 |
access_log path[format[buffer=size]] | 服务日志定义,此处定义所指日志与常规的不同,记录Nginx服务器提供服务过程应答前端请求的日志。可以对服务日志进行格式定义。配置如:log_format exampleLog ‘remoteaddr−[remoteaddr−[remote_addr - [time_local] requestrequestrequest status bodybytessentbodybytessentbody_bytes_sent http_referer $http_user_agent’输出:192.168.1.102 - [31/Oct/2011:20:41:29 +0800] “GET/HTTP/1.1” 200 151 “-” “Mozilla/5.0(compatible;MSIE 10.0;Window NT 6.2; Trident/6.0)” |
sendfile on/off | 配置允许sendfile方式传输文件,在Apache、lighttd等Web服务器配置中,都有和sendfile相关的配置。用于开启或者关闭sendfile传输文件。默认为off。在http块、server块或者location块进行配置。 |
sendfile_max_chunk size | worker process每次调用sendfile传输的数据量最大不能超过这个值。默认为0。在http块、server块或location块中配置。和sendfile指令一起使用。 |
keepalive_timeout timeout[header_timeout] | 配置连接超时时间,与用户建立会话连接后,Nginx服务器保持这些连接打开一段时间。此指令设置时间。timeout,服务器端对连接的保持时间。默认值为75s。header_tiemout,可选项,在应答报文头部Keep-Alive域设置超时时间。该指令被Mozilla或者Konqueror识别。配置如:keepalive_timeout 120s 100s;此指令在http块、server块或location块中配置。 |
keepalive_requests number | 单连接请求数上限,用户端和服务端建立连接后,用于限制用户通过某一连接向Nginx服务器发送请求的次数。在server块和location块中,默认设置100。 |
listen address[:port][default_server][setfib=number][backlog=number][rcvbuf=size][sndbuf=size][deferred] | 配置监听使用指令listen。address,IP地址,如果有IPv6的地址,需要使用中括号“[]”括起来,比如[fe80::1]等port,端口号,如果只定义IP地址没有定义端口号,就使用80端口。path,socket文件路径,如/var/run/nginx.sock等default_server,标识符,将此虚拟主机设置为address:port的默认主机。配置如:listen :80 / :8000;listen 192.168.1.10:8000;listen 192.168.1.10;listen 8000;listen 192.168.1.10 default_server backlog=1024; |
server_name name… | 基于名称的虚拟主机配置,主机指server块虚拟主机。设置主机名称并配置号DNS,用户就可以使用这个名词向此虚拟主机请求了。配置如:server_name myserver.com www.myserver.com |
location [ = / ~ / ~* / ^~ ] url | 配置location,匹配成功,就继续执行下面命令。”=”,用于标准url前,要求请求字符串与url严格匹配。”~”,用于表示URL包含正则表达式,并且区分大小写。”~*”,用于表示url包含正则表达式,并且不区分大小写。”^~”,用于标准url前,用于匹配请求最高location后,立即使用localtion处理请求。 |
root path | 配置请求的根目录,在服务端指定目录中请求资源。 |
alias path | 更改location的URL,使用alias指令改变location接收的URL的请求路径。配置如:alias /locationtest1/other/$1 |
index file … | 设置网站的默认首页,用于index设置为默认首页。配置如:index index.$1.html index.my.html index.html |
error_page code … [=[response]] url | 设置网站的错误页面,如果服务端错误需要错误页面来显示。这个设置错误页面。配置如:error_page 404 404/html |
allow address/CIDR/all | 基于IP配置Nginx的访问权限,通过IP来判断客户端是否拥有对Nginx的访问权限。address,允许访问的客户端的IP,不支持同时设置多个。需要重复使用allow指令。CIDR,允许访问的客户端CIDR地址,例如202.80.18.23/25。all,代表允许所有客户端访问。配置如:deny 192.168.1.1;allow 192.168.1.0/24 deny all; |
auth_basic string/off | 基于密码配置Nginx的访问权限,该给予HTTP Basic Authentication协议的认证。该协议是一种HTTP性质的认证办法,需要识别用户名和密码,认证失败的苦户端不拥有访问Nginx服务器权限。 |
auth_basic_user_file file | 用语设置包含用户名和密码信息的文件路径。file为密码文件的绝对路径。file配置如:name1:password1 |
通过指令的实例和指令的详细说明,可以学会看nginx.conf。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
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
61Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elasticsearchTemplate' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchDataAutoConfiguration.class]: Unsatisfied dependency expressed through method 'elasticsearchTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchClient' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.Client]: Factory method 'elasticsearchClient' threw exception; nested exception is java.lang.NoSuchMethodError: org.jboss.netty.channel.socket.nio.NioWorker.<init>(Ljava/util/concurrent/Executor;Lorg/jboss/netty/util/ThreadNameDeterminer;)V
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 33 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchClient' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.Client]: Factory method 'elasticsearchClient' threw exception; nested exception is java.lang.NoSuchMethodError: org.jboss.netty.channel.socket.nio.NioWorker.<init>(Ljava/util/concurrent/Executor;Lorg/jboss/netty/util/ThreadNameDeterminer;)V
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 43 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.Client]: Factory method 'elasticsearchClient' threw exception; nested exception is java.lang.NoSuchMethodError: org.jboss.netty.channel.socket.nio.NioWorker.<init>(Ljava/util/concurrent/Executor;Lorg/jboss/netty/util/ThreadNameDeterminer;)V
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 56 common frames omitted
Caused by: java.lang.NoSuchMethodError: org.jboss.netty.channel.socket.nio.NioWorker.<init>(Ljava/util/concurrent/Executor;Lorg/jboss/netty/util/ThreadNameDeterminer;)V
at org.jboss.netty.channel.socket.nio.NioWorkerPool.newWorker(NioWorkerPool.java:44)
at org.jboss.netty.channel.socket.nio.NioWorkerPool.newWorker(NioWorkerPool.java:28)
at org.jboss.netty.channel.socket.nio.AbstractNioWorkerPool.init(AbstractNioWorkerPool.java:80)
at org.jboss.netty.channel.socket.nio.NioWorkerPool.<init>(NioWorkerPool.java:39)
at org.jboss.netty.channel.socket.nio.NioWorkerPool.<init>(NioWorkerPool.java:33)
at org.elasticsearch.transport.netty.NettyTransport.createClientBootstrap(NettyTransport.java:354)
at org.elasticsearch.transport.netty.NettyTransport.doStart(NettyTransport.java:290)
at org.elasticsearch.common.component.AbstractLifecycleComponent.start(AbstractLifecycleComponent.java:68)
at org.elasticsearch.transport.TransportService.doStart(TransportService.java:182)
at org.elasticsearch.common.component.AbstractLifecycleComponent.start(AbstractLifecycleComponent.java:68)
at org.elasticsearch.client.transport.TransportClient$Builder.build(TransportClient.java:164)
at org.springframework.data.elasticsearch.client.TransportClientFactoryBean.buildClient(TransportClientFactoryBean.java:89)
at org.springframework.data.elasticsearch.client.TransportClientFactoryBean.afterPropertiesSet(TransportClientFactoryBean.java:85)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration.createTransportClient(ElasticsearchAutoConfiguration.java:116)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration.createClient(ElasticsearchAutoConfiguration.java:93)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration.elasticsearchClient(ElasticsearchAutoConfiguration.java:84)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$68f5928b.CGLIB$elasticsearchClient$1(<generated>)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$68f5928b$$FastClassBySpringCGLIB$$5550a67a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$68f5928b.elasticsearchClient(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 57 common frames omitted
从异常的信息看,有两种可能:
先找一下有没有netty包,找了一遍,发现有netty的
那只有第二种可能了,就是包冲入,又仔细看了一遍引入的JAR包,果然又出现了一个jar
然后挨个挨个查找,发现是dubbo和zookeeper里面已经有了netty包了,所以出现了包冲突。
出错原因是Elasticsearch的netty包和dubbo、zookeeper里面的netty包冲突,我这里是排除了dubbo、zookeeper里面的netty包:
1 | <dependency> |
启动,成功!
]]>1 | <dependency> |
ES详细报错信息: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[2018-08-23T15:56:05,004][WARN ][o.e.x.s.t.n.SecurityNetty4ServerTransport] [node-1] exception caught on transport layer [NettyTcpChannel{localAddress=/192.168.1.40:9300, remoteAddress=/192.168.1.150:55594}], closing connection
java.lang.IllegalStateException: Received message from unsupported version: [2.0.0] minimal compatible version is: [5.6.0]
at org.elasticsearch.transport.TcpTransport.ensureVersionCompatibility(TcpTransport.java:1462) ~[elasticsearch-6.3.2.jar:6.3.2]
at org.elasticsearch.transport.TcpTransport.messageReceived(TcpTransport.java:1409) ~[elasticsearch-6.3.2.jar:6.3.2]
at org.elasticsearch.transport.netty4.Netty4MessageChannelHandler.channelRead(Netty4MessageChannelHandler.java:64) ~[transport-netty4-6.3.2.jar:6.3.2]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310) [netty-codec-4.1.16.Final.jar:4.1.16.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:297) [netty-codec-4.1.16.Final.jar:4.1.16.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:413) [netty-codec-4.1.16.Final.jar:4.1.16.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265) [netty-codec-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:241) [netty-handler-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:545) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:499) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) [netty-transport-4.1.16.Final.jar:4.1.16.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) [netty-common-4.1.16.Final.jar:4.1.16.Final]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
错误信息写的是因为版本不一致的原因导致的,客户端使用的2.0.0版本,要求最低是5.6.0版本的,然后各种百度各种查啊,原因如下:
springboot我用的版本是SpringBoot1.5.9,然后引入的spring-data-elasticsearch
里面包含的es版本是2.4.0
的。
解决办法有两种,1:重新安装ES版本,安装2.0.0版本的。 2:升级自己的SpringBoot。
我这里因为是新系统,为了代码规范,所以就安装了ES2.0.0版本了,但是我感觉最好的解决办法应该要升级SpringBoot版本才对。
1.5.9.RELEASE
版本,指定了elasticsearch版本,否则无法使用spring data elasticsearch | elasticsearch |
---|---|
3.0.0.RC2 | 5.5.0 |
3.0.0.M4 | 5.4.0 |
2.0.4.RELEASE | 2.4.0 |
2.0.0.RELEASE | 2.2.0 |
1.4.0.M1 | 1.7.3 |
1.3.0.RELEASE | 1.5.2 |
1.2.0.RELEASE | 1.4.4 |
1.1.0.RELEASE | 1.3.2 |
1.0.0.RELEASE | 1.1.1 |
创建elasticsearch用户
1 | groupadd elsearch |
提高系统线程数
1 | vim /etc/security/limits.conf |
1 | vim /etc/security/limits.d/90-nproc.conf |
否则会出现错误:
1 | max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] |
1 | vim /etc/sysctl.conf |
否则出现以下错误:1
max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
elsearch
用户 1 | su elsearch |
下载2.0.0
的elasticsearch包,因为程序使用的是spring-boot1.5.9.RELEASE
版本,所以使用elasticsearch的2.0.0
版本,否则无法启动
如果使用的是其他版本的springboot,需要按照代码版本使用不同版本的elasticsearch服务
下载地址:https://www.elastic.co/downloads/past-releases/elasticsearch-2-0-0
1 | wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/zip/elasticsearch/2.0.0/elasticsearch-2.0.0.zip |
给目录授权
使用root用户给ES目录授权
1 | chown -R elsearch:elsearch elasticsearch-2.0.0/ |
修改ES配置
1 | cd elasticsearch-2.0.0 |
主要修改一下几项:
1 | ERROR: bootstrap checks failed |
1 | http.cors.enabled: true |
使用elsearch
用户启动一下1
2
3cd elasticsearch-2.0.0
./bin/elasticsearch
如果出现started
字样,说明启动成功
然后使用下面启动方式,为后台启动1
./bin/elasticsearch -d
浏览器访问:http://192.168.1.40:9200
,出现一下为成功:1
2
3
4
5
6
7
8
9
10
11
12{
name: "node-1",
cluster_name: "my-application",
version: {
number: "2.0.0",
build_hash: "de54438d6af8f9340d50c5c786151783ce7d6be5",
build_timestamp: "2015-10-22T08:09:48Z",
build_snapshot: false,
lucene_version: "5.2.1"
},
tagline: "You Know, for Search"
}
项目版本:
项目是SpringBoot
的1.5.9-release
版本,fastdfs版本如下:1
2
3
4
5<dependency>
<groupId>net.arccode</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0</version>
</dependency>
调用方式如下:
我的fastdfs.conf
配置:1
2
3
4connect_timeout = 10
network_timeout = 30
charset = UTF-8
tracker_service = xxx.xxx.xxx.xxx:xxx
java调用:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class FileManage{
private TrackerClient trackerClient;
private TrackerService trackerService;
//初始化dfs
public FileManage(){
ClientGlobal.init("fastdfs.conf");
trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
trackerService = trackerClient.getConnection();
}
//文件上传
public void upload(){
StorageClient storageClient = new StorageClient(trackerService,null);
storageClient.upload_file(.....);
...
}
...
}
报错情况:
每次刚启动服务,如果没有直接使用,过一段时间,再调用上传文件服务,会报错,但是再次上传,就没事了,又正常了,报错信息如下:1
2
3
4
5
6
7
8
9
10java.io.IOException: recv package size -1 != 10
at org.csource.fastdfs.ProtoCommon.recvHeader(ProtoCommon.java:206)
at org.csource.fastdfs.ProtoCommon.recvPackage(ProtoCommon.java:242)
at org.csource.fastdfs.TrackerClient.getStoreStorage(TrackerClient.java:143)
at org.csource.fastdfs.StorageClient.newWritableStorageConnection(StorageClient.java:1912)
at org.csource.fastdfs.StorageClient.do_upload_file(StorageClient.java:702)
at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:207)
at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:225)
at org.csource.fastdfs.StorageClient1.upload_file1(StorageClient1.java:112)
经过多次验证重现这个错误,发现刚启动,间隔时间30秒,就会报错,不能上传,目测和fastdfs.conf
配置的network_timeout =30
有关系。
然后各种百度谷歌,发现有这么一句话:如果客户端服务启动,成功链接到dfs服务器,如果在network_timeout时间内,dfs服务没有接收到任何请求信息,会吧这个客户端踢掉!
日了,为毛要踢掉,我还要用啊,看来每次启动链接成功都需要给dfs服务发送点什么才行!
对dfs有研究了一波,发现fastdfs-client-java
包到ProtoCommon.java本来已经提供了一个发送信息到一个方法,如下:1
public static boolean activeTest(Socket sock)
废话不多少,先试一波,修改上面dfs初始化代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class FileManage{
private TrackerClient trackerClient;
private TrackerService trackerService;
//初始化dfs
public FileManage(){
ClientGlobal.init("fastdfs.conf");
trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
trackerService = trackerClient.getConnection();
//给dfs发送一个消息
ProtoCommon.activeTest(trackerService.getSocket());
}
//文件上传
public void upload(){
StorageClient storageClient = new StorageClient(trackerService,null);
storageClient.upload_file(.....);
...
}
...
}
启动项目,等30秒以上,测试,成功!
卧槽,终于记录完了,公司电脑不能上网,上面所有代码纯手工写的,累死!
]]>这个就不用多说了,地球人都在用,很好的开发工具,并且插件齐全,更牛逼的是支持各种语言开发。
官网地址:http://www.jetbrains.com/idea/
注册码地址:http://idea.lanyus.com/
Navicat其实是更好的一个数据库客户端管理工具,但是收费,很麻烦,就又找了一个,也是比较好用的,DataGrip也是IntelliJ IDEA中的一个工具。
官网地址:https://www.jetbrains.com/datagrip/
注册码地址:http://idea.lanyus.com/
这个是在开发中,经常测试RestfulApi接口使用的,并非专业接口测试用具,开发阶段使用是一个特别好的工具,可以设置各种请求方式,并且大多已经提供下拉框了,不用手打了,必须推荐。
官网地址:https://www.getpostman.com/postman
云笔记各种产品很多,我比较钟爱有道云笔记,支持分类,加密,markdown,手机版等好多功能,并且初始内存也是比较大的,3G的,写笔记够写一辈子了。
官网地址:http://note.youdao.com/noteintro.html
文本编辑器很重要,要选好,作为一名优秀的码农,notepad显然已经满足不了,文本编辑器,一定要轻量级的,速度快的,还要功能多的,vscode是最好的选择了。
官网地址:https://code.visualstudio.com/
赶紧告别Windows自带的cmd把,cmder是在是强大的一批,不要想别的了,赶紧下载使用把。
官网地址:http://cmder.net/
这个玩意就厉害了,SSH、FTP等管理工具,重要的是免费已经足够使用了,功能齐全,不用在为其他工具收费烦恼了。
官网地址:https://mobaxterm.mobatek.net/
说真的,已经彻底放弃微软的Office了,谁用谁恶心,还是WPS比较良心,而且现在2019版本的更强大,支持各种画图,太漂亮了。
这个是比较老牌的软件了,搜索电脑上各种文件,速度快的吓人。
官网地址:http://www.voidtools.com/
找了好多好多截图软件,还是这个比较舒服,一直用QQ截图习惯了,就找了一个类似QQ截图方式的工具,还能滚动截图,实用。
官网地址:https://xnipapp.com/
提高开发效率,各种软件切换和快速启动必不可缺啊,这个就特别适用,功能也算齐全。
官网地址:https://manico.im/
]]>突然有一天出了个需求,做文件防盗链的,而且需要通过nginx来做,这个时候必然想到了Openresty
,Openresty本身其实已经安装有nginx了,但是要求在公司原有的nginx上面装一些Openresty里面的模块,这个时候就有点复杂了,但是最终还是研究出来了,庆幸啊,这里做一个笔记,以便下次安装使用。
下载地址:https://github.com/openresty/openresty/releases1
2wget https://github.com/openresty/openresty/releases/download/v1.13.6.1/openresty-1.13.6.1.tar.gz
解压1
2
3
4tar -xvf openresty-1.13.6.1.tar.gz
cd openresty-1.13.6.1
编译安装1
2
3
4
5./configure -j2
gmake
gmake install
在下载openresty
安装包的时候,里面其实已经依赖了lua
了,只需要安装就好了
1 | cd openresty-1.13.6.1/bundle/LuaJIT-2.1-20171103/ |
找到以前nginx
的源码包,配置lua位置
1 | cd nginx-1.15.0 |
1 | ./configure --prefix=/usr/local/nginx --with-cc-opt=-O2 --add-module=/root/openresty-1.13.6.1/bundle/ngx_devel_kit-0.3.0 --add-module=/root/openresty-1.13.6.1/bundle/echo-nginx-module-0.61 --add-module=/root/openresty-1.13.6.1/bundle/xss-nginx-module-0.05 --add-module=/root/openresty-1.13.6.1/bundle/ngx_coolkit-0.2rc3 --add-module=/root/openresty-1.13.6.1/bundle/set-misc-nginx-module-0.31 --add-module=/root/openresty-1.13.6.1/bundle/form-input-nginx-module-0.12 --add-module=/root/openresty-1.13.6.1/bundle/encrypted-session-nginx-module-0.07 --add-module=/root/openresty-1.13.6.1/bundle/srcache-nginx-module-0.31 --add-module=/root/openresty-1.13.6.1/bundle/ngx_lua-0.10.11 --add-module=/root/openresty-1.13.6.1/bundle/ngx_lua_upstream-0.07 --add-module=/root/openresty-1.13.6.1/bundle/headers-more-nginx-module-0.33 --add-module=/root/openresty-1.13.6.1/bundle/array-var-nginx-module-0.05 --add-module=/root/openresty-1.13.6.1/bundle/memc-nginx-module-0.18 --add-module=/root/openresty-1.13.6.1/bundle/redis2-nginx-module-0.14 --add-module=/root/openresty-1.13.6.1/bundle/redis-nginx-module-0.3.7 --add-module=/root/openresty-1.13.6.1/bundle/rds-json-nginx-module-0.15 --add-module=/root/openresty-1.13.6.1/bundle/rds-csv-nginx-module-0.08 --add-module=/root/openresty-1.13.6.1/bundle/ngx_stream_lua-0.0.3 --with-ld-opt=-Wl,-rpath,/usr/local/lib/ --with-stream --with-stream_ssl_module --with-http_ssl_module |
编译完成了,执行make
,记住,这里不要执行make install
,不然会把以前安装的会覆盖的
1 | make |
这里有几个参数说明一下:
编译完成后,会新生成一个nginx执行文件,在nginx-1.15.0/objs目录下,测试一下对应的依赖有没有装上
1 | cd nginx-1.15.0/objs |
显示以下,说明完美1
2
3
4
5nginx version: nginx/1.15.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-cc-opt=-O2 --add-module=/root/openresty-1.13.6.1/bundle/ngx_devel_kit-0.3.0 --add-module=/root/openresty-1.13.6.1/bundle/echo-nginx-module-0.61 --add-module=/root/openresty-1.13.6.1/bundle/xss-nginx-module-0.05 --add-module=/root/openresty-1.13.6.1/bundle/ngx_coolkit-0.2rc3 --add-module=/root/openresty-1.13.6.1/bundle/set-misc-nginx-module-0.31 --add-module=/root/openresty-1.13.6.1/bundle/form-input-nginx-module-0.12 --add-module=/root/openresty-1.13.6.1/bundle/encrypted-session-nginx-module-0.07 --add-module=/root/openresty-1.13.6.1/bundle/srcache-nginx-module-0.31 --add-module=/root/openresty-1.13.6.1/bundle/ngx_lua-0.10.11 --add-module=/root/openresty-1.13.6.1/bundle/ngx_lua_upstream-0.07 --add-module=/root/openresty-1.13.6.1/bundle/headers-more-nginx-module-0.33 --add-module=/root/openresty-1.13.6.1/bundle/array-var-nginx-module-0.05 --add-module=/root/openresty-1.13.6.1/bundle/memc-nginx-module-0.18 --add-module=/root/openresty-1.13.6.1/bundle/redis2-nginx-module-0.14 --add-module=/root/openresty-1.13.6.1/bundle/redis-nginx-module-0.3.7 --add-module=/root/openresty-1.13.6.1/bundle/rds-json-nginx-module-0.15 --add-module=/root/openresty-1.13.6.1/bundle/rds-csv-nginx-module-0.08 --add-module=/root/openresty-1.13.6.1/bundle/ngx_stream_lua-0.0.3 --with-ld-opt=-Wl,-rpath,/usr/local/lib/ --with-stream --with-stream_ssl_module --with-http_ssl_module
复制前,最好把之前的nginx备份一下,以防不测1
2
3cd /usr/local/nginx/sbin/
cp nginx nginx.old
赢新的覆盖,覆盖之前,最好停掉nginx1
2
3cd nginx-1.15.0/
cp objs/nginx /usr/local/nginx/sbin/
这里会提示是否覆盖,输入y,然后回车就好了
1 | cd /usr/local/nginx |
启动完成,访问下以前的站点还能不能正常打开,目测是没问题的
创建一个专门存放lua文件的文件夹,我习惯创建在nginx目录下1
2
3cd /usr/local/nginx
mkdir lua
创建一个lua文件1
2
3
4vim hello.lua
ngx.log(ngx.ERR,"hello");
把这个lua文件依赖到nginx里面试试1
2
3
4
5
6location / {
root /workspace/hexo/public/;
index index.html index.htm;
access_by_lua_file lua/hello.lua;
}
老规矩,先检查下有没问题没,然后重启1
2
3
4
5cd /usr/local/nginx
./sbin/nginx -t
./sbin/nginx -s reload
然后打开日志,准备看有没有打印对应的日志信息1
tail -f logs/error.log
正常会看到以下日志1
2018/07/04 11:58:38 [error] 15646#0: *52 [lua] hello.lua:2: hello,
完美!
]]>Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
官方github:https://github.com/ctripcorp/apollo
作者对Apollo对介绍:https://github.com/ctripcorp/apollo/wiki/Apollo%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E4%BB%8B%E7%BB%8D
本次部署环境为DEV(开发环境)、FAT(测试环境)、UAT(预生产)、PRO(生产)
应用服务器:
环境 | 服务器 | 服务 | 端口 |
---|---|---|---|
/ | 192.168.35.206 | apollo-portal | 9102 |
DEV | 192.168.35.207 | apollo-configservice apollo-adminservice | 9100 9101 |
FAT | 192.168.35.208 | apollo-configservice apollo-adminservice | 9100 9101 |
UAT | 192.168.35.209 | apollo-configservice apollo-adminservice | 9100 9101 |
PRO | 192.168.35.210 | apollo-configservice apollo-adminservice | 9100 9101 |
数据库服务器:
环境 | 服务器 | 服务 | 数据库 | 端口 |
---|---|---|---|---|
/ | 192.168.35.226 | apollo-portal | ApolloPortalDB | 3306 |
DEV | 192.168.35.227 | apollo-configservice apollo-adminservice | ApolloConfigDB | 3306 |
FAT | 192.168.35.228 | apollo-configservice apollo-adminservice | ApolloConfigDB | 3306 |
UAT | 192.168.35.229 | apollo-configservice apollo-adminservice | ApolloConfigDB | 3306 |
PRO | 192.168.35.230 | apollo-configservice apollo-adminservice | ApolloConfigDB | 3306 |
下载代码:
1 | git clone https://github.com/ctripcorp/apollo.git |
比较重要的几个项目:
上图简要描述了配置发布的大致过程:
数据库初始化:
下面的sql为大写格式,注意数据库的大小写敏感设置
apollo\scripts\sql\apolloportaldb.sql
apollo\scripts\sql\apolloconfigdb.sql
调整配置并打包:
在Apollo
项目中找到目录apollo\scripts\
的配置文件build.sh
或者build.bat
ApolloConfigDB
配置,下面的是ApolloPortalDB
配置:1 | # apollo config db info 该数据库配置只需要配置一次,不同环境无需修改 |
1 | # meta server url, different environments should have different meta server addresses |
在DEV FAT UAT PRO 对应的ApolloConfigDB
数据库中,找到表ServerConfig
中的eureka.service.url
配置项:
1 | UPDATE apolloconfigdb.ServerConfig SET ServerConfig.`Value`='http://localhost:9100/eureka/' WHERE `Key`='eureka.service.url'; |
修改环境配置,在ApolloPortalDB
数据库修改表ServerConfig
中的apollo.portal.envs
:
1 | UPDATE apolloportaldb.serverconfig SET serverconfig.`Value`='dev,fat,uat,pro' WHERE `Key`='apollo.portal.envs'; |
具体eureka
配置,可以查看官网:https://github.com/ctripcorp/apollo/wiki/%E5%88%86%E5%B8%83%E5%BC%8F%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97
1 | ./build.sh |
apollo-configservice
, apollo-adminservice
, apollo-portal
和apollo-client
。ApolloConfigDB
在每个环境都有部署,所以对不同环境的config-service
和admin-service
需要使用不同的数据库连接信息打不同的包,portal
和client
只需要打一次包即可部署程序到对应的服务器
将apollo-configservice/target/
目录下的apollo-configservice-x.x.x-github.zip
上传到服务器上,解压
修改scripts/startup.sh
:
1 | LOG_DIR=/opt/logs/100003171 |
执行scripts/startup.sh
即可
如需停止服务,执行scripts/shutdown.sh.
将apollo-adminservice/target/
目录下的apollo-adminservice-x.x.x-github.zip
上传到服务器上,解压
修改scripts/startup.sh
:
1 | LOG_DIR=/opt/logs/100003172 |
执行scripts/startup.sh
即可
如需停止服务,执行scripts/shutdown.sh.
将apollo-portal/target/
目录下的apollo-portal-x.x.x-github.zip
上传到服务器上,解压
修改scripts/startup.sh
:
1 | LOG_DIR=/opt/logs/100003173 |
执行scripts/startup.sh
即可
如需停止服务,执行scripts/shutdown.sh.
访问测试
上面部署完成,可以测试
访问不同环境的eureka
,查看服务注册情况是否正确:
1 | http://192.168.35.207:9100/ |
如果可以看到:
1 | 192.168.35.207:apollo-adminservice:9101 |
两个服务都为UP,正常!
访问客户端:
1 | http://192.168.35.206:9102/ |
登录,默认用户名密码为:apollo/admin
新建项目测试。
apollo-core
和apollo-client
包: 1 | <dependency> |
请确保classpath:/META-INF/app.properties文件存在,并且其中内容为自己的项目名称,而且要保持唯一:1
app.id=demo
本地开发
如果是本地开发,可以在开发工具添加Environment:
1 | env=DEV |
线上环境配置方式:
java -Denv=YOUR-ENVIRONMENT -jar xxx.jar
在项目中引用apollo-core
和apollo-client
包,在apollo-core
包中可以看到apollo-env.properties
配置文件,默认配置为打包前配置的信息:
1 | local.meta=http://localhost:8080 |
如果需要修改或者覆盖的话,在项目的resources
从上面复制一个apollo-env.properties
文件,修改对应环境信息就可以了
@EnableApolloConfig
注解即可:1 | import org.springframework.boot.SpringApplication; |
添加一个测试的类DemoConfiguration
,当然配置中心要有下面配置的配置信息:1
2
3
4
5
6@Configuration
@EnableAutoConfiguration
public class DemoConfiguration {
@Value("${demo}")
private String demo;
}
完成!
这个图是计划部署的方案,并不是上面写的例子的方案
]]>为什么要有用分布式配置中心这玩意儿?现在这微服务大军已经覆盖了各种大小型企业,每个服务的粒度相对较小,因此系统中会出现大量的服务,每个服务都要有自己都一些配置信息,或者相同的配置信息,可能不同环境每个服务也有单独的一套配置,这种情况配置文件数量比较庞大,维护起来相当费劲,举个栗子:
在开发的过程中,一般数据库是开发环境数据库,所有服务DB的IP配置为:92.168.0.1,突然老大说,开发环境换了,DB的IP要修改,这下可不好受了,所有模块挨个修改DB的配置,就问你难受不难受?
这个时候分布式配置中心就发挥了很大的优势,只需要修改配置中心配置,所有服务即可自动生效,爽不爽!
官网地址:http://cloud.spring.io/spring-cloud-config/
Spring Cloud Config
为服务端和客户端提供了分布式系统的外部化配置支持。配置服务器为各应用的所有环境提供了一个中心化的外部配置。它实现了对服务端和客户端对Spring Environment
和PropertySource
抽象的映射,所以它除了适用于Spring构建的应用程序,也可以在任何其他语言运行的应用程序中使用。作为一个应用可以通过部署管道来进行测试或者投入生产,我们可以分别为这些环境创建配置,并且在需要迁移环境的时候获取对应环境的配置来运行。
置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。当然他也提供本地化文件系统的存储方式。
使用 spring Cloud 进行集中式配置管理,将以往的配置文件从项目中摘除后放到Git 或svn中集中管理,并在需要变更的时候,可以通知到各应用程序,应用程序刷新配置不需要重启。
其实这个实现原理相对比较简单一些,基于git的交互操作。
pom.xml添加依赖
1 | <dependencies> |
Application启动类添加注解
添加@EnableConfigServer
注解,启用配置中心:
1 | package com.qianxunclub; |
配置文件
在application.yml
或者application.properties
添加配置信息:
1 | spring: |
/**
,就是所有目录所有文件启动测试
首先在git里面添加一个application-dev.yml
配置文件,内容如此下:1
test: 我是配置中心配置信息
已经配置完成了,启动一波试试,看效果咋样,正常情况下是可以正常启动的,然后获取配置文件试试
访问地址:http://localhost:8888/test/dev
如果返回如下,就是成功了:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17{
"name":"test",
"profiles":[
"dev"
],
"label":null,
"version":"64e7882a8f280641724e454a2db5a3da7b44d3d4",
"state":null,
"propertySources":[
{
"name":"https://gitee.com/qianxunclub/spring-boot-config-repo/application-dev.yml",
"source":{
"test":"配置中心的配置信息"
}
}
]
}
http请求地址和资源文件映射如下:
pom.xml添加依赖1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- spring cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
配置文件
创建bootstrap.yml
文件,切记,是bootstrap.yml
文件bootstrap.yml
文件,我就因为写到了application.yml
这个里面,各种出现问题啊,添加如下配置:1
2
3
4
5
6
7spring:
cloud:
config:
name: application
profile: dev
label: master
uri: http://localhost:8888/
application-dev.yml
对应 application-dev.yml
对应启动测试
先添加一个获取配置信息的类:1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* @author chihiro.zhang
*/
public class DemoConfiguration {
private String test;
}
找个地方随便调用一下,输出这个test,就会打印上面git里面配置的信息了,爽不!
1 | spring: |
当时这个uri
配置的是公司的git仓库,公司的git仓库访问是需要开代理才能有权限访问的,代理也开了,可是一直报错:
1 | Whitelabel Error Page |
很郁闷,不知道为啥,可是就在刚刚,就刚刚,写博客的时候,有测试了一下,通了。。。。日了狗了,不知道啥原因,等研究出来了再来补充。
bootstrap.yml
里面uri
默认会调用端口为8888
的地址http://localhost:8888/
label
和uri
,profile
配置,profile
可以在启动参数添加,profile
也可以加在application.yml
添加name
也可以加在application.yml
添加 配置中心服务端:https://gitee.com/qianxunclub/qianxunclub-springboot-config
配置git仓库:https://gitee.com/qianxunclub/qianxunclub-springboot-config
配置客户端使用:https://gitee.com/qianxunclub/qianxunclub-starter-demo
客户端主要配置在:https://gitee.com/qianxunclub/qianxunclub-starter-parent/tree/master/qianxunclub-starter-config
新建了一个项目,我自己的服务器安装了一个redis,安装的时候,基本上都是默认参数,然后SpringBoot配置如下:
1 | spring: |
在项目启动的时候,报错:
1 | Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'redisTemplate' defined in class path resource [com/qianxunclub/starter/redis/autoconfigure/RedisConfig.class]: Unsatisfied dependency expressed through method 'redisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConnectionFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/redis/RedisAutoConfiguration$RedisConnectionConfiguration.class]: Invocation of init method failed; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR This instance has cluster support disabled |
从报错误的信息ERR This instance has cluster support disabled
很明显看得出来,是没有启动redis集群功能,可是我项目配置的集群的配置方式,要么修改代码为单机配置,要么修改redis为集群方式。
1、可以修改配置为单机redis配置:
1 | spring: |
2、在安装redis的目录找到redis配置文件redis.conf
,里面会找到配置:1
# cluster-enabled yes
把注释去掉就可以了
1 | cluster-enabled yes |
SpringBoot咱们开发一般pom.xml
是都集成spring-boot-starter-parent
的,这里为什么要自定义一个starter-parent呢,主要以下几个理由:
其实好处挺多的,谁用谁知道。
源码地址:https://gitee.com/qianxunclub/qianxunclub-starter-parent
源码依赖公用包:https://gitee.com/qianxunclub/framework-common
qianxunclub-starter-parent
里面已经开发好的几个插件,需要依据公司真实环境修改配置
源码地址:1
git clone https://gitee.com/qianxunclub/qianxunclub-starter-parent.git
因为qianxunclub-starter-parent
依赖了另一个framework-common
工具包,所以要下载该包源码并且编译:1
git clone https://gitee.com/qianxunclub/framework-common.git
1 | cd framework-common |
1 | mvn clean install |
本starter已包含一下功能:
POM需要依赖父级qianxunclub-starter-parent
:1
2
3
4
5<parent>
<groupId>com.qianxunclub</groupId>
<artifactId>qianxunclub-starter-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
继承该依赖,无需再引用spring-boot-starter-parent
,本项目已经继承的spring-boot-starter-parent
版本为1.5.9.RELEASE
。
1 | qianxunclub-demo |
1 | app: |
1 | <!-- 日志配置信息 --> |
profiles需要引入配置:
1 | spring: |
自定义配置:
1 | logging: |
以下为缺省配置:
1 | logging: |
日志默认存放目录:/logs/项目分组/项目名称/日志文件
如果没有项目分组:/logs/项目名称/日志文件
只需要在类上面添加@Slf4j
注解,即可使用log
对象打印日志
1 |
|
1 | <!-- 自动生成接口文档 --> |
swagger默认是不启用的,必须添加一下配置,才可以开启配置
1 | app: |
@EnableSBCSwagger
注解,开启接口1 |
|
启动项目成功后,访问API接口地址,例如:http://localhost:8080/swagger-ui.html。
1 | <!-- MYSQL配置信息 --> |
引入mysql配置:
1 | spring: |
添加数据源信息:
1 | app: |
端口默认为:3306
数据库密码加密:
1 | java -cp druid-1.1.6.jar com.alibaba.druid.filter.config.ConfigTools your_password |
以上配置完成后即可使用mysql以及MybatisPlus,该starter已封装部分常用数据库操作,方法如下:
MybatisPlus使用说明:http://mp.baomidou.com/#/?id=%e7%ae%80%e4%bb%8b
1、Entity规范
数据库对应的Entity需要继承BaseEntity
,如下:
1 |
|
2、Param规范
Param为入参查询常用发放,Param需要继承BaseParam
,如下:
1 |
|
3、Mapper规范
需要添加@Mapper
注解,继承BaseMapper
,并且要指定Entity泛型,如下:
1 |
|
4、Dao规范
需要继承BaseDao
,并且指定泛型,如下:
1 |
|
5、mapper.xml规范
默认可以不添加mapper.xml,如果遇到特定的SQL,可在resources
资源目录添加mapper文件夹,并添加对应的XML即可
1 | <!-- MYSQL配置信息 --> |
引入mysql配置:
1 | spring: |
添加redis配置信息:
1 | spring: |
端口默认为:6379
下面为缺省配置:
1 | spring: |
在类中可直接注入RedisTemplate
或StringRedisTemplate
即可使用,例如:
1 |
|
1 | <!-- 支持跨域请求 --> |
profiles需要引入配置:
1 | spring: |
pom.xml:
1 | <modelVersion>4.0.0</modelVersion> |
application.yml:
1 | app: |
完!
]]>