为了账号安全,请及时绑定邮箱和手机立即绑定

如何零基础搭建一套微服务框架(二)

标签:
Java Bootstrap

原标题:如何零基础搭建一套微服务框架(Spring Boot + Dubbo + Docker + Jenkins)

续前文:如何零基础搭建一套微服务框架(一)

6. 自动化构建

Jenkins是一个自动化构建工具,它可以帮助我们摆脱繁琐的部署过程,我们只需要在一开始配置好构建策略,以后部署只需要一键完成。

6.1 创建Jenkins容器

Jenkins采用Java开发,也需要Java环境,但我们使用Docker后,一切都采用容器化部署,Jenkins也不例外。

  • 拉取镜像
    这里我们使用Jenkins官方提供的镜像,大家只需执行如下命令拉取即可:
    docker pull docker.io/jenkins/jenkins
  • 启动容器
    由于Jenkins运行在Tomcat容器中,因此我们将容器的8080端口映射到宿主机的10080端口上:
    docker run --name jenkins -p 10080:8080 docker.io/jenkins/jenkins
  • 初始化Jenkins
    然后你需要访问IP:10080,Jenkins会带着你进行一系列的初始化设置,你只要跟着它一步步走就行了,比较傻瓜式。
    6.2 在Jenkins中创建项目

接下来我们要做的是,在Jenkins中为每一个服务创建一个项目,每个项目中定义了构建的具体流程。由于我们将整个项目分成了6个微服务,所以我们需要在Jenkins中分别为这6个服务创建项目。那句开始吧~

  • 点击页面左侧的“新建”按钮:

图片描述

  • 输入项目名称gaoxi-user,选择“构建一个Maven项目”,然后点击“OK”:

图片描述

  • 配置Git仓库
    选择Git,然后输入本项目Git仓库的URL,并在Credentials中输入Git的用户名和密码,如下图所示:

图片描述

  • 构建触发器
    选择第一项,如下图所示:

图片描述

  • Pre Step
    Pre Step会在正式构建前执行,由于所有项目都依赖于Gaoxi-Common-Service—Facade,因此在项目构建前,需要将它安装到本地仓库,然后才能被当前项目正确依赖。 因此,在Pre Step中填写如下信息:

图片描述

  • Build
    然后就是正式构建的过程,填写如下信息即可:

图片描述

OK,Gaoxi-User的构建过程就配置完成了。当我们点击“立即构建”按钮时,Jenkins首先会从我们指定的Git仓库中拉取代码,然后执行Pre Step中的Maven命令,将Gaoxi-Common-Serivce-Facade打包安装到本地仓库。然后执行Build过程,将Gaoxi-User进行编译打包。 但此时Gaoxi-User仍然只是一个本地war包,并没有部署到Tomcat容器中,而我们采用了容器化部署后,Jenkins服务和Gaoxi-User服务并不在同一个Docker容器中,那么究竟该如何才能将Jenkins本地编译好的war包发送到Gaoxi-User容器中呢?这就需要使用Jenkins的一个插件——Deploy Plugin。

6.3 远程部署
  • 下载插件
    首先你需要下载Deploy Plugin,下载地址如下: https://wiki.jenkins.io/display/JENKINS/Deploy+Plugin
  • 安装插件
    在系统管理–>插件管理–>高级上传deploy.hpi进行安装。
  • 在父项目的pom文件中增加远程部署插件:
<plugin>
    <groupId>org.codehaus.cargo</groupId>
    <artifactId>cargo-maven2-plugin</artifactId>
    <version>1.6.5</version>
    <configuration>
        <container>
            <!-- 指明使用的tomcat服务器版本 -->
            <containerId>tomcat8x</containerId>
            <type>remote</type>
        </container>
        <configuration>
            <type>runtime</type>
            <cargo.remote.username>Tomcat的用户名</cargo.remote.username>
            <cargo.remote.password>Tomcat的密码</cargo.remote.password>
        </configuration>
    </configuration>
    <executions>
        <execution>
            <phase>deploy</phase>
            <goals>
                <goal>redeploy</goal>
            </goals>
        </execution>
    </executions>
</plugin>
  • 为Tomcat设置用户名和密码
    修改gaoxi-user容器中tomcat的tomcat-users.xml文件,增加tomcat的manager用户

图片描述

注意:如果你使用了chaimm/tomcat镜像,那么其中Tomcat配置都已经完成,默认用户名:admin、默认密码:jishimen2019。强烈建议修改用户名和密码。

  • 修改Jenkins中gaoxi-user的配置
    在“构建后操作”中增加如下配置:

图片描述

  • WAR/EAR files:表示你需要发布的war包
  • Containers:配置目标Tomcat的用户名和密码
7. Maven的profile功能

在实际开发中,我们的系统往往有多套环境构成,如:开发环境、测试环境、预发环境、生产环境。而不同环境的配置各不相同。如果我们只有一套配置,那么当系统从一个环境迁移到另一个环境的时候,就需要通过修改代码来更换配置,这样无疑增加了工作的复杂度,而且易于出错。但好在Maven提供了profile功能,能帮助我们解决这一个问题。

  • 父项目的pom中添加profile元素
    首先,我们需要在总pom的中添加多套环境的信息,如下所示:
<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <profileActive>dev</profileActive>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <profileActive>test</profileActive>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <profileActive>prod</profileActive>
        </properties>
    </profile>
</profiles>
- 父项目的pom中添加resource元素
resource标识了不同环境下需要打包哪些配置文件。
<resources>
    <resource>
        <!-- 标识配置文件所在的目录 -->
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <!-- 构建时将这些配置文件全都排除掉 -->
        <excludes>
            <exclude>application.properties</exclude>
            <exclude>application-dev.properties</exclude>
            <exclude>application-test.properties</exclude>
            <exclude>application-prod.properties</exclude>
        </excludes>
    </resource>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <!-- 标识构建时所需要的配置文件 -->
        <includes>
            <include>application.properties</include>
            <!-- ${profileActive}这个值会在maven构建时传入 -->
            <include>application-${profileActive}.properties</include>
        </includes>
    </resource>
</resources>
- 父项目的pom中添加插件maven-resources-plugin
该插件用来在Maven构建时参数替换
<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.0.2</version>
    <configuration>
        <delimiters>
            <delimiter>@</delimiter>
        </delimiters>
        <useDefaultDelimiters>false</useDefaultDelimiters>
    </configuration>
</plugin> 
  • 在子项目中创建配置
    分别为dev环境、test环境、prod环境创建三套配置,application.proerpties中存放公用的配置。

图片描述

  • 在application.properties中添加spring.profiles.active=@profileActive@
    spring.profiles.active=@profileActive@
  • 修改Jenkins的配置
    在所有Jenkins中所有Maven命令的末尾添加-P test,在打包的时候-P后面的参数将会作为@profileActive@的值传入系统中,从而根据该值打包相应的application-{profileActive}.properties文件。
    8. 开发流程

到此为止,所有准备工作都已经完成,接下来就可以进入代码开发阶段。下面我以一个例子,带着大家感受下有了这套微服务框架后,我们的开发流程究竟有了哪些改变?下面以开发一个用户登录功能为例,介绍下使用本框架之后开发的流程。

8.1 开发目标
  • 在Gaoxi-User系统中实现登录的业务逻辑,并发布成RPC服务
  • 在Gaoxi-Controller中远程调用登录服务,并向前端提供登录的REST接口

图片描述

8.2 开发登录服务

首先需要在Gaoxi-Common-Service-Facade中创建UserService接口,并在其中声明登录的抽象函数。

public interface UserService {

    public UserEntity login(LoginReq loginReq);
}

PS:为什么要将UserService放在Gaoxi-Common-Service-Facade中? 在这个项目中,Gaoxi-User是UserService服务的提供方,Gaoxi-Controller是UserService服务的引用方。由于二者并不在同一个系统中,所以必须要借助于Dubbo来实现远程方法调用。而Dubbo发布服务和引用服务的时候,都是根据服务的接口标识服务的,即服务引用方和发布方都需要使用服务的接口,因此需要将服务的接口放在所有项目共同依赖的基础模块——Gaoxi-Common-Service-Facade中。

然后在Gaoxi-User中开发UserService的实现——UserServiceImpl。 UserServiceImpl上必须要加上Dubbo的@Service注解,从而告诉Dubbo,在本项目初始化的时候需要将这个类发布成一项服务,供其他系统调用。

@Service(version = "1.0.0")
@org.springframework.stereotype.Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Override
    public UserEntity login(LoginReq loginReq) {

        // 校验参数
        checkParam(loginReq);

        // 创建用户查询请求
        UserQueryReq userQueryReq = buildUserQueryReq(loginReq);

        // 查询用户
        List<UserEntity> userEntityList = userDAO.findUsers(userQueryReq);

        // 查询失败
        if (CollectionUtils.isEmpty(userEntityList)) {
            throw new CommonBizException(ExpCodeEnum.LOGIN_FAIL);
        }

        // 查询成功
        return userEntityList.get(0);
    }
}
8.3 引用登录服务

当UserService开发完毕后,接下来Gaoxi-Controller需要引用该服务,并向前端提供一个登录的REST接口。 若要使用userService中的函数,仅需要在userService上添加@Reference注解,然后就像调用本地函数一样使用userService即可。Dubbo会帮你找到UserService服务所在的IP和端口号,并发送调用请求。但这一切对于程序猿来说是完全透明的。

@RestController
public class UserControllerImpl implements UserController {
    @Reference(version = "1.0.0")
    private UserService userService;

    @Override
    public Result login(LoginReq loginReq, HttpServletResponse httpRsp) {

        // 登录鉴权
        UserEntity userEntity = userService.login(loginReq);

        // 登录成功
        doLoginSuccess(userEntity, httpRsp);
        return Result.newSuccessResult();
    }
}
8.4 自动构建服务

上面的代码完成后,接下来你需要将代码提交至你的Git仓库。接下来就是自动化部署的过程了。

你需要进入Jenkins,由于刚才修改了Gaoxi-User和Gaoxi-Controller的代码,因此你需要分别构建这两个项目。 接下来Jenkins会自动从你的Git仓库中拉取最新的代码,然后依次执行Pre Step、Build、构建后操作的过程。由于我们在Pre Step中设置了编译Gaoxi-Common-Service-Facade,因此Jenkins首先会将其安装到本地仓库;然后再执行Build过程,构建Gaoxi-User,并将其打包成war包。最后将执行“构建后操作”,将war包发布到相应的tomcat容器中。 至此,整个发布流程完毕!

8.5 查看服务的状态

当Jenkins构建完成后,我们可以登录Dubbo-Admin查看服务发布和引用的状态。

当我们搜索UserService服务后,可以看到,该服务的提供者已经成功发布了服务:

图片描述

点击“消费者”我们可以看到,该服务已经被controller-consumer成功订阅:

图片描述

9. 总结

总结一下,这套框架有如下优势:

  1. 微服务架构
    我们借助于SpringBoot和Dubbo实现了微服务架构。微服务架构的理念就是将一个原本庞大、复杂的系统,按照业务功能拆分成一个个具有独立功能、可以独立运行的子系统,系统之间若有依赖,则通过RPC接口通信。从而最大限度地降低了系统之间的耦合度,从而更加易于扩展、更加易于维护。
  2. 容器化部署
    我们借助于Docker实现了容器化部署。容器能够帮助我们屏蔽不同环境下的配置问题,使得我们只需要有一个Dockerfile文件,就可以处处运行。和虚拟机一样,Docker也拥有环境隔离的能力,但比虚拟机更加轻量级,由于每个容器仅仅是一条进程,因此它可以达到秒级的启动速度。
  3. 自动化构建
    我们借助于Jenkins实现了所有项目的自动化构建与部署。我们只需要点击“立即构建”这个按钮,Jenkins就可以帮助我们梳理好错综复杂的项目依赖关系,准确无误地完成构建,并将war包发送到相应的web容器中。在启动的过程中,Dubbo会扫描当前项目所需要发布和引用的服务,将所需要发布的服务发布到ZooKeeper上,并向ZooKeeper订阅所需的服务。 有了Jenkins之后,这一切都是自动化完成。也许你并没有太强烈地感受到Jenkins所带来的便利。但是你想一想,对于一个具有错综复杂的依赖关系的微服务系统而言,如果每个服务的构建都需要你手动完成的话,你很快就会崩溃,你大把的时间将会投入在无聊但又容易出错的服务构建上。而Jenkins的出现能让这一切自动化完成。
    作者:序猿柴毛毛,原文地址
点击查看更多内容
4人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消