第十六天.

昨天摆烂了,今天继续

练习

字母与数字

给定一个放有字母和数字的数组,找到最长的子数组,且包含的字母和数字的个数相同。

返回该子数组,若存在多个最长子数组,返回左端点下标值最小的子数组。若不存在这样的数组,返回一个空数组。

示例 1:

输入: ["A","1","B","C","D","2","3","4","E","5","F","G","6","7","H","I","J","K","L","M"]

输出: ["A","1","B","C","D","2","3","4","E","5","F","G","6","7"]
示例 2:

输入: ["A","A"]

输出: []
提示:

array.length <= 100000
class Solution {
    public String[] findLongestSubarray(String[] array) {
        Map<Integer, Integer> map = new HashMap<>();
        map.put(0,-1);
        int sum=0;//前缀和
        int maxnum=0;//最长子数组长度
        int left=0;//指针 最长子数组的左端点
        for (int i = 0; i < array.length; i++) {
            // 标定是否为字母,是则为1,不是则为-1
            sum += array[i].charAt(0) >='A'?1:-1;
            if(map.containsKey(sum)){
                // 判断哈希表中是否存在相同的s
                // 如果存在,则接收它的左端点
                int j=map.get(sum);
                if(maxnum<i-j){
                    // 判断数组长度i-j是否大于mx
                    // 如果是,则更新数组长度
                    maxnum=i-j;
                    // 同时更新左端点
                    left=j+1;
                }
            }else {
                // 如果不存在相同的s,则将它加入哈希表中
                map.put(sum,i);
            }
        }
        String[] strings = new String[maxnum];
        //arraycopy的使用
        //第一个参数:源数组
        //第二个参数:在源数组中,被复制的数字开始复制的下标
        //第三个参数:目标数组
        //第四个参数:从目标数组中,从第几个下标开始放入复制的数据
        //第五个参数:从源数组中,一共拿几个数值放到目标数组中
        System.arraycopy(array,left,strings,0,maxnum);
        return strings;
    }
}

上面sum +=我本来想写sum= sum+的

后来发现少了第一位的数字A 想了想

sum =sum+(array[i].charAt(0) >='A'?1:-1);

如果要写后面的 需要让后面的带上括号

至于解题思路,说实话,跟前天的一样,除了最好的arraycopy

前面都是一样的,判断最大长度,获取最大长度最左边的指针

设置一个数,当这个数的和为0的时候 返回这个字符串,判断字符串的长度

大于就记录,小于就直接过,没有就放入

八股

session 和 cookie 有什么区别?

session是客户与服务器连接的一次会话,也就是服务端用于访问用户的状态,而cookie则是存储着session会话的id,让服务端判断是那个用户来访问的。

说一下 session 的工作原理?

session就类似一个大型的map,其中的sessionid是由cookie存储的,当服务端通过cookie获取sessionid后,就可以从session取出对应的用户信息了

如果客户端禁止 cookie 能实现 session 还能用吗

一般情况下不能,因为cookie存储的sessionid,禁用了就无法获取对应的session了

但是可以通过

  1. 设置php.ini配置文件中的“session.use_trans_sid = 1”,或者编译时打开打开了“--enable-trans-sid”选项,让PHP自动跨页传递Session ID。

  1. 手动通过URL传值、隐藏表单传递Session ID。

  1. 用文件、数据库等形式保存Session ID,在跨页过程中手动调用。

spring mvc 和 struts 的区别是什么

底层框架不同

前者使用selvet 调用时初始化,服务停止后销毁,后者使用filter,容器启动后出书和,服务停止后销毁。而前者比后者更快

性能不同

前者是方法级别的连接,每次都是单例bean注入,后者是类级别的拦截,每次请求都要实例化一个action去加载所有的配置,所以前者性能高于后者

配置方便

springMVC的spring是无缝的,更安全

基于阳哥第二季的SpringCloud(第三天)

Zookeeper同eureka

替代Eureka

注册中心Zookeeper

zookeeper是一个分布式协调工具,可以实现注册中心功能

关闭Linux服务器防火墙后启动zookeeper服务器

zookeeper服务器取代Eureka服务器,zk作为服务注册中心

服务提供者

服务提供者
  新建cloud-provider-payment8004
 

 POM
<!-- SpringBoot整合zookeeper客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>
  

YML
#8004表示注册到zookeeper服务器的支付服务提供者端口号
server:
  port: 8004
#服务别名----注册zookeeper到注册中心名称
spring:
  application:
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: 192.168.111.144:2181
 
 
  主启动类
@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
public class PaymentMain8004
{
    public static void main(String[] args)
    {
        SpringApplication.run(PaymentMain8004.class,args);
    }

}

  Controller
@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/payment/zk")
    public String paymentzk()
    {
        return "springcloud with zookeeper: "+serverPort+"\t"
             + UUID.randomUUID().toString();
    }
}
 
启动8004注册进zookeeper
  如果启动失败
 解决zookeeper版本jar包冲突问题
排出zk冲突后的新POM
<!-- SpringBoot整合zookeeper客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--先排除自带的zookeeper3.5.3-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--添加zookeeper3.4.9版本-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </dependency>


  验证测试
http://localhost:8004/payment/zk
  验证测试2
获得json串后用在线工具查看试试
https://tool.lu/json/
  思考
服务节点是临时节点还是持久节点
是临时节点,一段时间没收到信息,会直接剃掉

服务消费者

服务消费者
  新建cloud-consumerzk-order80
  POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mscloud</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumerzk-order81</artifactId>


    <dependencies>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- SpringBoot整合zookeeper客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--先排除自带的zookeeper-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--添加zookeeper3.4.9版本-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
 

  YML
server:
  port: 80

spring:
  application:
    name: cloud-consumer-order
  cloud:
  #注册到zookeeper地址
    zookeeper:
      connect-string: 192.168.111.144:2181
 
 

  主启动
@SpringBootApplication
public class OrderZK80
{
    public static void main(String[] args)
    {
        SpringApplication.run(OrderZK80.class,args);
    }
}
 
  业务类
    配置Bean
@Configuration
public class ApplicationContextConfig
{
    @Bean
    @LoadBalanced 开启负载均衡
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}
    Controller
@RestController
@Slf4j
public class OrderZKController
{
    public static final String INVOKE_URL = "http://cloud-provider-payment";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping(value = "/consumer/payment/zk")
    public String paymentInfo()
    {///payment/zk在支付端里面的controller
        String result = restTemplate.getForObject(INVOKE_URL+"/payment/zk", String.class);
        System.out.println("消费者调用支付服务(zookeeper)--->result:" + result);
        return result;
    }

}
 
  验证测试
  访问测试地址
    http://localhost/consumer/payment/zk

Consul服务注册与发现 同eureka

Consul简介

是什么

Consul 是一套开源的分布式服务发现和配置管理系统,由 HashiCorp 公司用 Go 语言开发。
 
提供了微服务系统中的服务治理、配置中心、控制总线等功能。
这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,
总之Consul提供了一种完整的服务网格解决方案。
 
它具有很多优点。包括: 基于 raft 协议,比较简洁; 支持健康检查, 
同时支持 HTTP 和 DNS 协议 支持跨数据中心的 WAN 集群 提供图形界面 跨平台,
支持 Linux、Mac、Windows

https://www.consul.io/intro/index.html

能干嘛

服务发现

提供HTTP和DNS两种发现方式。

健康监测

支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控

KV存储

Key、Value的存储方式

多数据中心

Consul支持多数据中心

可视化Web界面

去哪下

https://www.consul.io/downloads.html

怎么玩

https://www.springcloud.cc/spring-cloud-consul.html

安装并运行Consul

官网安装说明

https://learn.hashicorp.com/consul/getting-started/install.html

下载完成后只有一个consul.exe文件, 硬盘路径下双击运行,查看版本号信息

使用开发模式启动

consul agent -dev

通过以下地址可以访问Consul的首页:http://localhost:8500

结果页面

服务提供者

新建Module支付服务provider8006

cloud-providerconsul-payment8006

   
  POM
 <!--SpringCloud consul-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

  YML
###consul服务端口号
server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
####consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        service-name: ${spring.application.name}
 
 

  主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006
{
    public static void main(String[] args)
    {
        SpringApplication.run(PaymentMain8006.class,args);
    }
}
 
  业务类Controller
@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/consul")
    public String paymentInfo()
    {
        return "springcloud with consul: "+serverPort+"\t\t"+ UUID.randomUUID().toString();
    }
}
  验证测试
http://localhost:8006/payment/consul

消费提供者

新建Module消费服务order80
  cloud-consumerconsul-order80
POM
 <!--SpringCloud consul-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

YML
###consul服务端口号
server:
  port: 80

spring:
  application:
    name: cloud-consumer-order
####consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        service-name: ${spring.application.name}

主启动类
@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
public class OrderConsulMain80
{
    public static void main(String[] args)
    {
        SpringApplication.run(OrderConsulMain80.class,args);
    }
}
 
 
配置Bean
@Configuration
public class ApplicationContextBean
{
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}
 
Controller
@RestController
public class OrderConsulController
{
    public static final String INVOKE_URL = "http://cloud-provider-payment"; //consul-provider-payment

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping(value = "/consumer/payment/consul")
    public String paymentInfo()
    {
        String result = restTemplate.getForObject(INVOKE_URL+"/payment/consul", String.class);
        System.out.println("消费者调用支付服务(consule)--->result:" + result);
        return result;
    }
}
 
 
 
验证测试
访问测试地址
  http://localhost/consumer/payment/consul

三个注册中心异同点

CAP

C:Consistency(强一致性)

A:Availability(可用性)

P:Partition tolerance(分区容错性)

CAP理论关注粒度是数据,而不是整体系统设计的策略

经典CAP图

最多只能同时较好的满足两个。

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,

因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。

CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。

AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。 例如淘宝(必须可用,不保证数据的一致性)

AP(Eureka)

AP架构
当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。
结论:违背了一致性C的要求,只满足可用性和分区容错,即AP

CP(Zookeeper/Consul)

CP架构
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性
结论:违背了可用性A的要求,只满足一致性和分区容错,即CP

Ribbon负载均衡服务调用

概述

是什么

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端  负载均衡的工具。
 
简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。

官网资料

https://github.com/Netflix/ribbon/wiki/Getting-Started

Ribbon目前也进入维护模式

未来替换方案

能干吗

LB(负载均衡)

LB负载均衡(Load Balance)是什么
简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。
常见的负载均衡有软件Nginx,LVS,硬件 F5等。
 
Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别
 Nginx是服务器负载均衡,客户端所有请求都会交给nginx,
然后由nginx实现转发请求。即负载均衡是由服务端实现的。
 
 Ribbon本地负载均衡,在调用微服务接口时候,
会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
 

集中式LB

 
即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx),
 由该设施负责把访问请求通过某种策略转发至服务的提供方;

进程内LB

 
将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,
然后自己再从这些地址中选择出一个合适的服务器。
 
Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,
消费方通过它来获取到服务提供方的地址。
 

前面我们讲解过了80通过轮询负载访问8001/8002

一句话

负载均衡+RestTemplate调用

Ribbon负载均衡演示

架构说明

总结:Ribbon其实就是一个软负载均衡的客户端组件, 他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

POM

spring-cloud-starter-netflix-eureka-client
自带了spring-cloud-starter-ribbon引用,


<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

二说RestTemplate的使用

官网

https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

getForObject方法/getForEntity方法

返回对象为响应体中数据转化成的对象,基本上可以理解为Json

返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等

postForObject/postForEntity

GET请求方法

 
<T> T getForObject(String url, Class<T> responseType, Object... uriVariables);
 
<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables);
 
<T> T getForObject(URI url, Class<T> responseType);
 
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables);
 
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables);
 
<T> ResponseEntity<T> getForEntity(URI var1, Class<T> responseType);

POST请求方法

 
<T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables);
 
<T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables);
 
<T> T postForObject(URI url, @Nullable Object request, Class<T> responseType);
 
<T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables);
 
<T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables);
 
<T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType);

Ribbon核心组件IRule

    IRule:根据特定算法中从服务列表中选取一个要访问的服务
      com.netflix.loadbalancer.RoundRobinRule
        轮询
      com.netflix.loadbalancer.RandomRule
        随机
      com.netflix.loadbalancer.RetryRule
        重试
        先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
      WeightedResponseTimeRule
权重
        对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
      BestAvailableRule
过滤多次访问故障
        会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
      AvailabilityFilteringRule
        先过滤掉故障实例,再选择并发较小的实例
      ZoneAvoidanceRule
        默认规则,复合判断server所在区域的性能和server的可用性选择服务器

如何替换

修改cloud-consumer-order80

注意配置细节

官方文档明确给出了警告:
这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,
否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。

新建package

com.atguigu.myrule

上面包下新建MySelfRule规则类

package com.atguigu.myrule;

mport com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MySelfRule
{
    @Bean
    public IRule myRule()
    {
        return new RandomRule();//定义为随机
    }
}
 

主启动类添加@RibbonClient

 * 在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效,形如:
 */
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration=MySelfRule.class)
public class OrderMain80
{
    public static void main(String[] args)
    {
        SpringApplication.run(OrderMain80.class,args);
    }
}
 

测试

http://localhost/consumer/payment/get/31

Ribbon负载均衡算法

原理

负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标  ,每次服务重启动后rest接口计数从1开始。
 
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
 
如:   List [0] instances = 127.0.0.1:8002
   List [1] instances = 127.0.0.1:8001
 
8001+ 8002 组合成为集群,它们共计2台机器,集群总数为2, 按照轮询算法原理:
 
当总请求数为1时: 1 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001
当总请求数位2时: 2 % 2 =0 对应下标位置为0 ,则获得服务地址为127.0.0.1:8002
当总请求数位3时: 3 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001
当总请求数位4时: 4 % 2 =0 对应下标位置为0 ,则获得服务地址为127.0.0.1:8002
如此类推......
 
 

RoundRobinRule源码

手写

自己试着写一个本地负载均衡器试试

7001/7002集群启动

8001/8002微服务改造

controller

 @GetMapping(value = "/payment/lb")
    public String getPaymentLB()
    {
        return serverPort;
    }

80订单微服务改造

ApplicationContextBean去掉注解@LoadBalanced

@Configuration
public class ApplicationContextBean
{
    @Bean
    //@LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}
 

LoadBalancer接口

public interface LoadBalancer
{
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}

MyLB

package com.atguigu.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @auther zzyy
 * @create 2020-02-02 17:57
 */
@Component
public class MyLB implements LoadBalancer
{
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public final int getAndIncrement()
    {
        int current;
        int next;
        do
        {
            current = this.atomicInteger.get();
            next = current >= 2147483647 ? 0 : current + 1;
        } while(!this.atomicInteger.compareAndSet(current, next));
        System.out.println("*****next: "+next);
        return next;
    }


    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances)
    {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}
 
 

OrderController

 
package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.lb.LoadBalancer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.net.URI;
import java.util.List;

/**
 * @auther zzyy
 * @create 2020-01-28 16:22
 */
@RestController
public class OrderController
{
    //public static final String PAYMENT_SRV = "http://localhost:8001";
    public static final String PAYMENT_SRV = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;
    //可以获取注册中心上的服务列表
    @Resource
    private DiscoveryClient discoveryClient;
    @Resource
    private LoadBalancer loadBalancer;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment)
    {
        return restTemplate.postForObject(PAYMENT_SRV+"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id)
    {
        return restTemplate.getForObject(PAYMENT_SRV+"/payment/get/"+id,CommonResult.class);
    }

    @GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPayment2(@PathVariable("id") Long id)
    {
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_SRV+"/payment/get/"+id, CommonResult.class);
        if(entity.getStatusCode().is2xxSuccessful()){
            return entity.getBody();
        }else {
            return new CommonResult(444, "操作失败");
        }
    }
 
 
    @Resource
    private LoadBalancer loadBalancer;

    @GetMapping("/consumer/payment/lb")
    public String getPaymentLB()
    {
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

        if(instances == null || instances.size()<=0) {
            return null;
        }
        ServiceInstance serviceInstance = loadBalancer.instances(instances);
        URI uri = serviceInstance.getUri();

        return restTemplate.getForObject(uri+"/payment/lb",String.class);
    }
}
 
 
 

测试

http://localhost/consumer/payment/lb

ribbon已经被移除了 详细请看下面的大神写的

http://t.csdn.cn/56uLx

总结

很苦恼,因为ribbon已经在springcloud被废除了

所以不得不用LoadBalancer

来改,但是这就跟阳哥写的完全相悖了

注解位置也不一样,虽然负载也是一样写的,但是已经没必要去听了

所以明明还有40分钟的课我花了很长时间去将ribbon改成loadbalancer

然后,失败了

心态有点炸 主要是ribbon跟loadbalancer改规则的方式有区别,虽然看着别人的代码写了

但是实际上还有不断的小问题,懒得继续了,真到用的时候再学吧

已经废除了,学LoadBalancer更有用一点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值