声明式调用就像调用 本地方法 一样调用远程方法,无感知远程HTTP请求。
 1.SpringCloud的声明式调用,可以做到使用HTTP请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是 远程方法 。更 感知不到这是一个HTTP请求 。
 2.它像Dubbo一样,consumr直接调用接口方法调用provider,而不需要通过常规的Http Client构造请求再解析返回数据。
 3.它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。
 实现电商平台的基本操作
 
 
 <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.luyi</groupId>
    <artifactId>springcloud-ego-product-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-ego-product-service</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <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>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
复制代码 
 /**
 * 描述:     商品接口
 */
@RequestMapping("/product")
public interface ProductService {
    //查询所有商品
    @RequestMapping(value = "/findAll", method = RequestMethod.GET)
    public List<Product> findAll();
}
复制代码 
 /**
 * 描述:     商品实体
 */
public class Product {
    private Integer id;
    private String name;
    public Product() {
    }
    public Product(Integer id, String name) {
        this.id = id;
        this.name = 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;
    }
}
复制代码 
 <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.luyi</groupId>
    <artifactId>springcloud-ego-product-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-ego-product-provider</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <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.luyi</groupId>
            <artifactId>springcloud-ego-product-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
复制代码 
 spring.application.name=ego-product-provider server.port=9001 #设置服务注册中心地址,向所有注册中心做注册 eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/ 复制代码
/**
 * Product-Provider服务
 */
@RestController
public class ProductController implements ProductService {
    @Override
    public List<Product> findAll() {
        ArrayList<Product> list = new ArrayList<>();
        list.add(new Product(1, "电视"));
        list.add(new Product(2, "电脑"));
        list.add(new Product(3, "冰箱"));
        list.add(new Product(4, "手电筒"));
        return list;
    }
}
复制代码 
 @EnableEurekaClient
@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.luyi</groupId>
    <artifactId>springcloud-ego-product-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-ego-product-consumer</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <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.luyi</groupId>
            <artifactId>springcloud-ego-product-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
复制代码 
 spring.application.name=ego-product-consumer server.port=9002 #设置服务注册中心地址,向所有注册中心做注册 eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/ 复制代码
/**
 * Product-Consumer服务
 */
@RestController
public class ProductController {
    @Autowired
    private ProductConsumerService consumerService;
    /**
     * Consumer中查询所有商品的方法
     * @return
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public List<Product> list(){
        return consumerService.findAll();
    }
}
复制代码 
 //指定实现该接口的服务
@FeignClient(name = "ego-product-provider")
public interface ProductConsumerService extends ProductService {
}
复制代码 
 //添加如下两个注解开启对feign的支持
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
复制代码 
 //根据商品id查询商品
@RequestMapping(value = "/getProductById", method = RequestMethod.GET)
//RequestParam必须指定参数
public Product getProductById(@RequestParam("id") Integer id);
复制代码 
 @Override
public Product getProductById(Integer id) {
    return new Product(id, "SpringCloud");
}
复制代码 
 /**
 * Consumer中根据商品id查询商品
 */
@RequestMapping(value = "/get", method = RequestMethod.GET)
public Product getProduct(@RequestParam("id") Integer id){
    return consumerService.getProductById(id);
}
复制代码 
 //添加商品,传递多个参数,get方式
@RequestMapping(value = "/add", method = RequestMethod.GET)
public Product addProduct(@RequestParam("id") Integer id, @RequestParam("name") String name);
复制代码 
 @Override
public Product addProduct(Integer id, String name) {
    return new Product(id, name);
}
复制代码 
 /**
 * 商品添加,传递多个参数,get方式
 */
@RequestMapping(value = "/add", method = RequestMethod.GET)
public Product addProduct(Product product){
    return consumerService.addProduct(product.getId(), product.getName());
}
复制代码 
 //添加商品,传递多个参数,post方式 @RequestMapping(value = "/add2", method = RequestMethod.POST) public Product addProduct2(@RequestBody Product product); 复制代码
@Override
public Product addProduct2(@RequestBody Product product) {
    return product;
}
复制代码 
 /**
 * 商品添加,传递多个参数,post方式
 */
@RequestMapping(value = "/add2", method = RequestMethod.GET)
public Product addProduct2(Product product){
    return consumerService.addProduct2(product);
}
复制代码 
  gzip原理:gzip是一种 数据格式 ,采用deflate算法压缩数据,gzip是一种流行的文件压缩算法,应用十分广泛,尤其是在Linux平台。
 gzip能力:当gzip压缩到一个 纯文本文件 时效果是非常明显的,大约可以减少70%以上的文件大小。
 gzip的作用:网络数据经过压缩后 也就较低了网络传输的字节数 ,最明显的就是 可以提高网页加载的速度 。网页加载速度加快的好处不言而喻,除了节省流量、改善用户的浏览体验外,另一个潜在的好处就是gzip与搜索引擎的提取工具有着更好的关系。例如Google就可以直接通过读取gzip文件来比普通手工抓取更快的检索网页。
 第一:客户端向服务器请求中带有: Accept-Encoding:gzip ,deflate字段,向服务器表示,客户端支持的压缩格式(gzip或者deflate),如果不发送该消息头,服务器是不会压缩的。
 第二:服务端在收到请求之后,如果发现请求头中含有Accept-Encoding字段,并且支持该类型的压缩,就对响应报文压缩之后返回给客户端。 并且携带Content-Encoding:gzip消息头 ,表示响应报文是根据该格式压缩过的。
 第三:客户端接收请求之后,先判断是否有 Content-Encoding:消息头 ,如果有,按改格式解压报文,否则按正常报文处理。
#配置请求GZIP压缩 feign.compression.request.enabled=true #配置响应GZIP压缩 feign.compression.respinse.enabled=true #配置压缩支持MIME TYPE feign.compression.request.mime-types=text/xml,application/xml,application/json #配置压缩数据大小的最小阈值,默认2048 feign.compression.request.min-request-size=512 复制代码
#-------------spring boot gzip #是否启用压缩 server.compression.enabled=true server.compression.mime-types=application/json,application/xml,text/html,text/xml,type/plain 复制代码
为什么http连接池能提高性能
 a.两台服务器建立http连接的过程是很复杂的过程,涉及到多个数据包的交换,并且也很消耗时间
 b.Http连接需要三次握手四次挥手,开销很大。这样的开销对于请求比较多但信息量又比较小的请求开销更大。
 a.如果我们直接采用http连接池,节约了大量三次握手四次挥手的时间,这样能大大提升吞吐量。
 b.feign的http客户端支持3种框架:HttpURLConnection、HttpClient、okhttp,默认是HttpURLConnection。
 c.传统的HttpURLConnection是JDK自带的,并不支持连接池,如果要实现连接池的机制。还需要自己来管理连接对象。对于网络请求这种底层相对复杂的操作,如果有可用的其他方案,也没有必要自己去管理连接对象。
 d.HttpClient相比于JDK自带的HttpURLConnection,它封装了访问http的请求头、参数、内容体、响应等等。它不仅使发送http请求变得容易,而且也方便开发人员测试接口(基于HTTP协议的),即提高了开发的效率,也方便提高代码的健壮性,另外高并发大量的请求的时候,还是用连接池提高吞吐量。
<!--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.0</version>
</dependency>
复制代码 
 #启用httpclient feign.httpclient.enabled=true 复制代码
/**
 * 描述:     商品接口
 */
@RequestMapping("/product")
public interface ProductService {
    //查询所有商品
    @RequestMapping(value = "/findAll", method = RequestMethod.GET)
    public List<Product> findAll();
    //根据商品id查询商品
    @RequestMapping(value = "/getProductById", method = RequestMethod.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, consumes = MediaType.APPLICATION_JSON_VALUE)
    public Product addProduct3(Product product);
}
复制代码 
   将输出日志级别设置为 DEBUG 
<!-- 日志输出级别 -->
<root level="DEBUG">
    <appender-ref ref="Stdout" />
    <appender-ref ref="RollingFile" />
</root>
复制代码 
 //添加如下两个注解开启对feign的支持
@EnableDiscoveryClient
@EnableFeignClients
@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的负载均衡底层用的就是Ribbon
#全局配置 #请求连接的超时时间,默认为1000ms ribbon.ConnectTimeout=5000 #处理请求的超时时间 ribbon.ReadTimeout=5000 复制代码
#局部配置 #对所有操作请求都进行重试 ego-product-provider.ribbon.OkToRetryOnAllOperations=true #对当前实例的重试次数 ego-product-provider.ribbon.MaxAutoRetries=2 #切换实例的重试次数 ego-product-provider.ribbon.MaxAutoRetriesNextServer=0 #请求连接的超时时间 ego-product-provider.ribbon.ConnectTimeout=3000 #请求处理的超时时间 ego-product-provider.ribbon.ReadTimeout=3000 复制代码