原文地址:http://www.cnblogs.com/skyblog/p/5535418.html

Spring cloud适应于云端服务,也适用于企业信息化SOA建设。spring boot也是restful微服务开发的利器。但对于内网服务,即服务与服务之间的调用,spring并没有去刻意封装,也许他们认为已经没有必要了,因为已经有了thrift、ice等强大的框架。

如果是用spring boot本身提供的restful服务作为服务与服务之间的调用,效率低很多,thrift的效率大概是restful的100-1000倍左右。本篇既是基于spring boot框架,结合thrift和zookeeper实现的一个简单微服务框架,服务与服务之间使用thrift通信(thrift既是通信方式也是数据压缩方式)。

本demo一共包括三个工程:

cloud-thrift-server:服务提供方

cloud-thrift-interface:接口及传输对象定义

cloud-thrift-client:服务调用方

开源代码地址:http://git.oschina.net/zhou666/spring-cloud-7simple

1)建立thrift接口定义文档

namespace java cloud.simple.service

struct UserDto {

1: i32 id

2: string username

}

service UserService {

UserDto getUser()

}

接口定义完后,使用thrift命令生成对应的java文件,主要生成两个文件,分别是UserService.java和UserDto.java,把这两个文件放入cloud-thrift-interface工程,因为客户端也需要这个接口定义。

2)实现thrift服务注册

在服务的提供端需要实现接口,并且还要把实现类注册到thrift服务器。

    UserService.Processor processor = new UserService.Processor(

                       new UserServiceImpl());

         TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(

                       tServerTransport()).processor(processor));

UserServiceImpl就是接口实现类,将其注册金Tserver。

注册完服务后,需要启动Tserver,很显然这个需要在线程里启动。

    executor.execute(new Runnable() {

                @Override

                public void run() {

                       tServer().serve(); 

                }

    });

3) 使用zookeeper进行服务名称注册

上面是注册具体的服务执行类,这一步是将服务的实例注册进zookeeper,这样才能实现负载均衡。让客户端可以根据服务实例列表选择服务来执行。当然这里只需要注册服务所在服务器的IP即可,因为客户端只要知道IP,也就知道访问那个IP下的该服务。

String servicePath = "/"+serviceName ;// 根节点路径

       ZkClient zkClient = new ZkClient(serverList);

       boolean rootExists = zkClient.exists(servicePath);

       if (!rootExists) {

           zkClient.createPersistent(servicePath);

       }

       InetAddress addr = null;

       try {

           addr = InetAddress.getLocalHost();

       } catch (UnknownHostException e) {

           e.printStackTrace();

       }

       String ip = addr.getHostAddress().toString();

       String serviceInstance = System.nanoTime() +"-"+ ip;

       // 注册当前服务

       zkClient.createEphemeral(servicePath + "/" + serviceInstance);

       System.out.println("提供的服务为:" + servicePath + "/" + serviceInstance);

要注意这里使用zkClient.createEphemeral建立临时节点,如果这台服务器宕机,这个临时节点是会被清除的,这样客户端在访问时就不会再选择该服务器上的服务。

4) 客户端更新服务列表

客户端需要能及时的监听服务列表的变化并作出负载均衡,我们用如下方式监听服务列表的变化:

 // 注册事件监听

         zkClient.subscribeChildChanges(servicePath, new IZkChildListener() {

                // @Override

                public void handleChildChange(String parentPath,

                              List<String> currentChilds) throws Exception {

                       // 实例(path)列表:当某个服务实例宕机,实例列表内会减去该实例

                       for (String instanceName : currentChilds) {

                              // 没有该服务,建立该服务

                              if (!serviceMap.containsKey(instanceName)) {

                                     serviceMap.put(instanceName,createUserService(instanceName));

                              }

                       }

                       for (Map.Entry<String, UserService.Client> entry : serviceMap.entrySet()) {

                              // 该服务已被移除

                              if (!currentChilds.contains(entry.getKey())) {

                                     serviceMap.remove(entry.getKey());

                              }

                       }

                       System.out.println(parentPath + "事件触发");

                }

    });

有了服务列表,客户端在调用服务的时候就可以采用负载均衡的方式了,在这里使用最简单的随机方式:

  public UserService.Client getBalanceUserService(){       

         Map<String, UserService.Client> serviceMap =ZooKeeperConfig.serviceMap;

         //以负载均衡的方式获取服务实例           

         for (Map.Entry<String, UserService.Client> entry : serviceMap.entrySet()) {

                System.out.println("可供选择服务:"+entry.getKey());

         }

         int rand=new Random().nextInt(serviceMap.size());           

         String[] mkeys = serviceMap.keySet().toArray(new String[serviceMap.size()]);

         return serviceMap.get(mkeys[rand]);

  }

本文结束,具体参见代码,另外,之前还不了解thrift和zookeeper的朋友,不要被他们吓到,其实他们是很轻量级的技术,很容易上手,这也许就是他们流行的原因。

spring boot和thrift、zookeeper建立微服务的更多相关文章

  1. 使用Ratpack和Spring Boot打造高性能的JVM微服务应用

    使用Ratpack和Spring Boot打造高性能的JVM微服务应用 这是我为InfoQ翻译的文章,原文地址:Build High Performance JVM Microservices wit ...

  2. 使用spring boot和thrift、zookeeper建立微服务

    Spring cloud适应于云端服务,也适用于企业信息化SOA建设.spring boot也是restful微服务开发的利器.但对于内网服务,即服务与服务之间的调用,spring并没有去刻意封装,也 ...

  3. 翻译-使用Ratpack和Spring Boot打造高性能的JVM微服务应用

    这是我为InfoQ翻译的文章,原文地址:Build High Performance JVM Microservices with Ratpack & Spring Boot,InfoQ上的中 ...

  4. Spring Boot (九): 微服务应用监控 Spring Boot Actuator 详解

    1. 引言 在当前的微服务架构方式下,我们会有很多的服务部署在不同的机器上,相互是通过服务调用的方式进行交互,一个完整的业务流程中间会经过很多个微服务的处理和传递,那么,如何能知道每个服务的健康状况就 ...

  5. SpringCloud微服务实战——搭建企业级开发框架(四十四):【微服务监控告警实现方式一】使用Actuator + Spring Boot Admin实现简单的微服务监控告警系统

      业务系统正常运行的稳定性十分重要,作为SpringBoot的四大核心之一,Actuator让你时刻探知SpringBoot服务运行状态信息,是保障系统正常运行必不可少的组件.   spring-b ...

  6. 基于Spring Cloud和Netflix OSS构建微服务,Part 2

    在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...

  7. Spring Boot同时开启HTTP和HTTPS服务

    由于Spring Boot中通过编码开启HTTPS服务比较复杂,所以官方推荐通过编码开启HTTP服务,而通过配置开启HTTPS服务. Spring Boot的application.yml中添加如下配 ...

  8. Spring Boot 2.X(十三):邮件服务

    前言 邮件服务在开发中非常常见,比如用邮件注册账号.邮件作为找回密码的途径.用于订阅内容定期邮件推送等等,下面就简单的介绍下邮件实现方式. 准备 一个用于发送的邮箱,本文是用腾讯的域名邮箱,可以自己搞 ...

  9. 今天介绍一下自己的开源项目,一款以spring cloud alibaba为核心的微服务架构项目,为给企业与个人提供一个零开发基础的微服务架构。

    LaoCat-Spring-Cloud-Scaffold 一款以spring cloud alibab 为核心的微服务框架,主要目标为了提升自己的相关技术,也为了给企业与个人提供一个零开发基础的微服务 ...

随机推荐

  1. The number of steps(概率dp)

    Description Mary stands in a strange maze, the maze looks like a triangle(the first layer have one r ...

  2. Linux 下 UltraEdit 版本 破解 30 天试用限制

    原创 http://yhz61010.iteye.com/blog/2319599 rm -rfd ~/.idm/uex rm -rf ~/.idm/*.spl rm -rf /tmp/*.spl 一 ...

  3. mysql table status

    SHOW TABLE STATUS 能获得表的信息 可以SHOW TABLE STATUS where name='表名'

  4. unused import statement android studio 解决方法

    解决方法:“file”-->“invalidate caches/restart” 解决 感谢大神的解答

  5. JNI基础学习

    1.JNI(Java Native Interface): 它允许Java代码和其他语言写的代码进行交互,JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要 ...

  6. boost::Circular Buffer

    boost.circular_buffer简介 很多时候,我们需要在内存中记录最近一段时间的数据,如操作记录等.由于这部分数据记录在内存中,因此并不能无限递增,一般有容量限制,超过后就将最开始的数据移 ...

  7. jmeter 请求发送加密参数

    最近在做http加密接口,请求头的uid参数及body的请求json参数都经过加密再发送请求,加密方式为:ase256.所以,jmeter发送请求前也需要对uid及json参数进行加密.我这里是让开发 ...

  8. NOI2013部分题解

    Day 1 T1:向量内积 直接暴力有60.发现将n个向量合成$n\times d$的矩阵$A$,然后求$A\times A^T$,得到的矩阵包含了所有的答案. 先考虑$k=2$,将答案矩阵和全1矩阵 ...

  9. [COGS2479 && COGS2639]高维偏序(CDQ分治,bitset)

    COGS2479:四维偏序. CDQ套CDQ CDQ:对a分治,对b排序,再对a打标记,然后执行CDQ2 CDQ2:对b分治,对c归并排序,对d树状数组. #include<cstdio> ...

  10. 【后缀数组】【线段树】poj3974 Palindrome

    考虑奇数长度的回文,对于字符串上的每个位置i,如果知道从i开始的后缀和到i为止的前缀反转后的字符串的lcp长度的话,也就知道了以第i个字符为对称中心的最长回文的长度了.因此,我们用在S中不会出现的字符 ...