Spring Cloud&系统结构演变&远程调用&Http客户端工具

系统结构演变

单一应用->垂直拆分->分布式服务->SOA->微服务架构->Service Mesh

集中式架构

数据访问框架(ORM)

分布式服务

将核心业务抽取出来,作为独立的服务,逐渐形成服务中心

服务治理(面向服务SOA)

增加一个调度中心基于访问压力实时管理集群容量

  • 服务注册中心实现服务自动注册和发现,,无需人为记录服务地址
  • 服务自动订阅,服务列表自动推送,服务调用透明化,无需关心依赖关系
  • 动态监控服务状态监控报告,人为控制服务状态

不符合DevOps思想(软件开发人员(Develop)”和“IT运维技术人员(Operations)”之间沟通合作的文化、运动或惯例)

Docker类似于虚拟机,轻量级、跨平台,可打包成镜像

微服务

对系统进行拆分

传统SOA技术栈一致,全用同一种技术

微服务SOA
能拆分就拆分服务能放一起就放一起
纵向业务划分水平分多层
由单一组织负责按层级划分不同的部门组织负责
细粒度粗粒度
独立的子公司类似大公司划分出来的业务单元(BU)
组件小组件复杂
业务逻辑存在每个服务中业务逻辑横款多个业务领域
使用轻量级通信,如HTTP企业服务产总线(ESB)充当服务之间通信角色

特点:

  • 单一职责
  • 拆分粒度小
  • 面向服务:每个服务需要对外暴露服务接口API,与平台、语言无关,只提供Rest的接口
  • 自治:服务间相互独立
    • 团队独立
    • 技术独立
    • 前后端分离
    • 数据库分离
    • 部署独立

远程调用方式

  • RPC:Remote Procedure Call远程过程调用,自定义数据格式,类似的还有RMI(远程方法调用Remote Method Invocation),现在热门的Dubbo就是RPC的典型。基于原生的TCP通信。
  • HTTP:基于TCP通信。缺点是消息封装臃肿,Rest是HTTP协议实现

RPC

允许运行于一台计算机的程序调用另一台计算机的子程序,无需为而外的交互进行编程。调用过程对于用户是透明的。

实现远程调用,想调用本地服务一样调用远程服务。包括Socket通信,动态代理进行隐藏,封装

采用TCP为底层传输协议,定义好请求好请求和响应的个数。数据在网络中需要进行序列化,约定统一的序列化方式。

HTTP

应用层协议

响应 

区别

  1. RPC没有规定数据传输格式,可任意指定。不同的RPC协议可以有不同的格式
  2. HTTP定义了资源定位的路径,RPC不用
  3. RPC在调用过程在API层面进行封装(像调用本地服务一样调用远程服务),限制开发的语言环境
  4. RPC更透明,HTTP更灵活没有规定语言和API,但是数据繁琐

Http客户端工具

  • URLConnection:java原生的类实现Http请求
  • HttpClient
  • OKHttp:比HttpClient更轻量,Android用的多

HttpClient

Http Components下的子组件,支持Https协议,通过Http代理建立透明的连接,自动处理Set-Cookie中的Cookie

    <dependency> 
         <groupId>org.apache.httpcomponents</groupId> 
          <artifactId>httpclient</artifactId> 
         <version>4.5.1</version>         
    </dependency> 
    <dependency> 
         <groupId>org.apache.httpcomponents</groupId> 
          <artifactId>httpclient-cache</artifactId> 
         <version>4.5.1</version>         
    </dependency> 
    <dependency> 
         <groupId>org.apache.httpcomponents</groupId> 
          <artifactId>httpmime</artifactId> 
         <version>4.5.1</version>         
    </dependency>
package edu.qut.httpdemo;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.qut.pojo.User;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.junit.Before;
import org.junit.Test;

import java.io.Closeable;
import java.io.IOException;
import java.util.List;

/**
 * @Author: AmberXu
 * @Date: 2018/9/24 21:49
 */
public class HttpTests {
    CloseableHttpClient httpClient;
    ObjectMapper mapper = new ObjectMapper();
    @Before
    public void init(){
        //创建httpClient的客户端
        httpClient = HttpClients.createDefault();
    }
    @Test
    public void testGet()throws IOException{
        //发起get请求
        HttpGet request = new HttpGet("http://www.baidu.com");
        //执行请求
        String response = this.httpClient.execute(request,new BasicResponseHandler());
        System.out.println(response);
    }
    @Test
    public void testPost()throws IOException{
        //可能会被鉴定为爬虫
        HttpPost request = new HttpPost("http://www.oschina.net/");
        //头信息
        request.setHeader("User-Agent","Mozila/5.0(Window NT 10.0; WOW64) AppleWebkit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");
        String response = this.httpClient.execute(request,new BasicResponseHandler());
        System.out.println(response);
    }
    @Test
    public void testGetPojo()throws IOException{
        //远程调用,只需知道URL,获取到JSON
        HttpGet request = new HttpGet("http://localhost/hello");
        String response = this.httpClient.execute(request,new BasicResponseHandler());
//        将JSON数据转化为User
        User user = mapper.readValue(response, User.class);
//        转换List<User>
//        List<User> userList = mapper.readValue(response,mapper.getTypeFactory().constructCollectionType(List.class,User.class));
       // List<User> userList = mapper.readValue(response, new TypeReference<List<User>>(){});
        System.out.println(user);
    }
}

在百度直接输入网址是Get,不能用post

JsonUtils把对象变成Json字符串(序列化),把Json字符串变成对象(反序列化)

Spring的RestTemplate

模板工具类,基于Http客户端的封装

@RunWith(SpringRunnner.class)
@SpringBootTest(classes = HttpDemoApplicationTests.class)
public class HttpDemoApplicationTests {
    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void httpGet(){
        User user = this.restTemplate.getForObject("http://localhost/hello",User.class);
        System.out.println(user);
    }
}

Spring Cloud

微服务框架

配置管理、服务发现、智能路由、负载均衡、熔断器、控制总线、集群状态

  • Eureka:注册中心
  • Zuul:服务网关
  • Ribbon:负载均衡
  • Feign:服务调用
  • Hystix:熔断器

微服务场景模拟

新建一个服务,对外提供查询用户的服务

右键点击new,选择Module->Spring Initializr->next

待完善

Eureka注册中心

定时发送Http请求,维持“心跳(续约renew)”。管理服务,实现服务的自动发现、自动注册、服务的监管

定期拉取服务列表

对于客户端添加@EnableDiscoveryClient

添加@EnableEurekaServer,编写application.yml


eureka:
  server:
    wait-time-in-ms-when-sync-empty: 0
    enable-self-preservation: true # false 关闭自我保护,不管如何都要剔除心跳检测异常的服务
  instance:
    hostname: eureka1


@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
	public static void main(String[] args) {
		new SpringApplicationBuilder(EurekaApp.class).web(true).run(args);
}
}
<!-- 注册中心 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<!-- 服务轨迹跟踪 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zipkin</artifactId>
		</dependency>
		<!-- 配置中心服务器 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>
		<!-- 配置总线依赖 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
		</dependency>
		<!-- 监控埋点 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

一个服务下可以有多个实例

服务提供者:提供服务的应用,并注册到Eureka的注册中心

服务消费者:从注册中心获取服务列表,从而得知每个服务提供者的信息。通过DiscoveryClient对象getInstances(服务名称)获取服务,返回集合List<ServiceInstance>,可能是集群,编写负载均衡算法。ServiceInstance对象通过getHost和getPost获取。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值