java笔记:分布式系统架构+RPC+Dubbo

分布式系统架构+RPC+Dubbo

分布式系统架构

分布式架构概述

分布式系统是建立在网络之上的软件系统,相对于一个系统只由一个程序组成的单体程序而言,分布式程序是由多个子系统程序组成的,并且这些子程序是相互联结且互相协作的.

分布式架构与单体架构的比较

单体

在这里插入图片描述

单体架构就是一个项目包含了整个项目的全部代码,包含了全部功能,通过包(package)区分各个模块

优点:部署简单,维护方便,成本低

缺点:当项目规模大、用户访问频率高、并发量大、数据量大时,会大大降低程序执行效率,甚至出现服务器宕机等情况。

适用项目:传统管理项目,小型互联网项目

分布式

在这里插入图片描述

分布式架构会把一个项目按照特定要求(多按照模块或功能)拆分成多个项目,每个项目分别部署到不同的服务器上。

优点:

1.增大了系统可用性。减少单点故障,导致整个应用不可用。

2.增加重用性。因为模块化,所以重用性更高。高内聚、低耦合。

3.增加可扩展性。有新的模块增加新的项目即可。

4.增加每个模块的负载能力。因为每个模块都是一个项目,所以每个模块的负载能力更强。

缺点:

1.成本更高。

2.架构更加复杂。

3.整体响应之间变长,一些业务需要多项目通信后给出结果。

4.吞吐量更大。吞吐量= 请求数/秒。

适用项目:中、大型互联网项目。客户多,数据多,访问并发高,压力大,吞吐量高.

问:分布式系统下,子项目之间如何互相协作?

答:RPC

RPC

PRC的概述

RPC:远程过程调用,在java中,就是调用其他服务器上部署的应用的方法.所以,在分布式架构下,分布在不同的服务器上的子节点程序之间,相互调用方法时,需要使用RPC来完成远程方法调用.

RPC架构组成

典型 RPC 的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,其中“RPC 协议”就指明了程序如何进行网络传输和序列化。

一次完整的RPC过程

在这里插入图片描述

1.客户端以本地调用的方式(接口的方式)发出服务请求

2.客户端存根收到调用的请求后,把方法、参数等组装成一个消息体(序列化成二进制)

3.消息体通过socket的方式从客户端socket发送到服务端socket

4.服务端socket收到消息体后,经过服务端存根解码(反序列化)

5.服务端存根将参数传递给服务端方法,并执行被调用的方法

6-10.执行完成后再把返回结果以同样的方式发回给客户端,

总结:RPC的目的就是把234789这些步骤封装起来.

问:在java实现RPC的方式?

答:dubbo

dubbo

dubbo的概述

dubbo是一款高性能的java RPC框架,作为RPC框架,提高性能的关键在于序列化和网络通信两个方面

dubbo的序列化

本地的对象要在网络上进行传输,必须序列化(实现Serializable接口),常用的序列化类型有java原生、xml、json、Hessian和二进制等,效率最高的就是二进制流(因为计算机就是二进制的),dubbo采用的就是二进制流.

dubbo的网络通信

相较于HTTP的7步走(三次握手,四次挥手),dubbo采用socket通信一步到位,提升了通信效率,并且支持长连接,不用反复连接直接传输数据

dubbo的特点

1.面向接口代理,为开发者屏蔽远程调用的底层细节,使用简单

2.多种负载均衡策略,智能负载均衡,减少调用延迟,提高系统吞吐量

3.支持多种注册中心服务,服务自动注册,实时感知服务上下线

4.运行期流量调度,支持灰度发布

5.高可扩展能力,平等对待内部实现和第三方实现

6.监控中心能够提供服务调用统计功能,提供可视化的管理和维护功能

dubbo中的角色

在这里插入图片描述

什么是服务提供者/消费者

远程调用过程必然有服务提供者和消费者,比如订单服务器提供订单服务,用户服务器使用订单服务,其中订单服务器是提供者,用户服务器是消费者.反之亦然.

所以在RPC中没有绝对的消费者和提供者,任何服务都能同时兼备消费者和提供者两个身份,并且绝大多数时候如此

什么是注册中心

假如我们有100台A服务器和100台B服务器,其中一台A想要调用B,这时候A怎么知道要调用哪一台B(总不可能每台A上都存储所有B的信息吧?)

这时候,我们就需要类似于婚介所的角色,这个地方存储了所有的信息(包含A和B),小伙找小姑娘可以随时问婚介所,反之亦然

实际注册中心就能根据负载策略来分配调用哪一台服务器,dubbo推荐使用 Zookeeper 注册中心

dubbo与springboot整合案例

0.安装并启动zookeeper

1.创建maven项目dubbodemo作为父项目

2.创建maven项目名api ,添加依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

创建提供方和消费方都需要调用的公共pojo和接口

package cn.ppl.api.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
}

package cn.ppl.api.service;

import cn.ppl.api.pojo.User;

public interface ProviderService {

    User setUser(User user);
}

3.创建服务提供方,springboot项目名provider,添加依赖

 <!-- 引入spring-boot-starter以及dubbo和curator的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.3</version>
        </dependency>
 <!--        下面两个是dubbo的依赖包-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
        </dependency>
<!--        公共api依赖包-->
        <dependency>
            <groupId>cn.ppl</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

创建将要被远程调用的service

注意:@service注解是dubbo的,不是spring的

package cn.ppl.provider.service.impl;

import cn.ppl.api.pojo.User;
import cn.ppl.api.service.ProviderService;
import org.apache.dubbo.config.annotation.Service;

@Service
public class ProviderServiceImpl implements ProviderService {
    @Override
    public User setUser(User user){
        user.setId(11);
        user.setAge(16);
        user.setName("Jhon");
        return user;
    }
}

配置文件配置dubbo

#命名本服务
dubbo.application.name=provider
#声明注册中心
dubbo.registry.address=zookeeper://192.168.134.100:2181

4.创建springboot项目名consumer,添加依赖(比provider多个web),

 <!-- 引入spring-boot-starter以及dubbo和curator的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.3</version>
        </dependency>
 <!--        下面两个是dubbo的依赖包-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
        </dependency>
<!--        公共api依赖包-->
        <dependency>
            <groupId>cn.ppl</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

创建controller和service

package cn.ppl.consumer.controller;

import cn.ppl.api.pojo.User;
import cn.ppl.consumer.service.ConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {
    @Autowired
    ConsumerService consumerService;
    @RequestMapping("/demo")
    @ResponseBody
    public String demo(){
        User user = new User();
        return consumerService.showUser(user);
    }
}

package cn.ppl.consumer.service.impl;

import cn.ppl.api.pojo.User;
import cn.ppl.api.service.ProviderService;
import cn.ppl.consumer.service.ConsumerService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

@Service
public class ConsumerServiceImpl implements ConsumerService {
    @Reference
    private ProviderService providerService;

    @Override
    public String showUser(User user){
        return providerService.setUser(user).toString();
    }
}


配置文件配置dubbo

#避免和监控中心端口冲突,设为8082端口访问
server.port=8082
#命名本服务
dubbo.application.name=consumer
#声明注册中心
dubbo.registry.address=zookeeper://192.168.134.100:2181


总结:把spring的@Service和@Autowired替换成dubbo的@Service和@Reference ,配置服务名和注册中心 ,其他部分代码不变

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值