RPC

单体架构

单体架构就是一个项目里面包含这个项目中的全部代码,一个应用搞定全部功能,DNS服务器可以是单映射,也可以配置多个映射

软件代码结构

在单体结构项目中,团队都是通过包(package)进行区分每个模块

优缺点

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

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

使用项目

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

分布式架构

架构图(简易版)

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

软件代码结构

优缺点

优点

  • 增大了系统可用性,减少单点故障,导致整个应用不可用
  • 增加重用性,因为模块化,所以重用性更高
  • 增加可扩展性,有新的模块增加新的项目即可
  • 增加每个模块的负载能力,每个模块都是一个项目,每个模块负载能力更强

缺点

  • 成本更高
  • 架构更加复杂
  • 整体响应时间更长,一些业务需要多项目通信后给出结果
  • 吞吐量更大,吞吐量=请求数/秒

待解决问题

分布式结构可以使用Http协议,也可以使用RPC协议通信,RPC比Http更适合内部通信

RPC简介

RFC,(Requeest For comments)是由互联网工程任务组发布的文件集

文件集中每个文件都有唯一编号

RPC在rfc远程过程调用协议,RPC协议规定允许互联网中一台主机程序调用另一台主机程序

程序员无需对这个交互过程进行编程,在RPC协议中强调当A程序调用B程序中功能或方法时,A不知道B中方法的具体实现

RPC是上层协议,底层可以基于TCP协议,也可以基于HTTP协议,RPC是基于RPC的具体实现,如:Dubbo框架

满足网络中进行通讯调用的都称为RPC,甚至HTTP都可以称为RPC,具体分析RPC要比HTTP协议更加高效

RPC和HTTP对比

具体实现

RPC:可以基于TCP协议,也可以基于HTTP协议

HTTP:基于HTTP协议

效率

RPC:自定义具体实现可以减少很多无用的报文内容,使得报文体积更小

HTTP:如果是HTTP1.1报文中很多内容都是无用的,如果是HTTP2.0以后和RPC相差不大,比RPC少的可能就是一些服务治理

连接方式

RPC:长连接支持

HTTP:每次连接都是3次握手

性能

RPC可以基于很多序列化方式,如:thrift

HTTP主要通过JSON,序列化和反序列效率更低

注册中心

RPC:一般RPC框架都带有注册中心

HTTP:都是直连

负载均衡:

RPC:绝大多数RPC框架都带有负载均衡测量

HTTP:一般都需要借助第三方工具,如nginx

综合结论

RPC有丰富的服务治理功能,更适合企业内部接口调用,HTTP适合多平台间调用

HttpClient实现RPC

服务端

新建控制器

@Controller
public class DemoController{
    @RequestMapping("/demo")
    @ResponseBody
    public String demo(String param){
        return "demo" + param;
    }
}

新建启动器

@SpringBootApplication
public class ServerApplication{
    public static void main(String[] args){
        SpringApplication.run(ServerApplication.class, args);
    }
}

使用GET方法

添加依赖,官方地址:https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient

public class HttpClientDemo{
    @Test
    public void testGetDemo() throws {
        // 发送请求, 解析响应
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try{
            // 确定请求路径
            URIBuilder uriBuilder = new URIBuilder("http://localhost:8080/demo");
            // 创建httpGet请求对象
            HttpGet get = new HttpGet(uriBuilder.build());
            // 创建响应对象
            CloseableHttpResponse response = httpClient.execute(get);
            // 由于响应体是字符串, 因此把HttpEntity类型转换为字符串类型, 并设置字符集编码
            String result = EntityUtils.toString(response.getEntity(), "utf-8");
            // 输出结果
            System.out.println(result);
            // 释放资源
            response.close();
            httpClient.close();
        }catch(URISyntaxException e){
            e.printStackTrace();
        }        
    }

    @Test
    public void testPostDemo(){
        try{
            // 创建Http工具(理解成: 浏览器) 发送请求, 解析响应
            CloseableHttpClient httpClient = HttpClients.createDefault();
            // 创建HttpPost请求对象
            HttpPost post = new HttpPost("http://localhost:8080/");    
            // 创建请求参数
            List<NameValuePair> params = new ArrayList<>(NameValuePair);
            params.add(new BasicNameValuePair("param", "value"));
            HttpEntity httpEntity = new UrlEncodeFormEntity(params, "utf-8");
            post.setEntity(httpEntity);
            // 创建响应对象
            CloseableHttpResponse response = httpClient.execute(post);
            // 把HttpEntity类型转换为字符串类型
            String result = EntityUtils.toString(response.getEntity());
            // 输出结果, 释放资源
            System.out.println(result);
            response.close();
            httpClient.close();
        }catch(IOException e){
            e.printStackTrace();
        }        
    }
}

Jackson用法

添加依赖,官方地址:https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.2</version>
</dependency>

jackson常用方法

ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(content, User.class);
// 使用jackson把对象转换为Json
String userJson = objectMapper.writeValueAsString(user);
System.out.println(userJson);
response.close();
httpClient.close();

流数据,控制器

@Controller
public class DemoController{
    @RequestMapping("/demo")
    @ResponseBody
    public String demo(String param){
        return param + "abc";
    }

    @RequestMapping("/demo2")
    @ResponseBody
    public User demo2(User user){
        return user;
    }

    @RequestMapping("/demo3")
    @ResponseBody
    public User demo3(User user){
        List<User> list = new ArrayList<>();
        list.add(new User(1, "aaa"));
        list.add(new User(2, "bbb"));
        return list;
    }

    @RequestMapping("/demo4")
    @ResponseBody
    public String demo4(@RequestBody List<User> list){
        System.out.println(list);
        return list.toString();
    }

    @RequestMapping("/demo5")
    @ResponseBody
    @CrossOrigin
    public List<User> demo5(@RequestBody List<User> list){
        System.out.println(list);
        return list;
    }

    @Test
    public void testListPostDemo(){    
        try{
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost("http://localhost:8080/demo3");
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String content = EntityUtils.toString(response.getEntity());
            System.out.println(content);
            response.close();
            httpClient.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    @Test
    public void testInputStream(){
        CloseableHttpClient httpClient = HttpCliens.createDefault();
        HttpPost httpPost = new HttpPost("http://localhost:8080/demo4");
        List<User> listParam = new ArrayList<User>();
        listParam.add(new User(1, "zsf"));
        listParam.add(new User(2, "zwj"));

        ObjectMapper objectMapper = new ObjectMapper();
        // 集合对象转换为json
        try{
            String jsonParam = objectMapper.writeValueAsString(listParam);
            HttpEntity httpEntity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
            httpPost.setEntity(httpEntity);
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String content = EntityUtils.toString(response.getEntity());
            response.close();
            httpClient.close();
        }catch(JsonProcessingException e){
            e.printStackTrace();
        }    
    }
}
论读书
睁开眼,书在面前
闭上眼,书在心里
原文地址:https://www.cnblogs.com/YC-L/p/14354570.html