分布式软件系统基础介绍

标签:

本文出自jvm123.com-java技术分享站:http://jvm123.com/2019/12/fen-bu-shi-ruan.html

分布式应用

多个软件应用服务协作,共同对外提供服务。

实际开发中,这些应用一般在内网中,每个应用各司其职。

每个应用服务可能存在多个实例。

应用之间的调用RPC:

分布式软件系统基础介绍插图

协议

1 webservice

基于http,使用soap协议

2 http

直接通过http调用

3 dubbo

直接使用单一tcp长连接

调用feign:

  • 通过调用接口中定义的方法,就可以实现RPC远程调用
  • 可自定义翻译器、编码器、解码器、http客户端
/**
 * @author yawn http://jvm123.com
 * 2019/12/1 11:13
 */
public interface SearchClient {

    @RequestLine("GET /post/s/{wd}")
    List<PostVo> search(@Param("wd") String wd);

    @RequestLine("POST /post/s")
    @Headers("Content-Type: application/json")
    List<PostVo> search(@Param("t") String t, @Param("c") String c);

}
package com.jvm123.blog.config

import com.jvm123.blog.client.FeignRequestInterceptor
import com.jvm123.blog.client.HttpFeignClient
import feign.Feign
import feign.gson.GsonDecoder
import feign.gson.GsonEncoder
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

import com.jvm123.blog.client.SearchClient

/**
 *
 * @author yawn http://jvm123.com
 *     2019/10/30 14:46
 */
@Configuration
class FeignConfig {

    @Value('${feign.host}')
    String host = "https://api.jvm123.com"

    @Bean
    SearchClient searchClient() {
        return Feign.builder()
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .requestInterceptor(new FeignRequestInterceptor())
                .client(new HttpFeignClient())
                .target(SearchClient.class, host)
    }
}


/**
 * 自己实现的客户端
 * @author yawn http://jvm123.com
 * 2019/12/3 9:52
 */
public class HttpFeignClient implements Client {

    @Override
    public Response execute(Request request, Request.Options options) throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpRequestBase httpRequest = new HttpRequestBase() {
            @Override
            public String getMethod() {
                return request.method();
            }
        };
        try {
            httpRequest.setURI(new URI(request.url()));
        } catch (URISyntaxException ignored) { }
        CloseableHttpResponse httpResponse = httpClient.execute(httpRequest);
        HttpEntity entity = httpResponse.getEntity();
        byte[] body = EntityUtils.toByteArray(entity);
        Response response = Response.builder()
                .body(body)
                .headers(new HashMap<String, Collection<String>>())
                .status(httpResponse.getStatusLine().getStatusCode())
                .build();
        return response;
    }
}

应用通信:

消息中间件:jms规范

topic模式:publish/subscribe

queue模式:producer/consumer (send/onMessage)

应用管理及组件:

注册中心:redis、eureka、zookeeper

网关:

配置中心:

监控、日志:zipkin、logstash

负载均衡:客户端负载均衡ribbon(Server,IRule),服务端的nginx配置upstream

常用分布式服务器

数据库:cassandra,mysql,redis,mongodb

搜索服务器:elasticsearch

消息中间件:kafka

目标:高可用、没有单点故障。通常通过以下方法实现

多节点(nodes)

多节点,故障自动切换。

节点越多,可用性越高。

但在节点有限的情况下,可通过分片和副本技术实现。

分片(shards)

存储数据时,将数据按照一定的规则存储在不同的分片上,这就需要在查询时也能很快找到该数据所在的分片。一般可使用以下方法:

shard = hash(routing) % number_of_shards

routing为数据的唯一标识,一般是id。过程类似于根据key寻找hashmap节点所在的bin。

分布式软件系统基础介绍插图(1)

副本

将分片复制,作为副本存储,一般副本不存储在与主分片相同的节点上

特点总结

  • 多节点、多副本、分片存储
  • 各分片和副本分片均匀分布在各个节点上
  • 原数据主分片和副本分片存储在不同的节点上
http://jvm123.com/wp-content/uploads/2019/11/elas-head.jpg

分布式锁

主流实现方式:redis、zookeeper

redis: setnx key value expr 100ms

zookeeper:

/**
 *  1.客户端连接zookeeper,并在/lock下创建临时的且有序的子节点,
 * 第一个客户端对应的子节点为/lock/***-lock-0000000000,第二个
 * 为/lock/***-lock-0000000001,以此类推。
 *  2.客户端获取/lock下的子节点列表,判断自己创建的子节点是否为
 * 当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则
 * 监听刚好在自己之前一位的子节点删除消息,获得子节点变更通知
 * 后重复此步骤直至获得锁;
 *  3.执行业务代码;
 *  4.完成业务流程后,删除对应的子节点释放锁。
 *
 *  此锁能保证公平性,非公平锁的实现可参考:
 * @see ZkLock2Controller
 */
private void buyWithLock() throws Exception {
    //创建分布式锁, 锁空间的根节点路径为/lock
    InterProcessMutex lock = new InterProcessMutex(curator, "/lock");
    lock.acquire();
    //获得了锁, 进行业务流程
    buy();
    //完成业务流程, 释放锁
    lock.release();
}

分布式事务

XA两阶段提交、事务最终一致

最终一致事务使用消息中间件实现:消息中间件 onMessage 确认机制,自动确认、手动确认、批量确认、单条确认

eg:添加用户后,需要初始化用户的积分,因为用户和积分在不同的服务中,所以需要进行分布式的事务。

分布式软件系统基础介绍插图(3)

增加事件(event)表,定时处理事件,如下:

分布式软件系统基础介绍插图(4)

发表评论