HTTP状态码(记录)

HTTP状态码总的分为五类:

1开头:信息状态码

2开头:成功状态码

3开头:重定向状态码

4开头:客户端错误状态码

5开头:服务端错误状态码

 1XX:信息状态码

状态码 含义 描述
100 继续 初始的请求已经接受,请客户端继续发送剩余部分
101 切换协议 请求这要求服务器切换协议,服务器已确定切换

 2XX:成功状态码

状态码 含义 描述
200 成功 服务器已成功处理了请求
201 已创建 请求成功并且服务器创建了新的资源
202 已接受 服务器已接受请求,但尚未处理
203 非授权信息 服务器已成功处理请求,但返回的信息可能来自另一个来源
204 无内容 服务器成功处理了请求,但没有返回任何内容
205 重置内容 服务器处理成功,用户终端应重置文档视图
206 部分内容 服务器成功处理了部分GET请求

3XX:重定向状态码

状态码 含义 描述
300 多种选择 针对请求,服务器可执行多种操作
301 永久移动 请求的页面已永久跳转到新的url
302 临时移动 服务器目前从不同位置的网页响应请求,但请求仍继续使用原有位置来进行以后的请求
303 查看其他位置 请求者应当对不同的位置使用单独的GET请求来检索响应时,服务器返回此代码
304 未修改 自从上次请求后,请求的网页未修改过
305 使用代理 请求者只能使用代理访问请求的网页
307 临时重定向 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求

4XX:客户端错误状态码

状态码 含义 描述
400 错误请求 服务器不理解请求的语法
401 未授权 请求要求用户的身份演验证
403 禁止 服务器拒绝请求
404 未找到 服务器找不到请求的页面
405 方法禁用 禁用请求中指定的方法
406 不接受 无法使用请求的内容特性响应请求的页面
407 需要代理授权 请求需要代理的身份认证
408 请求超时 服务器等候请求时发生超时
409 冲突 服务器在完成请求时发生冲突
410 已删除 客户端请求的资源已经不存在
411 需要有效长度 服务器不接受不含有效长度表头字段的请求
412 未满足前提条件 服务器未满足请求者在请求中设置的其中一个前提条件
413 请求实体过大 由于请求实体过大,服务器无法处理,因此拒绝请求
414 请求url过长 请求的url过长,服务器无法处理
415 不支持格式 服务器无法处理请求中附带媒体格式
416 范围无效 客户端请求的范围无效
417 未满足期望 服务器无法满足请求表头字段要求

 

5XX:服务端错误状态码

状态码 含义 描述
500 服务器错误 服务器内部错误,无法完成请求
501 尚未实施 服务器不具备完成请求的功能
502 错误网关 服务器作为网关或代理出现错误
503 服务不可用 服务器目前无法使用
504 网关超时 网关或代理服务器,未及时获取请求
505 不支持版本 服务器不支持请求中使用的HTTP协议版本

spring-cloud搭建ribbon(负载均衡)

Spring cloud配置Ribbon用于负载君和,如果要在细节上配置更多,那么需要阅读一下官方文档。

* RoundRobinRule:轮询
* RandomRule:随机
* AvailabilityFilteringRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,以及并发的连接数量
*      超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问;
* WeightedResponseTimeRule: 根据平均响应时间计算所有服务的权重,响应时间越快,服务权重越大,被选中的机率越高;
*      刚启动时,如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够时,会切换到WeightedResponseTimeRule
* RetryRule: 先按照RoundRobinRule的策略获取服务,如果获取服务失败,则在指定时间内会进行重试,获取可用的服务;
* BestAvailableRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务;
* ZoneAvoidanceRule: 默认规则,复合判断server所在区域的性能和server的可用性选择服务器;

首先maven文件:

<?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>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.test</groupId>
    <artifactId>router</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>router</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.M3</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

配置文件:

server:
  address: 127.0.0.1
  port: 7001
  undertow:
    io-threads: 19 # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
    worker-threads: 24 # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
    buffer-size: 1024 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
    direct-buffers: true # 是否分配的直接内存
    always-set-keep-alive: true #socket-binding="http",保持长连接

spring:
  application:
    name: router-server
  profiles:
    active: test
  cloud:
    loadbalancer:
      retry:
        enabled: true #重试机制开启为true,关闭为false

eureka:
  instance:
    appname: router-server
    virtual-host-name: router-server
    secure-virtual-host-name: router-server
    instance-id: ${server.address}:router-server-peer:${server.port}
    hostname: localhost
#    non-secure-port: 6001 #非安全通信端口
#    non-secure-port-enabled: true #是否启用非安全端口接受请求
#    secure-port: 6444 #安全通信端口
#    secure-port-enabled: true #是否启用安全端口接受请求
    prefer-ip-address: false #是否优先使用IP地址作为主机名的标识,默认false
    lease-renewal-interval-in-seconds: 30 #eureka节点定时续约时间,默认30
    lease-expiration-duration-in-seconds: 90 #eureka节点剔除时间,默认90
  client:
    register-with-eureka: true #将自己注册到eureka注册中心,单节点关闭
    fetch-registry: true #从注册中心获取注册信息,单节点关闭
    registry-fetch-interval-seconds: 30 #从注册中心获取注册信息的时间间隔
    eureka-server-connect-timeout-seconds: 15
    eureka-server-read-timeout-seconds: 10
    service-url:
      defaultZone: http://${eureka.instance.hostname}:7000/eureka/ #注册到另外两个节点,实现集群

ribbon:
  eureka:
    enabled: true

注解开启服务:

@EnableEurekaClient
@SpringBootApplication
public class RouterApplication {

    public static void main(String[] args) {
        SpringApplication.run(RouterApplication.class, args);
    }

}

写一个RestTemplate服务层,用于公共接口转发:

package com.test.router.system.service;

import com.test.router.system.core.BaseService;
import com.test.router.system.core.ResultResp;
import com.test.router.system.service.resources.IAPIDispatcherService;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Map;

@Service
public class APIDispatcherServiceImpl extends BaseService implements IAPIDispatcherService {

    @Resource
    private RestTemplate restTemplate;


    @Override
    public ResultResp<Map<String, Object>> getForObject(String name, Object... uriVariables) {
        return restTemplate.getForObject("http://api-server/" + name, ResultResp.class);
    }

    @Override
    public ResultResp<Map<String, Object>> postForObject(String name, Map<String, Object> body) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> data = new HttpEntity<>(body,headers);

        ResponseEntity<ResultResp> resp = restTemplate.postForEntity("http://api-server/" + name , data, ResultResp.class);
        return resp.getBody();
    }

    @Override
    public ResultResp<Map<String, Object>> putForObject(String name, Integer id, Map<String, Object> body) {
        HttpEntity<Map<String, Object>> data = new HttpEntity<>(body);
        ResponseEntity<ResultResp> resp = restTemplate.exchange("http://api-server/" + name + "/{1}", HttpMethod.PUT, data, ResultResp.class, id);
        return resp.getBody();
    }

    @Override
    public ResultResp<Map<String, Object>> deleteForObject(String name, Integer id) {
        ResponseEntity<ResultResp> resp = restTemplate.exchange("http://api-server/" + name + "/{1}", HttpMethod.PUT, null, ResultResp.class, id);
        return resp.getBody();
    }
}

最后需要一个控制器,用于转发使用:

package com.test.router.app.v1;

import com.test.router.app.base.BaseV1Controller;
import com.test.router.constant.Constant;
import com.test.router.system.base.IDefaultRestController;
import com.test.router.system.core.ResultResp;
import com.test.router.system.model.http.Request;
import com.test.router.system.service.resources.IAPIDispatcherService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@RestController
public class TestController extends BaseV1Controller implements IDefaultRestController {


    @Resource
    private IAPIDispatcherService dispatcherService;

    /**
     * http://127.0.0.1:7001/v1/router?name=v2/test&namespace=api&user=avc
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/router", method = RequestMethod.GET)
    @Override
    public ResultResp<Map<String, Object>> doGet(HttpServletRequest request, HttpServletResponse response) {
        String namespace = request.getParameter("namespace");
        String name = request.getParameter("name");

        if (Constant.NAMESPACE_API.equals(namespace)) {
            Map<String, String> args = this.initUriVariables(name, request);
            StringBuffer sb = new StringBuffer();
            if (name.lastIndexOf("?") == -1) {
                name += "?";
            }
            sb.append(name);
            args.forEach((k, v) -> {
                sb.append(k).append("=").append(v).append("&");
            });
            return dispatcherService.getForObject(sb.toString(), null);
        }

        return new ResultResp<>();
    }

    /**
     * http://127.0.0.1:7001/v1/router?user=avc
     *
     *
     * {
     *     "header":{
     *         "namespace":"api",
     *         "name":"v2/test"
     *     },
     *     "payload":{
     *         "username":"张三",
     *         "age":15
     *     }
     * }
     * @param body
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/router", method = RequestMethod.POST)
    @Override
    public ResultResp<Map<String, Object>> doPost(@RequestBody Request<Map<String, Object>> body, HttpServletRequest request, HttpServletResponse response) {
        String namespace = body.getHeader().getNamespace();
        String name = body.getHeader().getName();

        if (Constant.NAMESPACE_API.equals(namespace)) {
            Map<String, String> args = this.initUriVariables(name, request);
            StringBuffer sb = new StringBuffer();
            if (name.lastIndexOf("?") == -1) {
                name += "?";
            }
            sb.append(name);
            args.forEach((k, v) -> {
                sb.append(k).append("=").append(v).append("&");
            });
            return dispatcherService.postForObject(sb.toString(), body.getPayload());
        }

        return new ResultResp<>();
    }

    @Override
    public ResultResp<Map<String, Object>> doPut(@PathVariable Integer id, @RequestBody Request<Map<String, Object>> obj, HttpServletRequest request, HttpServletResponse response) {
        return null;
    }

    @Override
    public ResultResp<Map<String, Object>> doDelete(@PathVariable Integer id, HttpServletRequest request, HttpServletResponse response) {
        return null;
    }
}

这样子基本上完成,主要使用浏览器打开http://127.0.0.1:7001/v1/router?name=v2/test&namespace=api&user=avc,就会根据name对应的值去获取api-service的对应的接口。

更多请参阅:

https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.2.0.RC1/reference/html/#spring-cloud-ribbon

spring-cloud搭建EurekaServer

Spring cloud配置EurekaServer很简单,如果要在细节上配置更多,那么需要阅读一下官方文档。

首先是maven:

<?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>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.test</groupId>
    <artifactId>server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.M3</spring-cloud.version>
    </properties>

    <dependencies>
        <!--        <dependency>-->
        <!--            <groupId>org.springframework.cloud</groupId>-->
        <!--            <artifactId>spring-cloud-bus</artifactId>-->
        <!--        </dependency>-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

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


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

其次就是配置:

server:
  address: 127.0.0.1
  port: 7000
  undertow:
    io-threads: 19
    worker-threads: 24
    buffer-size: 1024
    direct-buffers: true
    always-set-keep-alive: true

spring:
  application:
    name: eureka-server
  profiles:
    active: test


eureka:
  instance:
    appname: eureka-server
    virtual-host-name: eureka-server
    secure-virtual-host-name: eureka-server
#    non-secure-port: 6000
#    non-secure-port-enabled: true
#    secure-port: 6443
#    secure-port-enabled: true
    lease-renewal-interval-in-seconds: 15
    lease-expiration-duration-in-seconds: 45
    instance-id: ${server.address}:eureka-server-peer:${server.port}
    hostname: localhost
  client:
    register-with-eureka: true
    fetch-registry: true
    registry-fetch-interval-seconds: 30
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 1000

最后就是注解开启:

package com.test.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;


@EnableEurekaServer
@SpringBootApplication
public class ServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class, args);
    }

}

使用浏览器打开http://127.0.0.1:7000就可以看到效果了。

 

spring cloud服务发现注解@EnableDiscoveryClient与@EnableEurekaClient

使用服务发现的时候提到了两种注解,一种为@EnableDiscoveryClient,一种为@EnableEurekaClient,用法上基本一致,今天就来讲下两者,下文是从stackoverflow上面找到的对这两者的解释:

There are multiple implementations of “Discovery Service” (eureka, consul, zookeeper).
@EnableDiscoveryClient lives in spring-cloud-commons and picks the implementation on the classpath.
@EnableEurekaClient lives in spring-cloud-netflix and only works for eureka. If eureka is on your classpath, they are effectively the same.

意思也就是spring cloud中discovery service有许多种实现(eureka、consul、zookeeper等等),@EnableDiscoveryClient基于spring-cloud-commons, @EnableEurekaClient基于spring-cloud-netflix。

其实用更简单的话来说,就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

注解@EnableEurekaClient上有@EnableDiscoveryClient注解,可以说基本就是EnableEurekaClient有@EnableDiscoveryClient的功能,

另外上面的注释中提到,其实**@EnableEurekaClient**z注解就是一种方便使用eureka的注解而已,可以说使用其他的注册中心后,

都可以使用@EnableDiscoveryClient注解,但是使用@EnableEurekaClient的情景,就是在服务采用eureka作为注册中心的时候,使用场景较为单一。

@EnableEurekaClient
我们具体的对@EnableEurekaClient的源码看一下,如下:

/**
* Convenience annotation for clients to enable Eureka discovery configuration
* (specifically). Use this (optionally) in case you want discovery and know for sure that
* it is Eureka you want. All it does is turn on discovery and let the autoconfiguration
* find the eureka classes if they are available (i.e. you need Eureka on the classpath as
* well).
*
* @author Dave Syer
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableDiscoveryClient
public @interface EnableEurekaClient {

}

1111213141532
 
Copyright © 2008-2021 lanxinbase.com Rights Reserved. | 粤ICP备14086738号-3 |