iyihua

  • 首页

  • 标签

  • 分类

  • 归档

[使用spring-boot+spring-cloud一步步搭建微服务架构]一-开始一个spring-boot应用

发表于 2016-07-11 | 更新于 2019-05-22 | 分类于 java-spring

一. 目标愿景

我们的目标是:使用spring boot + spring cloud一步步搭建微服务架构
本系列demo项目githu地址:
https://github.com/YihuaWanglv/lannisi

1. 都说服务化,以前我们是怎么搭建soa服务的?之前的架构有什么未达理想?

之前,一个比较流行的soa服务化方案是dubbo/dubbox+zookeeper,配上spring boot。
这个方案是比较流行的方案之一,但是有几点未达理想的地方:

  • 1) dubbo的性能并不如一些其他服务化开发工具,比如thrift和ice。
  • 2) dubbo是一个RPC的半完善解决方案,中规中矩,配套的软件基础设施不全。问题定位、熔断和监控方面的问题让人没有那么的放心。
  • 3) 服务提供者和消费者都需要使用xml文件配置,不优雅。

2. 为什么使用Spring Cloud ?

Spring Cloud 提供了一整套分布式服务开发的工具,带着一些问题,我们希望在spring could中寻找答案。
Spring Cloud有什么特点?

  • 1) 集成了springboot与docker,用起来很方便。配置中心,服务中心,服务,客户端等等组件开启,都非常的简单,往往只需几行代码。
  • 2) 提供了一整套分布式服务开发的工具,从边缘服务的Zuul,到服务发现Eureka ,再到hystrix 熔断机制,是一套完整的生态。特别是hystrix,提供了完整的熔断机制,可以很轻易的引入现有系统。
  • 3) Spring Cloud有一个不好的地方是,实际编码会有侵入性。

3. 为什么使用spring boot?

  • 1) spring boot有pivotal和netfix背书,是一套完整的企业级应用的开发方案,天然集成分布式云架构spring-cloud。
  • 2) spring-boot的完全抛弃以往java项目配置文件过多的“陋习”,开启一个项目只需几行代码。
  • 3) Sprinboot允许项目使用内嵌的tomcat像启动普通java程序一样启动一个web项目.由于有了这个特性,项目不再需要打war包部署到tomcat,而是打成jar包,直接使用java -jar命令启动.

二. 开始第一个springboot项目

在一切开始之前,我们首先要知道如何开始一个springboot项目。

1. 创建一个空的maven项目,pom.xml中添加maven依赖

1
2
3
4
5
6
7
8
9
10
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

2. 编写项目启动入口App.java

1
2
3
4
5
6
7
@SpringBootApplication
public class App
{
public static void main(String[] args) throws Exception {
SpringApplication.run(App.class, args);
}
}

ok! done!
这样就已经能直接使用spring boot了.
启动App.java,spring boot就会使用内置的tomcat直接在本机的8080端口开启一个服务。

3. 再进一步,为应用引入spring mvc

1
2
3
4
5
6
7
8
9
10
11
@Controller
public class SampleController {


@RequestMapping("/")
@ResponseBody
String home() {
String data = "";
return "Hello World!";
}
}

启动App.java,访问localhost:8080, 即可遇见“Hello World!”

helloword项目也可参照:https://github.com/YihuaWanglv/lannisi 下的boot-sample-helloword项目。
https://github.com/YihuaWanglv/lannisi/tree/master/boot-sample-helloword

使用RAP作为接口管理和调试的工具

发表于 2016-07-08 | 更新于 2019-05-22 | 分类于 tools

一、为什么使用RAP?

  • 接口定义和管理,传统的方式是使用word文档。但word文档管理接口文档有不少问题。
    比如,word文档在相互传递的过程中,可能会导致彼此文档版本不一致;word文档难以结构化的集中维护各项目的文档,而且编写麻烦;word文档的接口定义功能单一,仅仅提供文档功能。

  • 而是用RAP作为接口文档定义管理的工具,则为我们提供了以下功能:
    1.可以按团队和项目结构化的管理接口文档。
    2.提供统一方便的接口定义方式。
    3.为前端提供mock数据,以便在后端没有开发好后端接口前,提前根据接口进行开发。
    4.校验后端提供的接口的数据格式和字段是否符合要求。

虽然RAP在自动化测试方面功能还有欠缺,仍不失为接口管理一个十分方便的工具。

二、RAP安装部署

1.下载RAP

在RAP的github主页上下载最新版本war包

2.环境准备

需要tomcat和mysql

3.部署

RAP在tomcat中要使用ROOT的方式部署。

  • 把下载好的war包放入tomcat的webapps目录下,然后删除tomcat中webapps目录下原先的ROOT文件夹,重命名war包为ROOT.war
  • 在mysql中建立rap_db数据库,导入RAPgithub代码中提供的sql脚本初始化数据库
  • 启动tomcat
  • 访问http://localhost:8080/

三、RAP的使用

1.注册账号

RAP自带账号管理和登陆功能,使用前先注册账号,登陆即可

2.添加团队、项目产品线等。

  • 创建团队
  • 创建产品线

3.分组和项目管理


4.添加模块和页面

5.添加接口

6.为返回值字段设置自定义的mock数据


我们可以为不同的字段自定义不同的mock数据,已适应实际需要。

7.前端使用接口mock数据提前进行开发


这个例子中的“项目根路径”:localhost:8080/mockjs/1
就是这个mock服务的模拟服务路径
前端访问:http://localhost:8080/mockjs/1/client/machine/activate?drive_id=sfd&activate_code=sdf&mac_address=sdf
就是访问我们模拟的接口地址: /client/machine/activate

[dev][collect][2016-06]collect-of-dev

发表于 2016-07-07 | 更新于 2019-05-22 | 分类于 collect

2016-06

2016-06-24

  • 【直播全文记录】 从零开始搭建高可用IM系统
    http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=206924771&idx=1&sn=4705b832c410765a3c89acfa1300b0b6&scene=21#wechat_redirect

  • 如何设计类似微信的多终端数据同步协议 | Grouk实践分享
    http://chuansong.me/n/1718596

2016-06-22

  • 基于Dubbo框架构建分布式服务
    http://shiyanjun.cn/archives/1075.html

  • 高并发性能调试经验分享
    https://zhuanlan.zhihu.com/p/21348220

  • Java进阶(三)多线程开发关键技术
    http://www.jasongj.com/java/multi_thread/

  • blog kafka
    http://www.jasongj.com/tags/Kafka/

  • 如何构建Android MVVM应用程序
    http://www.jianshu.com/p/2fc41a310f79

  • 超详细React Native实现微信好友/朋友圈分享功能-Android/iOS双平台通用
    http://www.lcode.org/%E8%B6%85%E8%AF%A6%E7%BB%86react-native%E5%AE%9E%E7%8E%B0%E5%BE%AE%E4%BF%A1%E5%A5%BD%E5%8F%8B%E6%9C%8B%E5%8F%8B%E5%9C%88%E5%88%86%E4%BA%AB%E5%8A%9F%E8%83%BD-androidios%E5%8F%8C%E5%B9%B3%E5%8F%B0/

  • SHELL编程之常用技巧
    http://mp.weixin.qq.com/s?__biz=MzIxNDMyODgyMA==&mid=2247483698&idx=1&sn=3b52493d202362aae0bf511002e63d52

  • 让你爱上写作的 11 款 Markdown 工具
    http://www.ifanr.com/app/665209

  • 基于Docker搭建Hadoop集群之升级版
    http://kiwenlau.com/2016/06/12/160612-hadoop-cluster-docker-update/

  • Kafka设计解析(一)- Kafka背景及架构介绍
    http://www.jasongj.com/2015/03/10/KafkaColumn1/

2016-06-15

  • 淘拍拍前端架构2.0-简介
    http://www.w3cfuns.com/notes/25101/33114eae47bbda0c50fb67eeb4a7fd6c.html

  • 轻松监控上万台服务器:企业运维监控平台架构设计与实践指南
    http://dbaplus.cn/news-21-466-1.html

  • Mesos+Zookeeper+Marathon+Docker分布式集群管理最佳实践
    http://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650755658&idx=1&sn=9f5e4831b2c27d66e4296c49ffcd3d7c&scene=21#wechat_redirect

  • 网易蜂巢微服务架构:用RabbitMQ实现轻量级通信
    http://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650755639&idx=2&sn=0e43c1b7168dbcd60582326fb20f2f19&scene=21#wechat_redirect

  • 使用Vue.js从零构建GitHub项目浏览器
    http://xlbd.me/vue-demo-github-file-explorer/

2016-06-07

  • 搭建Git服务器
    http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137583770360579bc4b458f044ce7afed3df579123eca000

  • gitlab centos一键安装
    http://blog.csdn.net/asd131531/article/details/42374285
    http://www.linuxidc.com/Linux/2014-08/105137.htm

在单服务器上安装部署FastDFS+Nginx

发表于 2016-07-07 | 更新于 2019-05-22 | 分类于 deploy

在单服务器上安装部署FastDFS+Nginx

那么多服务器和软件安装配置中,FastDFS算是比较复杂的一个了。
这个例子storage和tracker均部署在同一台服务器(ip:192.168.1.134)
我部署的服务系版本是centos6.7

FastDFS安装配置

Tracker的安装及配置

1.安装编译器

1
yum install -y gcc gcc-c++

2.下载安装libevent

1
2
3
4
5
wget https://sourceforge.net/projects/levent/files/libevent/libevent-2.0/libevent-2.0.22-stable.tar.gz
tar xvzf libevent-2.0.22-stable.tar.gz
cd libevent-2.0.22-stable
./configure
make && make install

3.下载安装fastDFS

1
2
3
4
5
6
wget http://code.google.com/p/fastdfs/downloads/detail?name=FastDFS_v4.06.tar.gz
(code.google.com已无法访问,可以自己手动下载再上传到服务器)
tar -xvzf FastDFS_v4.06.tar.gz
cd FastDFS
./make.sh
./make.sh install

安装成功后/usr/local/bin下会出现一系列fastDFS命令

4.配置tracker

1
vim /etc/fdfs/tracker.conf

修改base_path以存储tracker信息(这里不做修改,使用默认路径/home/yuqing/fastdfs,需要先行创建目录)

5.启动tracker

1
/usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf

Storage配置 -> Storage1配置

正常情况下storage1部署一个服务器,storage2部署一个服务器,tracker部署一个服务器。
我这里只部署一个storage一个tracker,并部署在同一个服务器

1~3:参考Tracker安装步骤

4.配置storage

1
vim /etc/fdfs/storage.conf

修改tracker_server=192.168.1.134:22122
修改base_path以存储storage信息(这里不做修改,使用默认路径/home/yuqing/fastdfs,需要先行创建目录)
例子:

1
2
3
4
5
group_name=group1
base_path=/home/yuqing/fastdfs
store_path0=/home/yuqing/fastdfs
tracker_server=192.168.1.134:22122
http.server_port=8080 #web server的端口改成8080(与nginx 端口一致)

5.启动storage

1
/usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf

启动过程中,fastDFS会在base_path下的data目录中创建一系列文件夹,以存储数据

安装nginx以及fastdfs-nginx-module模块

nginx的rewrite模块和cache模块需要先安装pcre和openssl

安装pcre

下载pcre

1
2
3
4
5
tar zxvf pcre-8.12.tar.gz
cd pcre-8.12
./configure
make
make install

安装openssl

centos下解决办法:

1
yum -y install openssl openssl-devel

安装nginx

1
2
3
4
5
6
cd /home/yihua
wget http://nginx.org/download/nginx-0.8.55.tar.gz
tar zxvf nginx-0.8.55.tar.gz
cd nginx-0.8.55
./configure --prefix=/opt/nginx --with-http_stub_status_module
make && make install

安装fastdfs-nginx-module

下载并上传fastdfs-nginx-module_v1.15.tar.gz

1
2
3
4
tar xzf fastdfs-nginx-module_v1.15.tar.gz
cd /home/yihua/nginx-0.8.55
./configure --add-module=/home/yihua/fastdfs-nginx-module/src
make; make install

配置nginx和fastdfs-nginx-module

1
2
cp /home/yihua/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs
vim /etc/fdfs/mod_fastdfs.conf

修改 fastdfs的nginx模块的配置文件 mod_fastdfs.conf
一般只需改动以下几个参数即可:

1
2
3
4
5
6
7
8
9
base_path=/home/yuqing/fastdfs      #保存日志目录
tracker_server=192.168.1.134:22122 #tracker 服务器的 IP 地址以及端口号
storage_server_port=23000 #storage 服务器的端口号
group_name=group1 #当前服务器的 group 名
url_have_group_name = true #文件 url 中是否有 group 名
store_path_count=1 #存储路径个数,需要和 store_path 个数匹配
store_path0=/home/yuqing/fastdfs #存储路径
http.need_find_content_type=true # 从文件 扩展 名查 找 文件 类型 ( nginx 时 为true)
group_count = 1 #设置组的个数

然后在末尾添加分组信息,目前只有一个分组,就只写一个

1
2
3
4
5
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/home/yuqing/fastdfs

建立 M00 至存储目录的符号连接

1
ln -s /home/yuqing/fastdfs/data /home/yuqing/fastdfs/data/M00

将 server 段中的 listen 端口号改为 8080:

1
2
vim /usr/local/nginx/conf/nginx.conf
listen 8080;

在 server 段中添加fastdfs的配置

1
2
3
4
location /group1/M00 {
root /home/yuqing/fastdfs/data;
ngx_fastdfs_module;
}

准备nginx启动脚本

编辑 /etc/init.d/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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/bin/bash
# nginx Startup script for the Nginx HTTP Server
# it is v.1.4.7 version.
# chkconfig: - 85 15
# description: Nginx is a high-performance web and proxy server.
# It has a lot of features, but it's not for everyone.
# processname: nginx

# pidfile: /usr/local/nginx/logs/nginx.pid
# config: /usr/local/nginx/conf/nginx.conf

nginxd=/usr/local/nginx/sbin/nginx
nginx_config=/usr/local/nginx/conf/nginx.conf
nginx_pid=/usr/local/nginx/logs/nginx.pid
nginx_lock=/var/lock/subsys/nginx
RETVAL=0
prog="nginx"

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -x $nginxd ] || exit 0

# Start nginx daemons functions.
start() {
nginx_is_run=`ps -ef | egrep 'nginx:\s*(worker|master)\s*process' | wc -l`
if [ ${nginx_is_run} -gt 0 ];then
echo "nginx already running...."
exit 1
fi
echo -n $"Starting $prog: "
daemon $nginxd -c ${nginx_config}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch ${nginx_lock}
return $RETVAL
}

# Stop nginx daemons functions.
stop() {
echo -n $"Stopping $prog: "
killproc $nginxd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${nginx_lock} ${nginx_pid}
}

# Reload nginx config file
reload() {
echo -n $"Reloading $prog: "
#kill -HUP `cat ${nginx_pid}`
killproc $nginxd -HUP
RETVAL=$?
echo
}

# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
stop
start
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $prog {start|stop|restart|reload|status|help}"
exit 1
esac

Nginx启动提示找不到libpcre.so.1解决方法
如果是32位系统

1
ln -s /usr/local/lib/libpcre.so.1 /lib

如果是64位系统

1
ln -s /usr/local/lib/libpcre.so.1 /lib64

启动nginx

1
2
3
4
5
6
7
# chmod u+x /etc/init.d/nginx
# chkconfig --add nginx
# chkconfig nginx on
# service nginx start
正在启动 nginx: [确定]
# service nginx status
nginx (pid 26500) 正在运行...

查看nginx的日志 错误日志logs/error.log 看是否有问题

其他

启动nginx,tracker和storage

重启tracker:
/usr/local/bin/restart.sh /usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf
重启storage:
/usr/local/bin/restart.sh /usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf
启动nginx:
/usr/local/nginx/sbin/nginx
检查nginx状态:
/usr/local/nginx/sbin/nginx -t
重启nginx:
/usr/local/nginx/sbin/nginx -s reload

tracker运行

直接使用 fdfs_trackerd 来启动tracker进程,然后使用netstat 查看端口是否起来。

1
2
3
4
[root@tracker fdfs]# fdfs_trackerd /etc/fdfs/tracker.conf restart
[root@tracker fdfs]# netstat -antp | grep trackerd
tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 14520/fdfs_trackerd
[root@tracker fdfs]#

storage运行

1
2
3
4
# fdfs_storaged /etc/fdfs/storage.conf restart
查看端口是否起来
# netstat -antp | grep storage
tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 10316/fdfs_storaged

也可以以下命令来监控服务器的状态

1
# fdfs_monitor /etc/fdfs/client.conf

看到ACTIVE,就说明已经成功注册到了tracker。

开机启动

设置tracker开机自动启动

1
2
3
4
5
6
7
8
9
10
[root@tracker tracker]# echo "/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart" >> /etc/rc.local
[root@tracker tracker]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
[root@tracker tracker]#

设置storage开机启动

1
2
3
4
5
6
7
8
9
[root@server1 fdfs]# echo "/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart" >> /etc/rc.local
[root@server1 fdfs]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

使用client测试文件上传

先配置一下client
vi /etc/fdfs/client.conf
保证一下配置:

1
2
3
base_path=/home/yuqing/fastdfs
tracker_server=192.168.1.134:22122
http.tracker_server_port=8080

vi test.txt

/usr/local/bin/fdfs_test /etc/fdfs/client.conf upload test.txt
得到:

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
This is FastDFS client test program v4.06

Copyright (C) 2008, Happy Fish / YuQing

FastDFS may be copied only under the terms of the GNU General
Public License V3, which may be found in the FastDFS source kit.
Please visit the FastDFS Home Page http://www.csource.org/
for more detail.

[2016-07-06 07:31:57] DEBUG - base_path=/home/yuqing/fastdfs, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0

tracker_query_storage_store_list_without_group:
server 1. group_name=, ip_addr=192.168.1.134, port=23000

group_name=group1, ip_addr=192.168.1.134, port=23000
storage_upload_by_filename
group_name=group1, remote_filename=M00/00/00/wKgBhld9Fl2ATSOYAAAAB9mqc8s085.txt
source ip address: 192.168.1.134
file timestamp=2016-07-06 07:31:57
file size=7
file crc32=3651826635
file url: http://192.168.1.134:8080/group1/M00/00/00/wKgBhld9Fl2ATSOYAAAAB9mqc8s085.txt
storage_upload_slave_by_filename
group_name=group1, remote_filename=M00/00/00/wKgBhld9Fl2ATSOYAAAAB9mqc8s085_big.txt
source ip address: 192.168.1.134
file timestamp=2016-07-06 07:31:57
file size=7
file crc32=3651826635
file url: http://192.168.1.134:8080/group1/M00/00/00/wKgBhld9Fl2ATSOYAAAAB9mqc8s085_big.txt
[root@localhost yihua]# This is FastDFS client test program v4.06
-bash: This: command not found
Copyright (C) 2008, Happy Fish / YuQing

在浏览器打开http://192.168.1.134:8080/group1/M00/00/00/wKgBhld9Fl2ATSOYAAAAB9mqc8s085.txt
可以看见你的文件。那么就成功了。

done.

项目管理建议

发表于 2016-07-01 | 更新于 2019-05-22 | 分类于 manager

对项目管理制度的一些看法和建议

当前存在的问题

  1. 技术工程师反映,技术人员与业务隔离,技术人员难以熟悉第一手业务需求,对工程师开发出契合业务部分需求的产品造成一定的理解障碍。

  2. 安卓、iOS、H5、后端、测试等各部门分而治之,缺乏一个强而有力的统筹推进,虽然增加了项目经理角色,但目前这个角色只能在各部门之间协调,仍然难以有力推动各部门按时按量完成进度。

  3. 从业务到产品到开发到测试上线,这个流程还可以有优化的地方。

分析和改进建议

针对问题1。

使用尝试让项目经理或者技术经理在产需求研和产品评审阶段就参与介入,能够一定程度的和业务部分做到沟通,让技术人员更熟悉业务。即使只是旁听也好

针对问题2。

程序界有一句话,“没有完美的模型,但有一些能用。”
既然目前公司的情况是各部分分而治之,各施其职,那么可以考虑这样一个构思,产品对业务负责,提供产品的产出;测试则对产品负责,提供项目和模块完成情况;技术经理对项目经理负责,提供项目模块开发时间评估,以及开发产出;各开发工程师对技术经理负责,按时按量完成技术经理制定的模块开发计划。而项目经理则对项目的进度和协调负责,应该要有渠道能对接所有相关部门,跟进项目的进度,协调各方遇到的问题,并协助解决。
这样,明确各部门应该对谁负责,各部门遇到项目开发相关问题,也就能明确的找到相应的人员,得到反馈,部门之间也能够相互推动。

这里推荐使用一个团队协作管理的工具:“Worktile”。
Worktile可以在一个看板中看到所有在做、已完成、在测试等等所有流程中的任务和完成情况。
例如,技术经理可以列出所有需要完成的模块和任务,为之分配负责人。负责人开发完成后,勾选完成,管理人员就可以拖动任务进入测试流程。
如此一个可视化简单的团队协作管理。
当然这个功能,像禅道也能部分实现。但是禅道的这个功能并不好用,从实践经验来说,使用的人积极性并不高。而Worktile这类工具如果推动成功,开发的管理效率将会得到提高。

各状态任务完成情况一览:

完成任务,推动到另一状态:

报表:

团队日历:每个时间点要完成的任务也会在此显示

针对问题3.

以门店收银机为例,发现存在一些流程上的问题。
首先,说接口,有两个问题。
一,客户端和服务端接口文档,用的是word文档沟通,各个人员直接相互传递,很可能导致相互之间接口文档不同步,也就会造成开发期间关于接口的一些扯皮。
二,虽然接口文档有了,但是客户端还是要等服务端出接口后,才能进行接口接入后的相关开发,这样前端的进度就要依赖于后端的产出。
既然有这样的问题,那么有没有改进办法呢?有的,这里推荐使用阿里开源的“RAP”接口管理工具进行接口管理。
RAP对我们接口开发的帮助有:
1)可视化结构化的接口编辑和管理。这样接口只有服务器上的一份,并且管理简单。
2)生成Mock数据、校验真实接口的正确性。有了Mock功能,前端可以在后端提供接口之前,利用rap提供的模拟接口数据,提前进行接口接入的开发,提高前端开发速度。最重要的是,前后端接口开发解耦。

其次,说说测试和螺旋式开发。
测试本身是一个发现细节的过程,有些问题测试到细节的地方,就会出现值得推敲和不断调试的情况。而我们项目留给测试的时间太少了。而前期,没完成之前,测试在等待开发,同时,最后所有模块大致完成才提测,又一股脑挤在后期测试和迭代,时间难免太紧,很容易导致进度延误。
这里的建议是,开发应该在项目开始时就梳理出模块间的依赖情况,前后端协调好应该先开发哪些模块,只要有一个模块开发完成,就马上提测。如此让测试尽早介入测试,达到项目螺旋式迭代推荐的目的。同时,也能让测试的时间合理分配,避免延误。

[api_version]4种在springmvc中进行api版本控制的处理方法

发表于 2016-06-28 | 更新于 2019-05-22 | 分类于 version

https://github.com/mindhaq/restapi-versioning-spring.git
https://github.com/augusto/restVersioning.git

这两个git项目里提供了4种在springmvc中进行api版本控制的处理方法,你们看怎么样,能否不使用冗余部署的方式。

  1. /api/v1/xxx
    controller中的方法注解写法:

    1
    2
    3
    4
    5
    @ResponseBody
    @RequestMapping(value = "/apiurl/{version}/hello", method = GET, produces = APPLICATION_JSON_VALUE)
    public Hello sayHelloWorldUrl(@PathVariable final ValidVersion version) {
    return new Hello();
    }
  2. /api/xxx
    在header中添加”X-API-Version”:”v1”来进行版本请求的区别
    controller中的方法注解写法:

    1
    2
    3
    4
    5
    @ResponseBody
    @RequestMapping(value = "/apiheader/hello", method = GET, produces = APPLICATION_JSON_VALUE)
    public Hello sayHelloWorldHeader(@RequestHeader("X-API-Version") final ValidVersion version) {
    return new Hello();
    }
  3. /api/xxx
    在header中添加Accept: “application/vnd.company.app-v1+json”来进行版本区别
    controller中的方法注解写法:

    1
    2
    3
    4
    5
    @ResponseBody
    @RequestMapping(
    value = "/apiaccept/hello", method = GET,
    produces = {"application/vnd.company.app-v1+json", "application/vnd.company.app-v2+json"}
    )
  4. /api/xxx
    在header中添加Accept: “application/vnd.company.app-v1+json”来进行版本区别
    controller写法:
    `
    @Controller
    @VersionedResource(media = “application/vnd.app.resource”)
    public class TestController {

    @RequestMapping(value = {“/resource”}, method = RequestMethod.GET)
    @VersionedResource(from = “1.0”, to = “1.0”)
    @ResponseBody
    public Resource getResource_v1() {

    return new Resource("1.0");
    

    }

    @RequestMapping(value = {“/resource”}, method = RequestMethod.GET)
    @VersionedResource(from = “2.0”)
    @ResponseBody
    public Resource getResource_v2_onwards() {

    return new Resource("2.0");
    

    }
    }

[dev][collect][2016-06-06]collect-of-im-netty-android-etc

发表于 2016-06-06 | 更新于 2019-05-22 | 分类于 collect

此集合[dev][collect]汇总开发资源.
资源含文章,git code等等..

2016-06-06

  • 一套仿 微信 IM系统 基于apache mina
    http://my.oschina.net/u/1167637/blog/411312

  • socketio 服务器推送
    http://blog.csdn.net/xtayfjpk/article/details/40948409

  • 开放源码,基于springMVC+springSecurity3.x+Mybaits3.x的权限系统,,支持开源
    https://github.com/caprice/lanyuan

  • Simple asynchronous non blocking chat server/client based on Netty 4
    https://github.com/caprice/nettychat
    https://github.com/YihuaWanglv/nettychat

  • [5][android]A High Copy WeChat ,SNS APP (高仿微信)
    https://github.com/YihuaWanglv/wechat

  • 一个Android开发者博客
    http://blog.csdn.net/finddreams

  • 案例剖析:从0开始搭建一个微服务的持续交付系统
    http://mp.weixin.qq.com/s?__biz=MzA5Nzc4OTA1Mw==&mid=2659597380&idx=1&sn=e0087759e6b65df0ba30126c1e3af915&scene=0#wechat_redirect

  • [5][android]这是一个可用于Android快速开发的框架,集成了很多项目中通用的东西,免去重复造轮子的麻烦,直接下载来了,修改一下就可以做为基础的框架进行开发,提高开发速度,适合当前移动互联网时代敏捷快速开发的节奏
    https://github.com/YihuaWanglv/Android_BaseLib

  • 使用Netty实现IMServer,方便的Entity解码编码机制,融合到二进制协议中
    https://github.com/YihuaWanglv/netty-chat

  • 仿淘宝的B2C商城项目
    页面用的jsp,稍显陈旧
    https://github.com/YihuaWanglv/B2CWeb

  • JavaEE项目开发脚手架
    https://github.com/YihuaWanglv/es
    后端:
    IoC容器 spring
    web框架 springmvc
    orm框架 hibernate + spring data jpa
    安全框架 shiro
    验证框架 hibernate validator
    任务调度框架 quartz
    缓存 ehcache
    数据源 druid
    日志 slf4j+logback
    Json fastjson
    日期美化 prettytime
    servlet 3.0(需要支持servlet3的servlet容器,如tomcat7)
    jcaptcha 验证码
    jsp 模板视图
    前端:
    jquery js框架
    jquery-ui-bootstrap界面框架
    font-wesome 字体/图标框架
    jquery Validation Engine 验证框架(配合spring的验证框架,页面验证简化不少)
    kindeditor 编辑器
    nicescroll 漂亮的滚动条
    zTree 树框架
    jquery blockUI 弹出框/遮罩框架
    jquery-fileupload 文件上传
    bootstrap-datatimepicker 日历选择

  • [5][android]Collect and classify android open source projects
    https://github.com/YihuaWanglv/android-open-project

  • Blog avec Spring MVC + spring DATA + mongodb + angularjs
    https://github.com/YihuaWanglv/blog_java

  • dianping-api-samples
    https://github.com/YihuaWanglv/dianping-open-sdk

  • JeeSite 是一个企业信息管理系统基础框架,Java EE(J2EE)快速开发框架,使用经典技术组合(Spring、Spring MVC、Apache Shiro、Hibernate、Bootstrap UI),包括核心模块如:组织机构、用户、权限授权、内容管理、工作流等。
    https://github.com/YihuaWanglv/jeesite

  • Demos of Apache MINA User Guide《Apache MINA 2 用户指南》中文翻译,文中用到的例子源码 https://github.com/waylau/apache-mina-2.x-user-guide
    https://github.com/waylau/apache-mina-2-user-guide-demos

  • Spring Framework 4.x Reference Documentation 中文翻译
    https://www.gitbook.com/book/waylau/spring-framework-4-reference/details
    https://github.com/waylau/spring-framework-4-reference

  • 免费的计算机编程类中文书籍
    https://github.com/YihuaWanglv/free-programming-books-zh_CN
    网页版:
    http://siberiawolf.com/free_programming/index.html

  • 一个合格的程序员应该读过哪些书
    http://justjavac.com/other/2012/05/15/qualified-programmer-should-read-what-books.html

  • Google 全球 IP 地址库
    https://github.com/justjavac/Google-IPs

  • 一份关于“资料汇总”的汇总
    https://github.com/YihuaWanglv/awesome-awesomeness-zh_CN

  • Freely available programming books
    https://github.com/YihuaWanglv/free-programming-books

  • RESTful API 设计参考文献列表,可帮助你更加彻底的了解REST风格的接口设计
    https://github.com/aisuhua/restful-api-design-references

  • ssential Netty in Action 《Netty 实战(精髓)》
    https://github.com/waylau/essential-netty-in-action
    gitbook:
    http://waylau.com/essential-netty-in-action/

  • Gradle 2 User Guide 中文翻译《Gradle 2 用户指南》
    https://github.com/waylau/Gradle-2-User-Guide
    gitbook:
    https://www.gitbook.com/book/waylau/gradle-2-user-guide/details

  • Netty 4.x User Guide 中文翻译《Netty 4.x 用户指南》
    https://github.com/waylau/netty-4-user-guide
    gitbook:
    http://waylau.com/netty-4-user-guide/

  • 这是一个整理即时通讯(IM)和社交系统(SNS)优秀开源项目的文档,项目上传github欢迎提交更新
    https://github.com/YihuaWanglv/Perfect_IM_SNS

  • 基于位置信息,空间时间结合的社交与分享的应用
    https://github.com/YihuaWanglv/Tuyi

  • SYTeamApp:基于环信平台进行开发,旨在打造的高效团队沟通的移动客户端,供企业内部协作使用、适应移动办公需要,提升企业沟通协同效率,增强企业办公管理效率。(当前仅实现了用户登入登出功能、通讯功能、投票功能。)
    https://github.com/YihuaWanglv/SYTeamApp

  • MeifuGO:An open source android app by using easemob IM SDK
    https://github.com/YihuaWanglv/MeifuGO

  • fangyuanshili:环信SDK,IM,geohash,lbs
    https://github.com/YihuaWanglv/fangyuanshili

  • zaina:该项目是改编自环信即时通讯云的demo改编
    https://github.com/YihuaWanglv/zaina

  • dianhua:基于react native 和 环信的实时通话的免费店话
    https://github.com/YihuaWanglv/dianhua

  • Baby:一个私密社交APP
    https://github.com/YihuaWanglv/Baby

  • MVPCommon:一个集成了众多开源项目的Android MVP框架以及应用搭建,全程博客更新。
    a common Architecture and project build with blogs releasing based on MVP,integrates many Open Source Projects ,to make your developing quicker and easier.
    https://github.com/YihuaWanglv/MVPCommon
    从零开始搭建android框架系列:
    http://www.jianshu.com/notebooks/3767449/latest

  • learnCloud:
    和应用服务器、存储服务器说再见
    再也不用租服务器,也不用写后端代码了。LeanCloud 提供一站式后端云服务,从数据存储、实时聊天、消息推送到移动统计,涵盖应用开发的多方面后端需求。
    https://leancloud.cn/

  • 不容错过,最全的安卓架构合集【从零开始搭建android框架系列(2)】
    http://www.jianshu.com/p/1f21e1d375aa

  • 安卓架构文章合集(a collection of android Architecture)
    https://github.com/YihuaWanglv/AndroidArchitectureCollection

[git]git分支使用和管理

发表于 2016-06-06 | 更新于 2019-05-22 | 分类于 git

git分支常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
从master创建dev分支,并checkout dev分支:
git checkout -b dev
此命令相当于:
git branch dev
git checkout dev

回到master,合并dev的更改到master:
git checkout master
git merge dev
合并后删除dev分支:
git branch -d dev

如果直接用git merge dev合并分支,git使用的是fast forward的模式,并不会留下commit历史,如果想要留下commit历史,就要加上--no-ff参数,并使用-m添加commit描述
git merge --no-ff -m "merge with no-ff" dev

保存临时状态

当你正在dev分支进行开发,还没有开发完成能提交,此时突然有一个线上版本的bug要紧急修复,这个时候你就需要用到git stash功能,保存正在开发的dev分支的状态

1
2
3
4
5
6
7
8
保存当前开发状态:
git stash

查看当前已保存的stash列表:
git stash list

取出之前保存的stash状态:
git stash pop

多人协作的工作模式

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
多人协作的工作模式通常是这样:

首先,可以试图用git push origin branch-name推送自己的修改;

如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

如果合并有冲突,则解决冲突,并在本地提交;

没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!

如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name。

这就是多人协作的工作模式,一旦熟悉了,就非常简单。

小结

查看远程库信息,使用git remote -v;

本地新建的分支如果不推送到远程,对其他人就是不可见的;

从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;

在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;

建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;

从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。

Windows下开启React-Native征途

发表于 2016-06-04 | 更新于 2019-05-22 | 分类于 javascript

我们的目标是星辰大海(说白了就是同一个东西咱不想Android做一份,iOS又做一份),现在我们要开启React-Native的征途(在Windows下)。
不过说出来你可能不太相信,这故事的开头,来的并没有想象中的困难。

以下是过程:

1. 安装Nodejs

React Native要求是4.0以上。

2. 安装react-native-cli

1
npm install -g react-native-cli

3. 初始化第一个项目

1
react-native init TestProject

初始化第一个测试Demo,init的时候可能需要一点时间. 伟大的目标值的那么些耐心的等待。

4. 设置环境变量

设置环境变量ANDROID_HOME指向Android SDK的目录
eg:

5. 安装Genymotion模拟器

Genymotion官网下载安装Genymotion模拟器,并创建Android emulator。
创建实例后,将得到如下画面:

Genymotion运行Android模拟实例需要VirtualBox和AndroidSdk的支持。
安装Genymotion后默认的VirtualBox和AndroidSdk不好使,我通过Setting设置配置好自己本地的VirtualBox和AndroidSdk。
设置VirtualBox

设置sdk

配置好后,就把模拟的Android实例启动起来放着吧。

6. 启动

1-启动React Native Server

1
react-native start

2-开一个新的命令行终端(cmd), 切换到项目目录安装APP

1
2
cd android
gradlew.bat installDebug

执行gradlew.bat installDebug时,需要先正常打开Genymotion模拟器,否则build 和 install会报错。

安装成功后,在Genymotion里手动打开APP ,正常的话,你就可以看到React-Native的欢迎画面。

Windows下的React Native开发环境搭建 – done.

[Jenkins自动化部署实践]Jenkins多环境部署git托管的springboot项目

发表于 2016-06-01 | 更新于 2019-05-22 | 分类于 deploy

[Jenkins自动化部署实践]Jenkins多环境部署git托管的springboot项目

目标

场景

Jenkins部署在服务器192.168.1.119:8080.
有一个在git托管的springboot构建的web项目,项目有n个依赖的父模块,现在想要把这个项目部署到服务器192.168.1.134上.
现在,我们需要使用Jenkins自动化部署实现这个目标.

为什么是springboot?

Sprinboot允许项目使用内嵌的tomcat像启动普通java程序一样启动一个web项目.由于有了这个特性,项目不再需要打war包部署到tomcat,而是打成jar包,直接使用java -jar命令启动.

如何实现?

1-需要在jenkins上建立n个maven项目打包任务,项目有多少个依赖的父模块,就建多少个。build。
2-建立目标项目的maven打包项目。build。
3-建立一个自由软件风格任务,作用是使用shell脚本,登录到目标服务器192.168.1.134,执行134上的shell脚本,从Jenkins所在的服务器cp目标jar包,拉取打包好的jar到134,然后启动jar。

实现步骤

下面是具体操作

1-需要在jenkins上建立n个maven项目打包任务,项目有多少个依赖的父模块,就建多少个。build。

由于要区分不同的部署环境,所以这里先建一个dev环境的项目组

建立maven打包任务,为项目所依赖的父模块建立编译打包任务
主要填好项目任务名称和项目git地址即可

2-建立目标项目的maven打包项目。build。

由于我们要实现不同部署环境区分不同配置,所以我们需要对项目做些额外的工作
首先在maven pom中添加profiles设置。我这里添加了3个环境local,dev和prod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<env>local</env>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<env>prod</env>
</properties>
</profile>
</profiles>

然后,添加maven-resources-plugin插件,这个插件会为我们复制生成三个环境的配置文件目录。

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
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-prod-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<!-- this is important -->
<overwrite>true</overwrite>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<outputDirectory>target/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources/${env}</directory>
<targetPath></targetPath>
</resource>
</resources>
<testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
</configuration>
</execution>
</executions>
</plugin>

这样就会在resources目录下生成三个不同环境的目录和配置文件

如果是cli命令行下,我们就可以使用mvn install -P$env命令打包不同环境的配置
如dev环境就是mvn install -Pdev

但是我们现在不是命令行,而是使用Jenkins做编译打包。
于是,添加的Jenkins任务,除了任务名称和git地址外,还需要额外多一个配置。
在“Build”标签下,填写“goals and options”字段,值为“clean install -Pdev”。
-Pdev表示我们要打的正是dev环境的配置

3-建立一个自由软件风格任务,作用是使用shell脚本,登录到目标服务器192.168.1.134,执行134上的shell脚本,从Jenkins所在的服务器cp目标jar包,拉取打包好的jar到134,然后启动jar。

由于我们需要执行远程服务器上的shell脚本,所以我们必须要让Jenkins知道远程服务器的ssh登录方法。
要让Jenkins能登录服务器做远程任务,我们需要在全局配置中配置好“SSH remote host”。

然后配置一个执行远程shell脚本的任务,如下图。

这个脚本很简单,只是设置好要登录的服务器,在shell中进入shell脚本所在目录,直接执行目标脚本。
而拉取jar包并更新启动springboot项目的任务则有远程脚本所承包了。

任务脚本例子:
这个shell脚本主要做了几件事:
1)使用sshpass和scp从119服务器远程复制打包好的jar包回来134,备份,再复制到项目定好的目标路径
2)kill关闭原java进程
3)使用nohup java -jar ${target_path}/${target_jar} < /dev/null > ${target_bak_path}/${now}/itime-${now}.log 2>&1 &
启动java程序,并把日志输出到指定的log文件。
4)检查java程序是否启动成功。

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
#!/bin/bash
# script to update and restart project itimes
remote_source_path=/root/.jenkins/workspace/dev-timeitem-itimes/target
target_jar=itimes-1.0.0-SNAPSHOT.jar
target_path=/usr/local/itimes
target_bak_path=/usr/local/itimes_bak

now=$(date '+%Y%m%d%H%M%S')
echo "update and restart project itimes start..."
echo "now time: ${now}"

mkdir -p ${target_bak_path}/${now}
/usr/bin/sshpass -p "root" scp root@192.168.1.119:${remote_source_path}/itimes-1.0.0-SNAPSHOT.jar ${target_bak_path
}/${now}

cd $target_bak_path/$now
if [ -f ${target_jar} ]; then
pkill -f 'java.*itimes'
sleep 3
temppid=$(ps aux | grep java| grep "${target_jar}" | grep -v grep | awk '{ print $2}')
if [[ "$temppid" != "" ]]; then
echo "temppid is ${temppid}"
ps -ef | grep ${target_jar} | grep -v grep | awk '{print $2}' | xargs kill
fi
echo "kill ${target_jar} done.."
cd $target_path
if [ -f ${target_jar} ]; then
rm -f ${target_jar}
echo "target_jar deleted.."
else
echo "${target_jar} not exist, go on to copy.."
fi
cp ${target_bak_path}/${now}/${target_jar} ${target_path}
echo "cp done!"
chmod 755 ${target_jar}
nohup java -jar ${target_path}/${target_jar} < /dev/null > ${target_bak_path}/${now}/itime-${now}.log 2>&1 &
echo "app startting.."
for i in 2 4 6 10; do
sleep $i
echo "wait and check app starting up..."
APP_PID=`ps aux | grep java| grep "${target_jar}" | grep -v grep | awk '{ print $2}'`
if [ $APP_PID > 0 ]; then
break;
else
echo "app is still starting up..."
fi
done
pid=$(ps aux | grep java| grep "${target_jar}" | grep -v grep | awk '{ print $2}')
echo "app id is: ${pid}"
if [ $pid ]; then
echo "${target_jar} is running now!"
else
echo "${target_jar} is not running! ${target_jar} startup failed!"
fi
success_flag="false"
for i in 2 4 6 8 10 12; do
echo "checking app startup status..."
success_target_tag=`cat ${target_bak_path}/${now}/itime-${now}.log | grep "Started App in"`
if [[ "" != "$success_target_tag" ]]; then
echo "Found success target tag, app startup successfully.."
success_flag="true"
break;
else
echo "app is still starting up..."
sleep $i
echo "sleep $i ..."
fi
done
if [[ "true" != "$success_flag" ]]; then
echo "Not found success target tag, app startup failed..."
fi
else
echo "Target jar not exist! Update not complete!"
fi

echo "update done!"

done.

1…567…9
Wanglv Yihua

Wanglv Yihua

82 日志
20 分类
206 标签
RSS
© 2019 Wanglv Yihua
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Muse v6.4.1