一、SpringCloud入门

一、SpringCloud基本概念

  • 1.为什么要使用SpringCloud
    • SpringCloud并不是rpc远程调用框架,而是一套全家桶的微服务解决框架,理念就是解决我们在微服务架构中遇到的任何问题。例如:服务注册中心、分布式配置、服务保护等。
    • SpringCloud 属于微服务全家桶框架 解决我们在
      微服务架构中遇到难题。
  • 2.微服务架构中常见问题
    • 分布式服务注册中心(服务治理) Eureka、Zookeeper、Consule、Nacos、Redis、数据库等;
    • 分布式配置中心 SpringCloud Config、携程阿波罗、Nacos Config;
    • 分布式事务解决方案(MQ最终一致性/LCN(已经淘汰)/ Seata(阿里背书))
    • 分布式任务调度平台(xxl-job、elastic job、阿里巴巴Scheduler)
    • 分布式日志采集系统ELK+Kafka
    • 分布式服务追踪与调用链Zipkin、skywalking等。
    • 分布式锁(Redis(Redisson)/Zookeeper(Curator)实现分布式锁)
    • 服务的接口保护(hystrix/sentinel)
  • 3.SpringCloud第一代和第二代区别
    • SpringCloud第一代:
      • SpringCloud Config 分布式配置中心
      • SpringCloud Netflix 核心组件
      • Eureka:服务治理
      • Hystrix:服务保护框架
      • Ribbon:客户端负载均衡器
      • Feign:基于ribbon和hystrix的声明式服务调用组件
      • Zuul: 网关组件,提供智能路由、访问过滤等功能
    • SpringCloud第二代
      • Spring Cloud Gateway 网关
      • Spring Cloud Loadbalancer 客户端负载均衡器
      • Spring Cloud r4j(Resilience4J) 服务保护
      • Spring Cloud Alibaba Nacos 服务注册
      • Spring Cloud Alibaba Nacos 分布式配置中心
      • Spring Cloud Alibaba Sentinel服务保护
      • SpringCloud Alibaba Seata分布式事务解决框架
      • Alibaba Cloud OSS 阿里云存储
      • Alibaba Cloud SchedulerX 分布式任务调度平台
      • Alibaba Cloud SMS 分布式短信系统
  • 4.为什么Alibaba要推出SpringCloud组件
    • SpringCloud与alibaba相结合,技术上有人负责更新新的组件,也还可以继续使用Spring社区的技术

二、微服务服务注册中心

  • 1.微服务服务注册中心概念
    • 服务治理
    • RPC远程调用
  • 2.什么是远程调用
    • 例如我们平台需要获取到天气预报,就可以直接调用中国天气预报接口:http://wthrcdn.etouch.cn/weather_mini?city=武汉,返回的是json格式数据,可以使用https://www.sojson.com/在线json格式化查看
{"data":{"yesterday":{"date":"26日星期六","high":"高温 15℃","fx":"北风","low":"低温 10℃","fl":"<![CDATA[2级]]>","type":"阴"},"city":"武汉","forecast":[{"date":"27日星期天","high":"高温 19℃","fengli":"<![CDATA[2级]]>","low":"低温 7℃","fengxiang":"北风","type":"阴"},{"date":"28日星期一","high":"高温 21℃","fengli":"<![CDATA[3级]]>","low":"低温 7℃","fengxiang":"东南风","type":"晴"},{"date":"29日星期二","high":"高温 24℃","fengli":"<![CDATA[3级]]>","low":"低温 10℃","fengxiang":"东南风","type":"多云"},{"date":"30日星期三","high":"高温 24℃","fengli":"<![CDATA[2级]]>","low":"低温 12℃","fengxiang":"东风","type":"中雨"},{"date":"31日星期四","high":"高温 18℃","fengli":"<![CDATA[4级]]>","low":"低温 14℃","fengxiang":"北风","type":"小雨"}],"ganmao":"感冒易发期,外出请适当调整衣物,注意补充水分。","wendu":"16"},"status":1000,"desc":"OK"}
  • 3.什么是RPC
    • 远程调用采用接口:接口协议+IP+端口/接口名称?接口参数
      • 接口协议
        • 1.netty 基于netty RPC自定义协议 dubbo
        • 2.http协议接口 httpclient或者okhttp
        • 3.WebService 底层soap+http+xml
      • 微服务架构:http+json格式,json格式比xml格式更加轻量级
      • http传递参数
        • 如果只有一个参数 可以直接使用?传递参数
        • 如果是多个参数 json格式

三、使用HttpClient实现RPC远程调用

1.maven依赖

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.66</version>
        </dependency>

2.工具类HttpClientUtils

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class HttpClientUtils {

    private static final CloseableHttpClient httpClient;
    public static final String CHARSET = "UTF-8";
    private static final Log log = LogFactory.getLog(HttpClientUtils.class);

    // 采用静态代码块,初始化超时时间配置,再根据配置生成默认httpClient对象
    static {
        RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
        httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
    }

    public static String doGet(String url, Map<String, String> params) {
        return doGet(url, params, CHARSET);
    }


    public static String doPost(String url, Map<String, String> params) throws IOException {
        return doPost(url, params, CHARSET);
    }

    /**
     * HTTP Get 获取内容
     *
     * @param url     请求的url地址 ?之前的地址
     * @param params  请求的参数
     * @param charset 编码格式
     * @return 页面内容
     */
    public static String doGet(String url, Map<String, String> params, String charset) {
        try {
            if (params != null && !params.isEmpty()) {
                List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    String value = entry.getValue();
                    if (value != null) {
                        pairs.add(new BasicNameValuePair(entry.getKey(), value));
                    }
                }
                // 将请求参数和url进行拼接
                url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
            }
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                httpGet.abort();
                throw new RuntimeException("HttpClient,error status code :" + statusCode);
            }
            HttpEntity entity = response.getEntity();
            String result = null;
            if (entity != null) {
                result = EntityUtils.toString(entity, "utf-8");
            }
            EntityUtils.consume(entity);
            response.close();
            return result;
        } catch (Exception e) {
            log.error("请求服务器端出错:" + e);
            return null;
        }

    }

    /**
     * HTTP Post 获取内容
     *
     * @param url     请求的url地址 ?之前的地址
     * @param params  请求的参数
     * @param charset 编码格式
     * @return 页面内容
     * @throws IOException
     */
    public static String doPost(String url, Map<String, String> params, String charset)
            throws IOException {
        List<NameValuePair> pairs = null;
        if (params != null && !params.isEmpty()) {
            pairs = new ArrayList<NameValuePair>(params.size());
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String value = entry.getValue();
                if (value != null) {
                    pairs.add(new BasicNameValuePair(entry.getKey(), value));
                }
            }
        }
        HttpPost httpPost = new HttpPost(url);
        if (pairs != null && pairs.size() > 0) {
            httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
        }
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                httpPost.abort();
                throw new RuntimeException("HttpClient,error status code :" + statusCode);
            }
            HttpEntity entity = response.getEntity();
            String result = null;
            if (entity != null) {
                result = EntityUtils.toString(entity, "utf-8");
            }
            EntityUtils.consume(entity);
            return result;
        } catch (ParseException e) {
            log.error("请求服务器端出错:" + e);
            return null;
        } finally {
            if (response != null)
                response.close();
        }
    }
}

3.RpcController

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sjyl.utils.HttpClientUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
public class RpcController {

    @RequestMapping("/getWeather")
    public Object getWeather(String city) {
        String url = "http://wthrcdn.etouch.cn/weather_mini";
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("city", city);
        String result = HttpClientUtils.doGet(url, params);
        JSONObject json = JSONObject.parseObject(result);
        Integer status = json.getInteger("status");
        if (status != 1000) {
            return "查询天气失败,请稍后重试!";
        }
        // 取出今日天气
        JSONArray forecast = json.getJSONObject("data").getJSONArray("forecast");
        return forecast;
    }
}

4.测试

  • 测试地址
    • http://127.0.0.1:8088/sjyl/getWeather?city=福州
      在这里插入图片描述
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无休止符

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值