第一章 负载均衡 Ribbon

 
(Spring Cloud 高级)
 

一、 Ribbon 在微服务中的作用

 

1 什么是 Ribbon

 
1.Ribbon 是一个基于 Http 和 TCP 的客服端负载均衡工具,它是基于 Netflix Ribbon 实
现的。
2.它不像 spring cloud 服务注册中心、配置中心、API 网关那样独立部署,但是它几乎
存在于每个 spring cloud 微服务中。包括 feign 提供的声明式服务调用也是基于该 Ribbon
实现的。
3.ribbon 默认提供很多种负载均衡算法,例如 轮询、随机 等等。甚至包含自定义的负
载均衡算法。
 

2 Ribbon 解决了什么问题

 
他解决并提供了微服务的负载均衡的问题。
 

二、 集中式与进程内负载均衡的区别

 

1 负载均衡解决方案的分类

 
目前业界主流的负载均衡方案可分成两类:
 
第一类:集中式负载均衡, 即在 consumer 和 provider 之间使用独立的负载均衡设施(可
以是硬件,如 F5, 也可以是软件,如 nginx), 由该设施负责把 访问请求 通过某种策略转发
至 provider;
 
第二类:进程内负载均衡,将负载均衡逻辑集成到 consumer,consumer 从服务注册中
心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的 provider。
Ribbon 就属于后者,它只是一个类库,集成于 consumer 进程,consumer 通过它来获取
到 provider 的地址。
 
 

2 两种负载均衡方式结构图

三、 Ribbon 的入门案例

 
Ribbon 中对于集群的服务采用的负载均衡的策略默认的是轮询
 

1 Consumer

@Service
public class UserService {
@Autowired
private LoadBalancerClient loadBalancerClient;//ribbon 负
载均衡器
public List<User> getUsers(){
//选择调用的服务的名称
//ServiceInstance 封装了服务的基本信息,如 IP,端口
ServiceInstance si =
this.loadBalancerClient.choose("eureka-provider");
//拼接访问服务的 URL
StringBuffer sb = new StringBuffer();
//http://localhost:9090/user
sb.append("http://").append(si.getHost()).append(":").appen
d(si.getPort()).append("/user");
System.out.println(sb.toString());
//springMVC RestTemplate
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference<List<User>> type = new
ParameterizedTypeReference<List<User>>() {};
//ResponseEntity:封装了返回值信息
ResponseEntity<List<User>> response =
rt.exchange(sb.toString(),HttpMethod.GET, null, type);
List<User> list =response.getBody();
return list; } }

2 Consumer 的配置文件

spring.application.name=eureka-consumer
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/

3 Provider 的集群部署

 

3.1将 provider 打包。部署到 linux 环境中

 

3.2创建启动脚本 server.sh

#!/bin/bash
cd `dirname $`
CUR_SHELL_DIR=`pwd`
CUR_SHELL_NAME=`basename ${BASH_SOURCE}`
JAR_NAME="springcloud-eureka-provider-0.0.1-SNAPSHOT.jar"
JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME
#JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m"
JAVA_MEM_OPTS=""
#SPRING_PROFILES_ACTIV="-Dspring.profiles.active=eureka2"
SPRING_PROFILES_ACTIV=""
LOG_DIR=$CUR_SHELL_DIR/logs
LOG_PATH=$LOG_DIR/${JAR_NAME%..log
echo_help()
{
echo -e "syntax: sh $CUR_SHELL_NAME start|stop"
}
if [ -z $ ];then
echo_help
exit
fi
if [ ! -d "$LOG_DIR" ];then
mkdir "$LOG_DIR"
fi
if [ ! -f "$LOG_PATH" ];then
touch "$LOG_DIR"
fi
if [ "$1" == "start" ];then
# check server
PIDS=`ps --no-heading -C java -f --width | grep $JAR_NAME | awk '{print $2}'`
if [ -n "$PIDS" ]; then
echo -e "ERROR: The $JAR_NAME already started and the PID is ${PIDS}."
exit
fi
echo "Starting the $JAR_NAME..."
# start
nohup java $JAVA_MEM_OPTS -jar $SPRING_PROFILES_ACTIV $JAR_PATH >>
$LOG_PATH >& &
COUNT=
while [ $COUNT -lt ]; do
sleep
COUNT=`ps --no-heading -C java -f --width | grep "$JAR_NAME" | awk
'{print $2}' | wc -l`
if [ $COUNT -gt ]; then
break
fi
done
PIDS=`ps --no-heading -C java -f --width | grep "$JAR_NAME" | awk '{print
$}'`
echo "${JAR_NAME} Started and the PID is ${PIDS}."
echo "You can check the log file in ${LOG_PATH} for details."
elif [ "$1" == "stop" ];then
PIDS=`ps --no-heading -C java -f --width | grep $JAR_NAME | awk '{print $2}'`
if [ -z "$PIDS" ]; then
echo "ERROR:The $JAR_NAME does not started!"
exit
fi
echo -e "Stopping the $JAR_NAME..."
for PID in $PIDS; do
kill $PID > /dev/null >&
done
COUNT=
while [ $COUNT -lt ]; do
sleep
COUNT=
for PID in $PIDS ; do
PID_EXIST=`ps --no-heading -p $PID`
if [ -n "$PID_EXIST" ]; then
COUNT=
break
fi
done
done
echo -e "${JAR_NAME} Stopped and the PID is ${PIDS}."
else
echo_help
exit
fi

4 启动 Consumer

四、 Ribbon 的常见负载均衡策略

五、 Ribbon 指定其他负载均衡策略

 

1 修改代码更换负载均衡策略

 

1.1创建项目

1.2在启动类中添加创建负载均衡策略对象的方法

@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
区域敏感性策略 ZoneAvoidanceRule:
.以一个区域为单位考察可
用性,对于不可用的区域整个丢 弃,从剩下区域中选可用的
provider
.如果这个 ip 区域内有一个或多
个实例不可达或响应变慢,都会降
低该 ip 区域内其他 ip 被选中的权 重。
@Bean
public RandomRule createRule(){
return new RandomRule();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

2 修改配置文件更换负载均衡策略

#设置负载均衡策略 eureka-provider 为调用的服务的名称
eureka-provider.ribbon.NFLoadBalancerRuleClassName=com.netf
lix.loadbalancer.RandomRule

六、 Ribbon 的点对点直连

2 去掉 Eureka 的坐标添加 Ribbon 坐标

<!-- ribbon 坐标 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

3 修改配置文件去掉与 Eureka 相关的配置,添加新配置项

spring.application.name=eureka-consumer-LB
server.port=
#禁用 eureka
ribbon.eureka.enabled=false
#指定具体的服务实例清单
eureka-provider.ribbon.listOfServers=192.168.70.137:

4 修改启动类去掉报错代码

@SpringBootApplication
public class ConsumerApplication {
/*@Bean
public RandomRule createRule(){
return new RandomRule();
}*/
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

第二章 声明式服务调用 Feign

 
(Spring Cloud 高级)
 

一、 什么是 Feign

 
Feign 是一种声明式、模板化的 HTTP 客户端(仅在 consumer 中使用)。
 

二、 什么是声明式,有什么作用,解决什么问题?

 
声明式调用就像调用本地方法一样调用远程方法;无感知远程 http 请求。
 
1,Spring Cloud 的声明式调用, 可以做到使用 HTTP 请求远程服务时能就像调用本地
方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。
 
2,它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的
Http Client 构造请求再解析返回数据。
 
3,它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细
节,更无需关注分布式环境开发。
 

三、 编写 Feign 的入门案例

1 需求

 
实现 Ego 电商平台中的商品基本操作
 

2 项目设计

3 创建项目

 

3.1创建 Product-Service

 

3.1.1创建项目

3.1.2修改 pom 文件添加依赖

<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">
<modelVersion>4.0.</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>springcloud-ego-product-service</artifactId> <version>0.0.-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
</project>

3.1.3创建 Service 接口

/**
* Product 服务接口
* @author Administrator
*
*/
@RequestMapping("/product")
public interface ProductService {
//查询所有商品
@RequestMapping(value="/findAll",method=RequestMethod.GE
T)
public List<Product> findAll();
}

3.1.4创建 POJO 类

public class Product {
private Integer id;
private String name;
public Integer getId() {
return id; }
public void setId(Integer id) {
this.id = id; }
public String getName() {
return name; }
public void setName(String name) {
this.name = name; }
public Product(Integer id, String name) {
super();
this.id = id;
this.name = name; }
public Product() {
super();
// TODO Auto-generated constructor stub
} }

3.2创建 Product-Provider

 

3.2.1创建项目

3.2.2修改 pom 文件添加依赖

<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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-ego-product-provider</artifactId
> <version>0.0.-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 添加 product-service 坐标 -->
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>springcloud-ego-product-service</artifactId>
<version>0.0.-SNAPSHOT</version>
</dependency>
</dependencies> <build> <plugins>
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

3.2.3添加全局配置文件

spring.application.name=ego-product-provider
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/

3.2.4编写 Controller

/**
* Product-Provider 服务
* @author Administrator
*
*/
@RestController
public class ProductController implements ProductService {
@Override
public List<Product> findAll() {
List<Product> list = new ArrayList<>();
list.add(new Product(, "电视"));
list.add(new Product(, "电脑"));
list.add(new Product(, "冰箱"));
list.add(new Product(, "手电筒"));
return list; } }

3.2.5编写 SpringBoot 的启动类

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

3.3创建 Product-consumer

3.3.1创建项目

3.3.2修改 pom 文件添加依赖

<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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-ego-product-consumer</artifactId
> <version>0.0.-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 添加 Feign 坐标 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- 添加 product-service 坐标 -->
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>springcloud-ego-product-service</artifactId>
<version>0.0.-SNAPSHOT</version>
</dependency>
</dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

3.3.3添加全局配置文件

spring.application.name=ego-product-consumer
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/

3.3.4编写 Controller

/**
* Product Consumer 服务
* @author Administrator
*
*/
@RestController
public class ProductController {
@Autowired
ProductConsumerService consumerservice;
/**
* Consumer 中的查询所有商品的方法
* @return
*/
@RequestMapping(value="/list",method=RequestMethod.GET)
public List<Product> getAll(){
return this.consumerservice.findAll();
} }

3.3.5编写 Service 接口

@FeignClient(name="ego-product-provider")
public interface ProductConsumerService extends
ProductService{
}

3.3.6编写 SpringBoot 启动类

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

四、 Feign 的请求参数处理

1 单个参数处理
 
1.1修改 Product-Service
 
 
/**
* Product 服务接口
* @author Administrator
*
*/
@RequestMapping("/product")
public interface ProductService {
//查询所有商品
@RequestMapping(value="/findAll",method=RequestMethod.GE
T)
public List<Product> findAll();
//根据商品 ID 查询商品
@RequestMapping(value="/getProductById",method=RequestMe
thod.GET)
public Product getProductById(@RequestParam("id") Integer
id);
}
1.2修改 Product-Provider
/**
* Product-Provider 服务
* @author Administrator
*
*/
@RestController
public class ProductController implements ProductService {
@Override
public List<Product> findAll() {
List<Product> list = new ArrayList<>();
list.add(new Product(, "电视"));
list.add(new Product(, "电脑"));
list.add(new Product(, "冰箱"));
list.add(new Product(, "手电筒"));
return list; }
@Override
public Product getProductById(Integer id) {
return new Product(id, "SpringCloud");
} }
1.3修改 Product-Consumer 
/**
* Product Consumer 服务
* @author Administrator
*
*/
@RestController
public class ProductController {
@Autowired
ProductConsumerService consumerservice;
/**
* Consumer 中的查询所有商品的方法
* @return
*/
@RequestMapping(value="/list",method=RequestMethod.GET)
public List<Product> getAll(){
return this.consumerservice.findAll();
}
/**
* Consumer 中根据商品 id 查询商品
*/
@RequestMapping(value="/get",method=RequestMethod.GET)
public Product getProduct(@RequestParam("id") Integer id){
return this.consumerservice.getProductById(id);
} }
2 多个参数处理
 
2.1方式一 GET 提交方式
 
2.1.1修改 Product-Service
/**
* Product 服务接口
* @author Administrator
*
*/
@RequestMapping("/product")
public interface ProductService {
//查询所有商品
@RequestMapping(value="/findAll",method=RequestMethod.GE
T)
public List<Product> findAll();
//根据商品 ID 查询商品
@RequestMapping(value="/getProductById",method=RequestMe
thod.GET)
public Product getProductById(@RequestParam("id") Integer
id);
//添加商品传递多个参数 方式一 :GET 方式
@RequestMapping(value="/add",method=RequestMethod.GET)
public Product addProduct(@RequestParam("id") Integer
id,@RequestParam("name") String name);
}
 
 
2.1.2修改 Product-Provider
/**
* Product-Provider 服务
* @author Administrator
*
*/
@RestController
public class ProductController implements ProductService {
@Override
public List<Product> findAll() {
List<Product> list = new ArrayList<>();
list.add(new Product(, "电视"));
list.add(new Product(, "电脑"));
list.add(new Product(, "冰箱"));
list.add(new Product(, "手电筒"));
return list; }
@Override
public Product getProductById(Integer id) {
return new Product(id, "SpringCloud");
}
@Override
public Product addProduct(Integer id, String name) {
return new Product(id, name);
}
2.1.3修改 Product-Consumer
/**
* Product Consumer 服务
* @author Administrator
*
*/
@RestController
public class ProductController {
@Autowired
ProductConsumerService consumerservice;
/**
* Consumer 中的查询所有商品的方法
* @return
*/
@RequestMapping(value="/list",method=RequestMethod.GET)
public List<Product> getAll(){
return this.consumerservice.findAll();
}
/**
* Consumer 中根据商品 id 查询商品
*/
@RequestMapping(value="/get",method=RequestMethod.GET)
public Product getProduct(@RequestParam("id") Integer id){
return this.consumerservice.getProductById(id);
}
/**
* 商品添加 传递多个参数。方式一:GET
*/
@RequestMapping(value="/add",method=RequestMethod.GET)
public Product addProduct(Product product){
return
this.consumerservice.addProduct(product.getId(),
product.getName());
} }

2.2方式二 POST 提交方式

 
2.2.1修改 Product-Service
/**
* Product 服务接口
* @author Administrator
*
*/
@RequestMapping("/product")
public interface ProductService {
//查询所有商品
@RequestMapping(value="/findAll",method=RequestMethod.GE
T)
public List<Product> findAll();
//根据商品 ID 查询商品
@RequestMapping(value="/getProductById",method=RequestMe
thod.GET)
public Product getProductById(@RequestParam("id") Integer
id);
//添加商品传递多个参数 方式一 :GET 方式
@RequestMapping(value="/add",method=RequestMethod.GET)
public Product addProduct(@RequestParam("id") Integer
id,@RequestParam("name") String name);
//添加商品传递多个参数 方式二 :POST 方式
@RequestMapping(value="/add",method=RequestMethod.POST)
public Product addProduct2(@RequestBody Product product);
}
2.2.2修改 Product-Provider
/**
* Product-Provider 服务
* @author Administrator
*
*/
@RestController
public class ProductController implements ProductService {
@Override
public List<Product> findAll() {
List<Product> list = new ArrayList<>();
list.add(new Product(, "电视"));
list.add(new Product(, "电脑"));
list.add(new Product(, "冰箱"));
list.add(new Product(, "手电筒"));
return list; }
@Override
public Product getProductById(Integer id) {
return new Product(id, "SpringCloud"); }
@Override
public Product addProduct(Integer id, String name) {
return new Product(id, name);
}
@Override
public Product addProduct2(@RequestBody Product product) {
return product;
} }
2.2.3修改 Product-Consumer 
/**
* Product Consumer 服务
* @author Administrator
*
*/
@RestController
public class ProductController {
@Autowired
ProductConsumerService consumerservice;
/**
* Consumer 中的查询所有商品的方法
* @return
*/
@RequestMapping(value="/list",method=RequestMethod.GET)
public List<Product> getAll(){
return this.consumerservice.findAll();
}
/**
* Consumer 中根据商品 id 查询商品
*/
@RequestMapping(value="/get",method=RequestMethod.GET)
public Product getProduct(@RequestParam("id") Integer id){
return this.consumerservice.getProductById(id);
}
/**
* 商品添加 传递多个参数。方式一:GET
*/
@RequestMapping(value="/add",method=RequestMethod.GET)
public Product addProduct(Product product){
return
this.consumerservice.addProduct(product.getId(),
product.getName());
}
/**
* 商品添加 传递多个参数。方式二:POST
*/
@RequestMapping(value="/add2",method=RequestMethod.GET)
public Product addProduct2(Product product){
return this.consumerservice.addProduct2(product);
} }

五、 Feign 的性能优化

 

1 通过 Gzip 压缩算法,提升网络通信速度

 

1.1gzip 介绍

 
gzip 介绍:gzip 是一种数据格式,采用用 deflate 算法压缩 data;gzip 是一种流行的文件
压缩算法,应用十分广泛,尤其是在 Linux 平台。
gzip 能力:当 Gzip 压缩到一个纯文本文件时,效果是非常明显的,大约可以减少 70%以上的文件大小。
gzip 作用:网络数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可
以加快网页加载的速度。网页加载速度加快的好处不言而喻,除了节省流量,改善用户的浏
览体验外,另一个潜在的好处是 Gzip 与搜索引擎的抓取工具有着更好的关系。例如 Google
就可以通过直接读取 gzip 文件来比普通手工抓取 更快地检索网页。
 

1.2HTTP 协议中关于压缩传输的规定

 
第一:客户端向服务器请求中带有:Accept-Encoding:gzip, deflate 字段,向服务器表示,
客户端支持的压缩格式(gzip 或者 deflate),如果不发送该消息头,服务器是不会压缩的。
第二:服务端在收到请求之后,如果发现请求头中含有 Accept-Encoding 字段,并且支
持该类型的压缩,就对响应报文压缩之后返回给客户端,并且携带 Content-Encoding:gzip 消
息头,表示响应报文是根据该格式压缩过的。
第三:客户端接收到请求之后,先判断是否有 Content-Encoding 消息头,如果有,按该
格式解压报文。否则按正常报文处理。
 

2 编写支持 Gzip 压缩案例

2.2修改配置文件

 

2.2.1只配置 Consumer 通过 Feign 到 Provider 的请求与相应

的 Gzip 压缩

#-----------------------------feign gzip
#配置请求 GZIP 压缩
feign.compression.request.enabled=true
#配置响应 GZIP 压缩
feign.compression.response.enabled=true
#配置压缩支持的 MIME TYPE
feign.compression.request.mime-types=text/xml,application/x
ml,application/json
#配置压缩数据大小的最小阀值,默认
feign.compression.request.min-request-size=

2.2.2对客户端浏览器的请求以及 Consumer 对 provider 的请

求与响应做 Gzip 压缩

#-----------------------------spring boot gzip
#是否启用压缩
server.compression.enabled=true
server.compression.mime-types=application/json,application/
xml,text/html,text/xml,text/plain

3 采用 Http 连接池,提升 Feign 的并发吞吐量

 
为什么 http 连接池能提升性能?
 

3.1http 的背景原理

 
a. 两台服务器建立 http 连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并
且也很耗时间。
b. Http 连接需要的 3 次握手 4 次分手开销很大,这一开销对于大量的比较小的 http 消
息来说更大。
 

3.2优化解决方案

 
a. 如果我们直接采用 http 连接池,节约了大量的 3 次握手 4 次分手;这样能大大提升吞
吐率。
b. feign 的 http 客户端支持 3 种框架;HttpURLConnection、httpclient、okhttp;默认是
HttpURLConnection。
c. 传统的 HttpURLConnection 是 JDK 自带的,并不支持连接池,如果要实现连接池的
机制,还需要自己来管理连接对象。对于网络请求这种底层相对复杂的操作,如果有可用的
其他方案,也没有必要自己去管理连接对象。
d. HttpClient 相比传统 JDK 自带的 HttpURLConnection,它封装了访问 http 的请求头,
参数,内容体,响应等等;它不仅使客户端发送 HTTP 请求变得容易,而且也方便了开发人
员测试接口(基于 Http 协议的),即提高了开发的效率,也方便提高代码的健壮性;另外
高并发大量的请求网络的时候,还是用“连接池”提升吞吐量
 

4 将 Feign 的 Http 客户端工具修改为 HttpClient

 

4.1创建项目

4.2修改 pom 文件添加 HttpClient 的坐标
 
<!-- 使用Apache HttpClient替换Feign原生httpURLConnection -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>8.17.</version>
</dependency>

4.3修改配置文件开启 HttpClient 的使用

 
#启用 httpclient
feign.httpclient.enabled=true
注意:如果使用 HttpClient 作为 Feign 的客户端工具。那么在定义接口上的注解是需要
注意,如果传递的是一个自定义的对象(对象会使用 json 格式来专递)。需要制定类型。
 

4.4Product-Service

/**
* Product 服务接口* @author Administrator
*
*/
@RequestMapping("/product")
public interface ProductService {
//查询所有商品
@RequestMapping(value="/findAll",method=RequestMethod.GE
T)
public List<Product> findAll();
//根据商品 ID 查询商品
@RequestMapping(value="/getProductById",method=RequestMe
thod.GET)
public Product getProductById(@RequestParam("id") Integer
id);
//添加商品传递多个参数 方式一 :GET 方式
@RequestMapping(value="/add",method=RequestMethod.GET)
public Product addProduct(@RequestParam("id") Integer
id,@RequestParam("name") String name);
//----------------------Httpclient----------------------
------------------------
//添加商品传递多个参数 方式二 :POST 方式
@RequestMapping(value="/add2",method=RequestMethod.POST,
consumes=MediaType.APPLICATION_JSON_VALUE)
public Product addProduct2(@RequestBody Product product);
//使用 HttpClient 工具 添加商品传递多个参数 :基于 GET 方式
@RequestMapping(value="/add3",method=RequestMethod.GET,c
onsumes=MediaType.APPLICATION_JSON_VALUE)
public Product addProduct3(Product product);
}
 
 

六、 查看微服务日志中记录每个接口 URL,状态码和耗时信息

 

1 创建项目

2 添加 logback.xml 文件

3 Logback 的输出日志级别需要时 debug 级别

<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="Stdout" />
<appender-ref ref="RollingFile" />
</root>

4 在启动类中添加一个方法

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
// NONE:不记录任何信息,默认值
// BASIC:记录请求方法、请求 URL、状态码和用时
// HEADERS:在 BASIC 基础上再记录一些常用信息
// FULL:记录请求和相应的所有信息
@Bean
public Logger.Level getLog(){
return Logger.Level.FULL; }
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

七、 配置 Feign 负载均衡请求超时时间

 
Feign 的负载均衡底层用的就是 Ribbon

1 修改配置文件,设置超时时间
               consumer里面配置
1.1全局配置
#全局配置
# 请求连接的超时时间 默认的时间为 秒
ribbon.ConnectTimeout=
# 请求处理的超时时间
ribbon.ReadTimeout=
1.2根据服务名称进行局部超时配置
#局部配置
# 对所有操作请求都进行重试
ego-product-provider.ribbon.OkToRetryOnAllOperations=true
# 对当前实例的重试次数
ego-product-provider.ribbon.MaxAutoRetries=
# 切换实例的重试次数
ego-product-providert.ribbon.MaxAutoRetriesNextServer=
# 请求连接的超时时间
ego-product-provider.ribbon.ConnectTimeout=
# 请求处理的超时时间
ego-product-provider.ribbon.ReadTimeout=

1.2修改 pom 文件添加 hystrix 的坐标

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

1.3修改配置文件

 
spring.application.name=eureka-consumer-ribbon-hystrix
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/
 
 

1.4修改启动类开启熔断器

 
@EnableCircuitBreaker //开启熔断器 断路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
}
}

1.5在项目中添加 Product 实体类

public class Product {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Product(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Product() {
super();
// TODO Auto-generated constructor stub
}
}

1.6修改 ProductService

 
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;// ribbon 负
载均衡器
@HystrixCommand(fallbackMethod="fallback")
public List<Product> getUsers() {
// 选择调用的服务的名称
// ServiceInstance 封装了服务的基本信息,如 IP,端口
ServiceInstance si =
this.loadBalancerClient.choose("ego-product-provider");
// 拼接访问服务的 URL
StringBuffer sb = new StringBuffer();
// http://localhost:9001/product/findAll
sb.append("http://").append(si.getHost()).append(":").appen
d(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
// springMVC RestTemplate
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new
ParameterizedTypeReference<List<Product>>() {
};
// ResponseEntity:封装了返回值信息
ResponseEntity<List<Product>> response =
rt.exchange(sb.toString(), HttpMethod.GET, null, type);
List<Product> list = response.getBody();
return list;
}
//返回托底数据的方法
public List<Product> fallback(){
List<Product> list = new ArrayList<>();
list.add(new Product(-, "我是托底数据"));
return list;
}}

1.7以下四种情况将触发 getFallback 调用

 
(1) 方法抛出非 HystrixBadRequestException 异常。
(2) 方法调用超时
(3) 熔断器开启拦截调用
(4) 线程池/队列/信号量是否跑满
 

2 请求缓存

 
Hystrix 为了降低访问服务的频率,支持将一个请求与返回结果做缓存处理。如果再次
请求的 URL 没有变化,那么 Hystrix 不会请求服务,而是直接从缓存中将结果返回。这样可
以大大降低访问服务的压力。
 
Hystrix 自带缓存。有两个缺点:
 
1. 是一个本地缓存。在集群情况下缓存是不能同步的。
2. 不支持第三方缓存容器。Redis,memcache 不支持的。
 
可以使用 spring 的 cache。
 

2.1安装 Redis

 
2.2创建项目

2.3修改 pom 文件添加 springCache 坐标

<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-eureka-consumer-ribbon-cache</ar
tifactId> <version>0.0.-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-eureka-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<!-- springCache --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

2.4在配置文件中配置 redis 链接信息

spring.application.name=eureka-consumer-ribbon-cache
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/
# Redis
spring.redis.database=
#Redis 服务器地址
spring.redis.host=192.168.70.139
#Redis 服务器连接端口
spring.redis.port=
#Redis 服务器连接密码(默认为空)
spring.redis.password= #连接池最大连接数(负值表示没有限制)
spring.redis.pool.max-active=
#连接池最大阻塞等待时间(负值表示没有限制)
spring.redis.pool.max-wait=
#连接池最大空闭连接数
spring.redis.pool.max-idle=
#连接汉最小空闲连接数
spring.redis.pool.min-idle=
#连接超时时间(毫秒)
spring.redis.pool.timeout=

2.5修改启动类开启缓存

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

2.6修改 ProductService

@CacheConfig(cacheNames={"com.bjsxt.ego.product"})
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;// ribbon 负
载均衡器
@HystrixCommand(fallbackMethod="fallback")
public List<Product> getUsers() {
// 选择调用的服务的名称
// ServiceInstance 封装了服务的基本信息,如 IP,端口
ServiceInstance si =
this.loadBalancerClient.choose("ego-product-provider");
// 拼接访问服务的 URL
StringBuffer sb = new StringBuffer();
// http://localhost:9001/product/findAll
sb.append("http://").append(si.getHost()).append(":").appen
d(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
// springMVC RestTemplate
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new
ParameterizedTypeReference<List<Product>>() {
};
// ResponseEntity:封装了返回值信息
ResponseEntity<List<Product>> response =
rt.exchange(sb.toString(), HttpMethod.GET, null, type);
List<Product> list = response.getBody();
return list; }
//返回托底数据的方法
public List<Product> fallback(){
List<Product> list = new ArrayList<>();
list.add(new Product(-, "我是托底数据"));
return list; }
//根据 ID 查询商品
@Cacheable(key="'product' + #id")
public Product getProductById(Integer id){
System.out.println("=========Get======"+id);
return new Product(id, "新的商品");
}
//根据 ID 删除商品
@CacheEvict(key="'product' + #id")
public void delProductById(Integer id){
System.out.println("=========Del======"+id);
} }

2.7修改 ProductController

@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")
public List<Product> getUsers() {
return this.userService.getUsers();
}
@RequestMapping(value="/get",method=RequestMethod.GET)
public Product get(Integer id){
return this.userService.getProductById(id);
}
@RequestMapping(value="/del",method=RequestMethod.GET)
public void del(Integer id){
this.userService.delProductById(id);
} }

3 请求合并

 
没合并的请求

请求合并

3.2修改 pom 文件添加 hystrix 坐标

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

3.3修改配置文件

spring.application.name=eureka-consumer-ribbon-batch
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/
 
 

3.4修改 ProductService

@Service
public class ProductService {
//利用 hystrix 合并请求
@HystrixCollapser(batchMethod = "batchProduct", scope =
com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL, collapserProperties = { //请求时间间隔在 20ms 之内的请求会被合并为一个请求,默认
为 10ms @HystrixProperty(name =
"timerDelayInMilliseconds", value = ""),
//设置触发批处理执行之前,在批处理中允许的最大请求
数。
@HystrixProperty(name = "maxRequestsInBatch",
value = ""),
})
//consumer 的 controller 调用的方法 该方法返回值必须要返回
Future 类型
public Future<Product> getProduct(Integer id){
System.out.println("=========="+id+"==========");
return null;
}
@HystrixCommand
//调用 Provider 服务的方法
public List<Product> batchProduct(List<Integer> ids){
for(Integer id:ids){
System.out.println(id);
}
//假设是调用 provider 服务后返回的 list
List<Product> list = new ArrayList<>();
list.add(new Product(, "电视"));
list.add(new Product(, "电脑"));
list.add(new Product(, "冰箱"));
list.add(new Product(, "手电筒"));
list.add(new Product(,"list............"));
System.out.println("ddddddddddddddddddddddd");
return list;
}
}

3.5修改 Controller

@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")public void getUsers() throws Exception{
Future<Product> p1 = this.userService.getProduct();
Future<Product> p2 = this.userService.getProduct();
Future<Product> p3 = this.userService.getProduct();
System.out.println(p1.get().toString());
System.out.println(p2.get().toString());
System.out.println(p3.get().toString());
}
}

4 服务熔断

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

4.3修改配置文件

spring.application.name=eureka-consumer-ribbon-breaker
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/

4.4修改启动类

@EnableCircuitBreaker //开启熔断器 断路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

4.5修改 ProductService

@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;// ribbon 负
载均衡器
@HystrixCommand(fallbackMethod = "fallback",
commandProperties = {
//默认 20 个;10s 内请求数大于 20 个时就启动熔断器,当请
求符合熔断条件时将触发 getFallback()。 @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER
_REQUEST_VOLUME_THRESHOLD,
value=""),
//请求错误率大于 50%时就熔断,然后 for 循环发起请求,
当请求符合熔断条件时将触发 getFallback()。 @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER
_ERROR_THRESHOLD_PERCENTAGE,
value=""),
//默认 5 秒;熔断多少秒后去尝试请求 @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER
_SLEEP_WINDOW_IN_MILLISECONDS,
value=""),
})
public List<Product> getUsers(int flag) {
System.out.println(flag);
if(flag == ){
throw new RuntimeException();
}
// 选择调用的服务的名称
// ServiceInstance 封装了服务的基本信息,如 IP,端口
ServiceInstance si =
this.loadBalancerClient.choose("ego-product-provider");
// 拼接访问服务的 URL
StringBuffer sb = new StringBuffer();
// http://localhost:9001/product/findAll
sb.append("http://").append(si.getHost()).append(":").appen
d(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
// springMVC RestTemplate
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new
ParameterizedTypeReference<List<Product>>() {
};
// ResponseEntity:封装了返回值信息
ResponseEntity<List<Product>> response =
rt.exchange(sb.toString(), HttpMethod.GET, null, type);
List<Product> list = response.getBody();
return list; }
//返回托底数据的方法
public List<Product> fallback(int flag){
List<Product> list = new ArrayList<>();
list.add(new Product(-, "我是托底数据"));
return list; } }

4.6修改 ProductController

@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")
public List<Product> getUsers(@RequestParam("flag")
Integer flag){
return this.userService.getUsers(flag);
} }

5.1.2修改 pom 添加 hystrix 坐标

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

5.1.3修改配置文件

spring.application.name=eureka-consumer-ribbon-threadpool
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/

5.1.4修改启动类

@EnableCircuitBreaker //开启熔断器 断路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

5.1.5修改 ProductService

@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;// ribbon 负
载均衡器
@HystrixCommand(groupKey="ego-product-provider",
commandKey = "getUsers",
threadPoolKey="ego-product-provider",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value =
""),//线程池大小
@HystrixProperty(name = "maxQueueSize",
value = ""),//最大队列长度
@HystrixProperty(name =
"keepAliveTimeMinutes", value = ""),//线程存活时间
@HystrixProperty(name =
"queueSizeRejectionThreshold", value = "")//拒绝请求
},
fallbackMethod = "fallback")
public List<Product> getUsers() {
System.out.println(Thread.currentThread().getName());
// 选择调用的服务的名称
// ServiceInstance 封装了服务的基本信息,如 IP,端口
ServiceInstance si =
this.loadBalancerClient.choose("ego-product-provider");
// 拼接访问服务的 URL
StringBuffer sb = new StringBuffer();
// http://localhost:9001/product/findAll
sb.append("http://").append(si.getHost()).append(":").appen
d(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
// springMVC RestTemplate
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new
ParameterizedTypeReference<List<Product>>() {
};
// ResponseEntity:封装了返回值信息
ResponseEntity<List<Product>> response =
rt.exchange(sb.toString(), HttpMethod.GET, null, type);
List<Product> list = response.getBody();
return list; }
//返回托底数据的方法
public List<Product> fallback(){
System.out.println(Thread.currentThread().getName());
List<Product> list = new ArrayList<>();
list.add(new Product(-, "我是托底数据"));
return list; }
public void showThread(){
System.out.println(Thread.currentThread().getName());
} }

5.1.6修改 ProductController

@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")
public List<Product> getUsers(){
return this.userService.getUsers();
}
@RequestMapping("/consumer1")
public void getUsers1(){
this.userService.showThread();
} }

5.2.2修改 pom 文件添加 hystrix 的坐标

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

5.2.3修改配置文件

spring.application.name=eureka-consumer-ribbon-semaphore
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/

5.2.5修改 ProductService

@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;// ribbon 负
载均衡器
@HystrixCommand(fallbackMethod = "fallback",
commandProperties = { @HystrixProperty(name=HystrixPropertiesManager.EXECUTION_ISOLA
TION_STRATEGY,
value="SEMAPHORE"),// 信号量 隔离
@HystrixProperty
(name=HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHOR
E_MAX_CONCURRENT_REQUESTS, value="")//信号量最大并度
})
public List<Product> getUsers() {
System.out.println(Thread.currentThread().getName());
// 选择调用的服务的名称
// ServiceInstance 封装了服务的基本信息,如 IP,端口
ServiceInstance si =
this.loadBalancerClient.choose("ego-product-provider");
// 拼接访问服务的 URL
StringBuffer sb = new StringBuffer();
// http://localhost:9001/product/findAll
sb.append("http://").append(si.getHost()).append(":").appen
d(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
// springMVC RestTemplate
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new
ParameterizedTypeReference<List<Product>>() {
};
// ResponseEntity:封装了返回值信息
ResponseEntity<List<Product>> response =
rt.exchange(sb.toString(), HttpMethod.GET, null, type);
List<Product> list = response.getBody();
return list; }
//返回托底数据的方法
public List<Product> fallback(){
System.out.println(Thread.currentThread().getName());
List<Product> list = new ArrayList<>();
list.add(new Product(-, "我是托底数据"));
return list; }
public void showThread(){
System.out.println(Thread.currentThread().getName());
} }

1.2修改配置文件开启对 hystrix 的支持

@Component
public class ProductServiceFallbackFactory implements
FallbackFactory<ProductConsumerService> {
Logger logger =
LoggerFactory.getLogger(ProductServiceFallbackFactory.class);
@Override
public ProductConsumerService create(final Throwable arg0)
{
return new ProductConsumerService() {
//能够返回托底数据的 fallback 方法
@Override
public List<Product> findAll() {
logger.warn("Fallback Exception: ",arg0);
List<Product> list = new ArrayList<>();
list.add(new Product(-, "我是托底数据"));
return list;
}
};
} }

2.3修改 ProductConsumerService

@FeignClient(name="ego-product-provider",fallbackFactory=Pr
oductServiceFallbackFactory.class)
public interface ProductConsumerService {
//查询所有商品
@RequestMapping(value="/product/findAll",method=RequestMeth
od.GET)
public List<Product> findAll();
}

五、 可视化的数据监控 Hystrix-dashboard

 
Hystrix-dashboard 是一款针对 Hystrix 进行实时监控的工具,通过 Hystrix
Dashboard 我们可以在直观地看到各 Hystrix Command 的请求响应时间, 请求成功率等数据。

<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-eureka-consumer-ribbon-dashboard
</artifactId> <version>0.0.-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-eureka-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties>
<project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId
>
</dependency>
</dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

3.修改启动类

@EnableCircuitBreaker //开启熔断器 断路器
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-eureka-consumer-ribbon-dashboard
</artifactId> <version>0.0.-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-eureka-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope> </dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId
>
</dependency>
</dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.3修改启动类
@EnableCircuitBreaker //开启熔断器 断路器
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

1.1修改 pom 文件添加 turbine 坐标

<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-eureka-consumer-turbine</artifac
tId> <version>0.0.-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-eureka-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding>
<project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId
>
</dependency>
<!-- 添加 turbine 坐标 -->
<dependency>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.2修改配置文件
spring.application.name=eureka-consumer-hystrix-turbine
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/
#---------------------------------------turbine------------
--------------
#配置 Eureka 中的 serviceId 列表,表明监控哪些服务
turbine.appConfig=eureka-consumer-ribbon-threadpool,springc
loud-eureka-consumer-feign-fallback
#指定聚合哪些集群,多个使用","分割,默认为 default。可使用
http://.../turbine.stream?cluster={clusterConfig 之一}访问
turbine.aggregator.clusterConfig= default
# . clusterNameExpression 指定集群名称,默认表达式 appName;此
时:turbine.aggregator.clusterConfig 需要配置想要监控的应用名称;
# . 当 clusterNameExpression: default 时,
turbine.aggregator.clusterConfig 可以不写,因为默认就是 default;
# . 当 clusterNameExpression: metadata['cluster']时,假设想要
监控的应用配置了 eureka.instance.metadata-map.cluster: ABC,
# 则需要配置,同时 turbine.aggregator.clusterConfig:
ABC
turbine.clusterNameExpression="default"
1.3修改启动类
@SpringBootApplication
@EnableTurbine
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class,
args);
}
}
2 使用 Turbine 聚合多个服务
2.1修改被聚合的项目的 pom 文件添加 dashboard 坐标
<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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-eureka-consumer-feign-fallback</
artifactId> <version>0.0.-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 添加 Feign 坐标 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- 添加 product-service 坐标 --> <dependency> <groupId>com.bjsxt</groupId> <artifactId>springcloud-ego-product-service</artifactId> <version>0.0.-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId
>
</dependency>
</dependencies> <build> <plugins>
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2修改被监控的服务的启动类
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
@EnableHystrixDashboard
@EnableCircuitBreaker //开启熔断器 断路器
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,
args);
} }

http://localhost:1002/turbine.stream

<?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">
<modelVersion>4.0.</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-eureka-consumer-ribbon-dashboard
-mq</artifactId> <version>0.0.-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-eureka-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding> <project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifac
tId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-stream</artifactId
>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
</dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt</groupId> <artifactId>springcloud-eureka-consumer-turbine-mq</arti
factId><version>0.0.-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-eureka-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5..RELEASE</version> <relativePath /> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-</project.build.sourceEn
coding>
<project.reporting.outputEncoding>UTF-</project.reporting.
outputEncoding> <java.version>1.8</java.version>
</properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR5</version> <type>pom</type> <scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine-stream</artifactId
>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
</dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
7 修改 Turbine 的配置文件
spring.application.name=eureka-consumer-hystrix-turbine
server.port=
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eur
eka1:/eureka/,http://user:123456@eureka2:8761/eureka/
spring.rabbitmq.host=192.168.70.139
spring.rabbitmq.port=
spring.rabbitmq.username=oldlu
spring.rabbitmq.password=
spring.rabbitmq.virtualHost=/
8 修改 Turbine 的启动类
@SpringBootApplication
@EnableTurbineStream
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class,
args);
} }
 

springcloud高级的更多相关文章

  1. 《Java开发学习大纲文档》V7.0

    <Java开发学习大纲文档>V7.0简介: 本文档是根据企业开发所需要掌握的知识点大纲进行总结汇编,是Java开发工程师必备知识体系,系统化学习针对性非常强,逻辑分析能力非常清晰;技术方面 ...

  2. SpringCloud系列十:SpringCloudConfig 高级配置(密钥加密处理(JCE)、KeyStore 加密处理、SpringCloudConfig 高可用机制、SpringCloudBus 服务总线)

    1.概念:SpringCloudConfig 高级配置 2.具体内容 在 SpringCloudConfig 之中考虑到所有配置文件都暴露在远程仓库之中的安全性问题,所以提供有安全访问的处理机制,这样 ...

  3. 微服务SpringCloud+Docker入门到高级实战(教程详情)

    第一章 课程介绍和学习路线 1.微服务架构SpringCloud课程介绍 简介:课程介绍和课程大纲讲解,讲课风格和重点内容理解技巧 2.技术选型和学后水平 简介:课程所需基础和技术选型讲解,学完课程可 ...

  4. 微服务SpringCloud+Docker入门到高级实战(目录)

    第一章 课程介绍和学习路线 1.微服务架构SpringCloud课程介绍 简介:课程介绍和课程大纲讲解,讲课风格和重点内容理解技巧2.技术选型和学后水平 简介:课程所需基础和技术选型讲解,学完课程可以 ...

  5. springcloud(十一):服务网关Zuul高级篇

    时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...

  6. 跟我学SpringCloud | 第十篇:服务网关Zuul高级篇

    SpringCloud系列教程 | 第十篇:服务网关Zuul高级篇 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特殊说明,本系列教程全 ...

  7. 跟我学SpringCloud | 第十四篇:Spring Cloud Gateway高级应用

    SpringCloud系列教程 | 第十四篇:Spring Cloud Gateway高级应用 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 ...

  8. 小D课堂 - 新版本微服务springcloud+Docker教程_4-04 高级篇幅之服务间调用之负载均衡策略调整实战

    笔记 4.高级篇幅之服务间调用之负载均衡策略调整实战     简介:实战调整默认负载均衡策略实战 自定义负载均衡策略:http://cloud.spring.io/spring-cloud-stati ...

  9. Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上)

    Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上) Jenkins+Docker+SpringCloud持续集成流程说明 大致流程说明: 1) 开发 ...

随机推荐

  1. PHP date_isodate_set() 函数

    ------------恢复内容开始------------ 实例 设置 2013 年第 5 周的 ISO 日期: <?php$date=date_create();date_isodate_s ...

  2. PHP symlink() 函数

    定义和用法 symlink() 函数创建一个从指定名称连接的现存目标文件开始的符号连接. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 symlink(target,link) ...

  3. 7.12 NOI模拟赛 生成树 装压dp vector装压

    LINK:生成树 这场比赛我打的真失败 T3是比较容易的 却一直刚 那道"数论" 10分其实搜一下全排列. 30分容易想到对边进行装压dp. 不过存在一些细节 可以对于一个连通块的 ...

  4. 安装ElasticSearch遇到的深坑

    实验需要ES,安装过程中遇到一些奇葩的问题,记录下.下面介绍下安装步骤: 第一步:安装java ES是运行在java虚拟机上面的,所以首先需要安装java环境,安装过程不再赘述,唯一需要注意的是ES对 ...

  5. 服务治理框架dubbo中zookeeper的使用

    Zookeeper提供了一套很好的分布式集群管理的机制,就是它这猴子那个几月层次型的目录树的数据结构,并对书中的节点进行有效的管理,从而可以设计出多种多样的分布式的数据管理模型:下面简要介绍下zook ...

  6. Java动态代理(AOP)

    目录 一.代理 1. 什么是代理? 2. 使用代理模式的作用 3. 实现代理的方式 二.静态代理 1. 模拟用户购买u盘 2. 静态代理的缺点 三.动态代理 四. JDK 动态代理 1. Invoca ...

  7. Android 菜单的使用

    有时间就随笔记录自己遇到的问题和所学的知识哈. 这是对本牛崽知识的提升也可以给其他牛牛们来点鸡汤和开胃菜. 菜单Menu的创建 首先menu是属于布局的嘛,所以嘞,咱们得在res(也就是布局资源)创建 ...

  8. Docker初探之Windows篇

    一.什么是Docker? Docker是一个开源的应用容器引擎,可以轻松地为任何应用创建一个轻量级.可移植.自给自足的容器.开发者在本地编译测试通过的容器可以批量地在生产环境中部署,包括虚拟机和其他平 ...

  9. 有哪些开源的 Python 库让你相见恨晚?

    Arrow 我们知道 Python 已经内置了好几个处理时间相关的库,但是对于时间以及时区间的转换并不清晰,操作起来略繁琐,而 Arrow 可以弥补这个问题,它提供了更友好的方法,方便我们对时间,日期 ...

  10. 入门实践,Python数据分析

    1-2 Anaconda和Jupyter notebook介绍 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知 ...