昨天摆烂了,今天继续
练习
字母与数字
给定一个放有字母和数字的数组,找到最长的子数组,且包含的字母和数字的个数相同。
返回该子数组,若存在多个最长子数组,返回左端点下标值最小的子数组。若不存在这样的数组,返回一个空数组。
示例 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了
但是可以通过
设置php.ini配置文件中的“session.use_trans_sid = 1”,或者编译时打开打开了“--enable-trans-sid”选项,让PHP自动跨页传递Session ID。
手动通过URL传值、隐藏表单传递Session ID。
用文件、数据库等形式保存Session ID,在跨页过程中手动调用。
spring mvc 和 struts 的区别是什么
底层框架不同
前者使用selvet 调用时初始化,服务停止后销毁,后者使用filter,容器启动后出书和,服务停止后销毁。而前者比后者更快
性能不同
前者是方法级别的连接,每次都是单例bean注入,后者是类级别的拦截,每次请求都要实例化一个action去加载所有的配置,所以前者性能高于后者
配置方便
springMVC的spring是无缝的,更安全
基于阳哥第二季的SpringCloud(第三天)
![](https://i-blog.csdnimg.cn/blog_migrate/01296d3bf58ab2e484dbb62d28390d57.png)
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 - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。 例如淘宝(必须可用,不保证数据的一致性)
![](https://i-blog.csdnimg.cn/blog_migrate/38f39154dee0f8ea2ca4f3ed9610cf38.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6ca8cf1d7d542f1c8507dc74f99f01f5.png)
AP(Eureka)
AP架构
当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。
结论:违背了一致性C的要求,只满足可用性和分区容错,即AP
![](https://i-blog.csdnimg.cn/blog_migrate/ed2e6602715d184bf4f94e3e713f1675.png)
CP(Zookeeper/Consul)
CP架构
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性
结论:违背了可用性A的要求,只满足一致性和分区容错,即CP
![](https://i-blog.csdnimg.cn/blog_migrate/b4ded96d79be2bf101e938e93948833d.png)
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负载均衡演示
架构说明
![](https://i-blog.csdnimg.cn/blog_migrate/6b5e455f79e4c70863f417aef841c0a8.png)
总结: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://i-blog.csdnimg.cn/blog_migrate/0cf5b0bd2bea2c7b6509f1829990adaa.png)
getForObject方法/getForEntity方法
返回对象为响应体中数据转化成的对象,基本上可以理解为Json
![](https://i-blog.csdnimg.cn/blog_migrate/593b74961feb40445105dd7f4acd477a.png)
返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等
![](https://i-blog.csdnimg.cn/blog_migrate/2ace15d45308394c3f4b18b43319599a.png)
postForObject/postForEntity
![](https://i-blog.csdnimg.cn/blog_migrate/7aa640b960fc9959480eaa6e07ecdd02.png)
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
![](https://i-blog.csdnimg.cn/blog_migrate/fefa2163f0bc9217cfdc4ae4723265e8.png)
上面包下新建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已经被移除了 详细请看下面的大神写的
总结
很苦恼,因为ribbon已经在springcloud被废除了
所以不得不用LoadBalancer
来改,但是这就跟阳哥写的完全相悖了
注解位置也不一样,虽然负载也是一样写的,但是已经没必要去听了
所以明明还有40分钟的课我花了很长时间去将ribbon改成loadbalancer
然后,失败了
心态有点炸 主要是ribbon跟loadbalancer改规则的方式有区别,虽然看着别人的代码写了
但是实际上还有不断的小问题,懒得继续了,真到用的时候再学吧
已经废除了,学LoadBalancer更有用一点