java服务中间件之旅(一):dubbo入门

前言

说起来这应该是博主的第一篇博客,平时博主一直都有记录笔记的习惯,都是以记录核心知识点的形式进行记录。工作几年,越发觉得分享自己的观点对于自身以及团队的成长是多么的关键,于是开始动手写这第一篇博客,也希望自己能够坚持下去。markdown语法用得不对,排版有问题请多包涵,也多提建议。文章本身的观点有不同看法,也尽情拍砖。
接下来的一段时间应该会使用较多的中间件,今天先来一篇最简单的dubbo入门,预告下一次的博客主题为“dubbo项目实践”,如果有时间,可能会自己尝试去实现一个简单的java中间件。废话不多说,开始我们今天的dubbo入门!

后端服务架构演化过程:

Paste_Image.png

针对某项目的架构演化过程:

项目架构演进过程中,给我感受最深的一点:所有项目演化过程其实都是大同小异,但最重要的是,去思考在什么阶段采用什么架构是最合适的,并在项目中去运用、解决实际的问题

  • 最初的单war包单服务器项目

    最简单的项目,所有的业务都在一个项目中,数据库,tomcat等都在同一台服务器上,采用session进行用户权限验证(并不是指session不好😄),文件保存在tomcat/nginx下

  • 项目业务的拆分
    随着业务发展,原有的架构出现了瓶颈,生产环境对app的项目要求稳定,但运营端的版本迭代速度明显要快于app,再在同一个java项目里对新版本部署带来很多麻烦,于是业务相关不大的项目就进行了拆分:运营端/app/销售项目/h5活动等等

  • 数据库/缓存/文件系统的拆分

    这个比较简单,就简单说下,无非是将其它的一些共用服务从原有的部署服务器上抽调出去,比如rds,七牛云等

  • 前后端分离

    前后端分离的事贯穿全程,从最初的jsp + form + iframe 到 ajax 横空出世,再到后面各种mvc/mvvm框架(angularjs, avalonjs等), 直到目前的前端nodejs代理层(也许不仅仅是代理层)

  • 通过maven将代码组件化

    整合大量公用代码,并将通用的服务从繁重的业务项目中独立出去。比如xxx(某不愿意透露姓名的互联网项目)项目中的im、通知中心、定时计划等服务

  • 进行读写分离与集群

    尽量减少分布式服务中的单点服务,提高服务的稳定性与性能。并对数据库进行读写分离。

  • 通过服务中间件进行服务优化

    今日的主题,通过dubbo来对架构变得更加立体化,提高稳定性,提升服务质量,提升代码维护的效率。

dubbo服务简介

官方服务文档:

[http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-%E8%83%8C%E6%99%AF][1]

非常详细,阅读前提:spring、redis / zookeeper、maven 等有一定的了解

dubbo服务架构

Paste_Image.png

节点说明:

  • Provider: 暴露服务的服务提供方,即接口的实现者
  • Consumer: 调用远程服务的服务消费方。 即客户端,调用接口方
  • Registry: 服务注册与发现的注册中心。 服务注册中心,大多由zookeeper来实现(我们的demo也主要围绕zookeeper注册中心来讲
    ps:redis的注册中心超难用,文档demo非常少)
  • Monitor: 统计服务的调用次调和调用时间的监控中心。 非必需,dubbo有自带一个dubbo-admin 项目可用
  • Container: 服务运行容器。 包括但不限于jboss / tomcat / jetty
    等,甚至是轻量级的服务,可通过main方法启动。

参考文章:http://www.cnblogs.com/ghj1976/p/5316126.html

dubbo服务优点

  • 像调用内部接口一样调用远程服务(再也不用该死的httpclient和难用的webservice了)
  • 接口调用的负载均衡机制:轮询、随机、权重等
  • 容灾机制:某个server挂了,还有其它的server。就算是注册中心挂了,内部的缓存仍然有效(比如某个接口由xxx.xx.xx.xx这台服务器提供服务,这个信息会缓存着)
  • 通过心跳机制动态的注册/使用服务
  • 与spring高度集成,使用方便
  • 接口版本号控制

开始我们的dubbo之旅

demo代码:

git@git.oschina.net:jianli/dubbo-demo.git

先来看下项目结构:

Paste_Image.png

dubbo-api 在此demo中作为公用的接口项目,包括接口,请求参数,与返回类
dubbo-server 作为服务生产者,提供服务(实现接口)
dubbo-custom 作为服务消费者,使用服务(调用接口)

项目代码我就不全贴了,git 上有,现在讲一下最基本的流程,以helloworld开始

1.安装启动zookeeper

ftp://ftp.kddilabs.jp/infosystems/apache/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz

下载后解压

配置zookeeper的主要配置文件:
zoo.cfg:

tickTime=2000
dataDir=/Users/lijian/Desktop/1.4.0
clientPort=2181

通过bin/zkServer.sh start启动

导入项目

git clone

不多说

3.启动dubbo-server项目。

先看主要配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
        http://code.alibabatech.com/schema/dubbo    http://code.alibabatech.com/schema/dubbo/dubbo.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
        
        <context:component-scan
            base-package="com.lijian.**" />
  
        <context:annotation-config />
    
    <!-- 公共信息,也可以用dubbo.properties配置 -->
    <dubbo:application name="lalocal-server"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
     <dubbo:protocol name="dubbo" port="-1"/>
    <!-- 扫描注解包路径,多个包用逗号分隔,不填pacakge表示扫描当前ApplicationContext中所有的类 -->
    <dubbo:annotation package="com.lijian.dubbo.service" />
    </beans>

主要指定了应用名,注册中心地址,dubbo协议端口号(-1为自动分配,之后细讲),和注解扫描路径

编写接口的实现类

    package com.lijian.dubbo.service.impl;
    import com.alibaba.dubbo.config.annotation.Service;
    import com.lijian.dubbo.service.HelloService;
    @Service
    public class HelloServiceImplv1 implements HelloService{
    
        public String hello(String name) {
            return "Hello, "+name;
        }
    
    }

十分简单,注意Service是dubbo的注解,不是spring的Service

然后启动spring容器,最简单的,通过main方法启动:

public class MainZookeeperClass {
    @SuppressWarnings("resource")
    public static void main(String[] args){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        context.start();
        System.out.println("服务已经启动...");
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        } // 按任意键退出
    }
}

4. 启动dubbo-custom项目

主要配置文件:

 <dubbo:application name="test-client"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <dubbo:annotation package="com.lijian.dubbo.customer" />
    </beans>

比较简单,不多说

接口的引用UserAction:

package com.lijian.dubbo.customer.action;

import org.springframework.stereotype.Component;

import com.alibaba.dubbo.config.annotation.Reference;
import com.lijian.dubbo.service.HelloService;

@Component
public class UserAction {

    @Reference
    HelloService helloService;
    
    public String say(String a){
        return helloService.hello(a + a);
    }
}

主要是@Reference的注解

启动Main方法:

public class MainClass {
    public static void main(String[] args){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        context.start();
        
        UserAction userAction = context.getBean(UserAction.class);
        String a = userAction.say("user ");
        System.out.println(a);
        
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        } // 按任意键退出
    }
}

控制台输出:

Paste_Image.png

5. 搭建dubbo服务的监控中心

从git 上下载dubbo-admin项目
https://github.com/alibaba/dubbo.git

dubbo-admin是一个web项目,需要使用web容器,jboss,tomcat都可以,方便起见,我们使用jetty

dubbo-admin 默认连接本地的2181端口,默认有root和guest两个帐号。这里我们采用默认的配置, 如果要改的话,改动/dubbo-admin/src/main/webapp/WEB-INF/dubbo.properties文件

启动dubbo-admin:

mvn jetty:run

然后登陆127.0.0.1:8080 去查看

至此,一个最简单的dubbo服务已经完成。回顾一下dubbo的服务架构,注册中心,生产者,消费者,容器,监控中心都有了😊。

下一篇博客,将为大家带来dubbo的实战讲解,讲我在dubbo中遇到的一些坑,以及常用的业务场景

推荐阅读更多精彩内容