Why SpringBoot?

SpringBoot is a new framework from the Pivotal team designed to simplify the initial setup and development process for new Spring applications. The framework uses a specific way to configure so that developers no longer need to define boilerplate configurations. In this way, Spring Boot aims to be a leader in the burgeoning field of rapid Application development.

  • Create a stand-alone Spring application

  • Embedded Tomcat without the need to deploy a WAR file

  • Simplifying Maven Configuration

  • Automatic Spring configuration

  • Provides production-ready functions such as metrics, health checks, and external configuration

  • There is absolutely no code generation and no configuration requirements for XML

Why Nginx?

  • An overview of the

    Nginx (Engine X) is an open source WWW service and proxy service software that supports high concurrency. Nginx was developed by Igor Sysoev, a Russian, and was initially applied to large Russian websites (www.rambler.ru). The author later open-source the source code for worldwide use under a bSD-like license. In terms of functional applications, Nginx is not only an excellent Web service software, but also has the functions of reverse proxy load balancing and caching. The reverse proxy load balancing is similar to LVS load balancing and HAProxy and other professional proxy software. Nginx is more convenient and simple to deploy. In terms of cache service function, there are professional cache service software like Squid. Nginx can run on UNIX, Linux, MS Windows Server, Mac OS X Server, Solaris and other operating systems.

  • Important features of Nginx

    1. High-speed node concurrent access and caching for static resources.
    2. Reverse proxy acceleration can be used, and data caching can be performed.
    3. Provides simple load balancing, node health check, and fault tolerance functions.
    4. Support cache acceleration for remote Fast CGI services.
    5. Support Fast CGI, Uwsgi, SCGI, Memcached Server acceleration and caching.
    6. Supports SSL, TLS, and SNI.
    7. Modular architecture.
    8. Filters include features such as Gzip compression, ranges support, chunked response, XSLT, SSL, and image scaling.
    9. In SSL filters, contain multiple SSL pages that can be processed in parallel if processed by Fast CGI or reverse proxy.
  • WWW service features of Nginx

    1. Supports virtual host configuration based on domain name, port, and IP address.
    2. Support KeepAlived and Piplined connections.
    3. It provides simple, convenient, and flexible configuration and management.
    4. Nginx configuration can be modified, and when the code is online, it can be smoothly restarted without interrupting service access.
    5. Customize log access formats, temporary buffer log writing operations, fast log polling, and log processing through Rsyslog.
    6. Signals can be used to control the Nginx process.
    7. Support 3XX-5xxHTTP status code redirection.
    8. Support for the rewrite module, SUPPORT for URI rewriting and regular expression matching.
    9. Supports access control based on client IP addresses and HTTP basic authentication.
    10. Supports special HTTP request methods, such as PUT, DELETE, MKCOL, COPY, and MOVE.
    11. Support FLV stream and MP4 stream technology product applications.
    12. Supports HTTP response rate limiting.
    13. Supports concurrent connection or request restrictions for the same IP address.
    14. Support for mail service agents.
    15. Support high concurrency, can support millions of concurrent connections.
    16. Resource consumption is low. Threads that can start 10 Nginx threads consume less than 200MB of memory for 30,000 concurrent connections.
    17. Can do HTTP reverse proxy and accelerated caching, and load balancing function, built-in health check function on RS node server, discount but can with professional HAProxy or LVS function.
    18. Have Squid and other professional cache software cache function.
    19. Support for asynchronous network I/O event model epoll (Linux2.6+).
  • Nginx software for major enterprise applications

    1. As Web services software.
    2. Use Nginx to run static data such as HTML, JS, CSS, and small images (similar to Lighttpd).
    3. Run dynamic programs such as PHP with Fast CGI (for example, using fastcgi_pass).
    4. Nginx with Tomcat/Resin and other Java dynamic program support (commonly used proxy_pass).
    5. Reverse proxy or load balancing service (Nginx has supported TCP proxies since 1.9.0).
    6. Front-end business data caching service.
  • Web service application performance comparison

    1. Static data access: when processing small files (less than 1MB), Nginx and Lighttpd have more advantages than Apache, Nginx has obvious advantages in processing small files, Lighttpd has the strongest comprehensive.
    2. Dynamic data access: there is not much difference between the three, Apache has the advantage, because the ability to process dynamic data lies in PHP (Java) and back-end database services, that is to say, the bottleneck is not in the Web server.
    3. In general, the reference value for concurrent connections supported by the common PHP engine is 300 to 1000. The reference value for concurrent connections between the Java engine and the database ranges from 300 to 1500.
  • Why is Nginx performing better than Apache?

    1. Nginx uses the latest version of the EEpoll (Linux 2.6 kernel) and KQueue (FreeBSD) asynchronous network I/O model, while Apache uses the traditional SELECT model.
    2. At present, Squid and Memcached software that can withstand high concurrent access under Linux adopt epoll model.
    3. The Select network I/O model used by Apache is relatively low when dealing with a large number of reads and writes to connections.
  • How to properly adopt a Web server?

    1. Static services: In high concurrency scenarios, use Nginx or Lighttpd. Nginx is preferred.
    2. Dynamic service: both Nginx and Apache can be used in theory. It is recommended to use Nginx. In order to avoid the software diversification of the same business service and increase the maintenance cost, dynamic service can use Nginx as a front-end proxy and then forward to other servers for processing according to the elements or directories on the page.
    3. If you have both dynamic and static business, use Nginx.


Create a project using the IDEA scenario initiator

  • To create a Maven project, modify the pom. XML file to add the following dependencies:
<dependencies>
    <!-- SpringBoot的自动配置相关依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>1.5.20.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>1.5.20.RELEASE</version>
    </dependency>
    <!-- 日志相关的依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
        <version>1.5.20.RELEASE</version>
    </dependency>
    <!-- 对象池相关的依赖 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.6.0</version>
    </dependency>

</dependencies>Copy the code

Create the necessary packages

  • Annotation: Store relevant annotations

  • Autoconfiguation: Stores the automatic configuration class

  • Factory: Stores the factory class

  • Properties: stores configuration parameter classes

  • service: Stores service classes

Typically, SpringBoot provides a corresponding @enablexxx annotation to enable a function in the application’s main startup class:

// EnableFastdfsClient.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(FastdfsAutoConfiguration.class)
@Documented
public @interface EnableFastdfsClient {
}Copy the code

Here are the relevant auto-configuration classes:

// FastdfsAutoConfiguration.java
@Configuration
@EnableConfigurationProperties(FastdfsProperties.class)
public class FastdfsAutoConfiguration {
    @Autowired
    private FastdfsProperties fastdfsProperties;

    @Bean
    @ConditionalOnMissingBean(FastdfsClientService.class)
    public FastdfsClientService fastdfsClientService() throws Exception {
        returnnew FastdfsClientService(fastdfsProperties); }}Copy the code

Create the associated factory class:

/ / StorageClientFactory. Java / / factory class used to create the connection object public class StorageClientFactory implements PooledObjectFactory<StorageClient> { @Override public PooledObject<StorageClient> makeObject() throws Exception { TrackerClient client = new TrackerClient(); TrackerServer server = client.getConnection();return new DefaultPooledObject<>(new StorageClient(server, null));
    }

    @Override
    public void destroyObject(PooledObject<StorageClient> p) throws Exception {
        p.getObject().getTrackerServer().close();
    }

    @Override
    public boolean validateObject(PooledObject<StorageClient> p) {
        return false;
    }

    @Override
    public void activateObject(PooledObject<StorageClient> p) throws Exception {

    }

    @Override
    public void passivateObject(PooledObject<StorageClient> p) throws Exception {

    }
}Copy the code

The Properties class maps application. Properties or application. Yml configuration files:

// FastdfsProperties.java
@ConfigurationProperties(prefix = "fastdfs"Public class FastdfsProperties {// Connection timeout duration // network timeout duration // character set encoding // Whether to use Token // Token encryption key // tracker IP address, // Maximum number of connection objects in the connection pool separated by semicolons // Maximum number of free objects in the connection pool // Minimum number of free objects in the connection pool // Nginx server IP address, Tolerable waiting time for multiple connection objects split by semicolons (ms) Private String connectTimeout ="5";
    private String networkTimeout = "30";
    private String charset = "UTF-8";
    private String httpAntiStealToken = "false";
    private String httpSecretKey = "";
    private String httpTrackerHttpPort = "";
    private String trackerServers = "";
    private String connectionPoolMaxTotal = "18";
    private String connectionPoolMaxIdle = "18";
    private String connectionPoolMinIdle = "2";
    private String nginxServers = ""; // Need to create the relevant Setter and Getter methods}Copy the code

To encapsulate methods in a Service class, just three common methods are shown below:

/ / FastdfsClientSerivce. Java public class FastdfsClientService {/ / / / SpringBoot loading configuration file connection pool configuration items / / converted / / / / connection pool configuration items Nginx server address private FastdfsProperties fdfsProp; private GenericObjectPoolConfig config; private Properties prop; private GenericObjectPool<StorageClient> pool; private String[] nginxServers; private Logger logger; public FastdfsClientService(FastdfsProperties fdfsProp) throws Exception { this.fdfsProp = fdfsProp; this.logger = LoggerFactory.getLogger(getClass()); init(); create(); info(); } /** * Initializes the global client */ private void init() throws Exception {this.prop = new Properties(); this.logger.info("FastDFS: reading config file...");
        this.logger.info("FastDFS: fastdfs.connect_timeout_in_seconds=" + this.fdfsProp.getConnectTimeout());
        this.logger.info("FastDFS: fastdfs.network_timeout_in_seconds=" + this.fdfsProp.getNetworkTimeout());
        this.logger.info("FastDFS: fastdfs.charset=" + this.fdfsProp.getCharset());
        this.logger.info("FastDFS: fastdfs.http_anti_steal_token=" + this.fdfsProp.getHttpAntiStealToken());
        this.logger.info("FastDFS: fastdfs.http_secret_key=" + this.fdfsProp.getHttpSecretKey());
        this.logger.info("FastDFS: fastdfs.http_tracker_http_port=" + this.fdfsProp.getHttpTrackerHttpPort());
        this.logger.info("FastDFS: fastdfs.tracker_servers=" + this.fdfsProp.getTrackerServers());
        this.logger.info("FastDFS: fastdfs.connection_pool_max_total=" + this.fdfsProp.getConnectionPoolMaxTotal());
        this.logger.info("FastDFS: fastdfs.connection_pool_max_idle=" + this.fdfsProp.getConnectionPoolMaxIdle());
        this.logger.info("FastDFS: fastdfs.connection_pool_min_idle=" + this.fdfsProp.getConnectionPoolMinIdle());
        this.logger.info("FastDFS: fastdfs.nginx_servers=" + this.fdfsProp.getNginxServers());

        this.prop.put("fastdfs.connect_timeout_in_seconds", this.fdfsProp.getConnectTimeout());
        this.prop.put("fastdfs.network_timeout_in_seconds", this.fdfsProp.getNetworkTimeout());
        this.prop.put("fastdfs.charset", this.fdfsProp.getCharset());
        this.prop.put("fastdfs.http_anti_steal_token", this.fdfsProp.getHttpAntiStealToken());
        this.prop.put("fastdfs.http_secret_key", this.fdfsProp.getHttpSecretKey());
        this.prop.put("fastdfs.http_tracker_http_port", this.fdfsProp.getHttpTrackerHttpPort());
        this.prop.put("fastdfs.tracker_servers", this.fdfsProp.getTrackerServers()); ClientGlobal.initByProperties(this.prop); } /** * Displays initialization information */ private voidinfo() {
        this.logger.info("FastDFS parameter: ConnectionPoolMaxTotal ==> " + this.pool.getMaxTotal());
        this.logger.info("FastDFS parameter: ConnectionPoolMaxIdle ==> " + this.pool.getMaxIdle());
        this.logger.info("FastDFS parameter: ConnectionPoolMinIdle ==> " + this.pool.getMinIdle());
        this.logger.info("FastDFS parameter: NginxServer ==> "+ Arrays.toString(this.nginxServers)); this.logger.info(ClientGlobal.configInfo()); } /** * Create a connection pool */ private voidcreate() {
        this.config = new GenericObjectPoolConfig();
        this.logger.info("FastDFS Client: Creating connection pool...");
        this.config.setMaxTotal(Integer.parseInt(this.fdfsProp.getConnectionPoolMaxTotal()));
        this.config.setMaxIdle(Integer.parseInt(this.fdfsProp.getConnectionPoolMaxIdle()));
        this.config.setMinIdle(Integer.parseInt(this.fdfsProp.getConnectionPoolMinIdle()));
        StorageClientFactory factory = new StorageClientFactory();
        this.pool = new GenericObjectPool<StorageClient>(factory, this.config);
        this.nginxServers = this.fdfsProp.getNginxServers().split(","); } /** * Nginx server load balancing algorithm ** @param Servers server address * @param Server IP address * @return*/ private String getNginxServer(String[] Servers, String address) {int size = Servers.length; private String getNginxServer(String[] Servers, String address) {int size = Servers.length; int i = address.hashCode(); int index = abs(i % size);returnservers[index]; } /** * download with anti-leech ** @param fileGroup fileGroup name * @param remoteFileName remoteFileName * @param clientIpAddress clientIpAddress * @returnPublic String autoDownloadWithToken(String fileGroup, String remoteFileName, String clientIpAddress) throws Exception { int ts = (int) (System.currentTimeMillis() / 1000); String token = ProtoCommon.getToken(remoteFileName, ts, ClientGlobal.getG_secret_key()); String nginx = this.getNginxServer(this.nginxServers, clientIpAddress);return "http://" + nginx + "/" + fileGroup + "/" + remoteFileName + "? token=" + token + "&ts="+ ts; } /** ** upload files, suitable for uploading pictures ** @param buffer byte array * @param ext extension * @returnPublic String[] autoUpload(byte[] buffer, String ext) throws Exception { String[] upload = this.upload(buffer, ext, null);returnupload; } /** * Download without anti-theft chain, * * @param fileGroup fileGroup name * @param remoteFileName remote file ID * @param clientIpAddress clientIpAddress, Nginx servers are assigned based on client IPreturnPublic String autoDownloadWithoutToken(String fileGroup, String remoteFileName, String clientIpAddress) throws Exception {if (ClientGlobal.getG_anti_steal_token()) {
            this.logger.error("FastDFS Client: You've turned on Token authentication.");
            throw new Exception("You've turned on Token authentication.");
        }
        String nginx = this.getNginxServer(this.nginxServers, clientIpAddress);
        return "http://" + nginx + fileGroup + "/"+ remoteFileName; } // There are many more methods, but I will not show them all.Copy the code

In order to use convenient configuration prompts in IDEA, we need to create metadata files (resources/spring-configuration-metadata.json) :

{
  "groups": [{"name": "fastdfs"."type": "com.bluemiaomiao.properties.FastdfsProperties"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"}]."properties": [{"name": "connectTimeout"."type": "java.lang.String"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"."defaultValue": "5"
    },
    {
      "name": "networkTimeout"."type": "java.lang.String"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"."defaultValue": "30"
    },
    {
      "name": "charset"."type": "java.lang.String"."defaultValue": "UTF-8"
    },
    {
      "name": "httpAntiStealToken"."type": "java.lang.String"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"."defaultValue": "false"
    },
    {
      "name": "httpSecretKey"."type": "java.lang.String"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"
    },
    {
      "name": "httpTrackerHttpPort"."type": "java.lang.Integer"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"
    },
    {
      "name": "trackerServers"."type": "java.lang.String"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"
    },
    {
      "name": "connectionPoolMaxTotal"."type": "java.lang.Integer"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"."defaultValue": "18"
    },
    {
      "name": "connectionPoolMaxIdle"."type": "java.lang.Integer"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"."defaultValue": "18"
    },
    {
      "name": "connectionPoolMinIdle"."type": "java.lang.Integer"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"."defaultValue": "2"
    },
    {
      "name": "nginxServers"."type": "java.lang.String"."sourceType": "com.bluemiaomiao.properties.FastdfsProperties"}]."hints": [{"name": "http_anti_steal_token"."values": [{"value": "false"
        },
        {
          "value": "true"}]}]}Copy the code

Add the custom starter to the project

  • Create a SpringBoot project, select Web options and version 1.5.20

  • Go to the project directory of the scenario initiator and run MVN Clean Install to install it locally

  • Add dependencies to the pom.xml file:
<dependency> <groupId>com.bluemiaomiao</groupId> <artifactId>fastdfs-spring-boot-starter</artifactId> < version > 1.0 - the SNAPSHOT < / version > < / dependency >Copy the code

Remember to enable the automatic import function of IDEA

  • Create the configuration file application.properties
Fastdfs. Nginx - the servers = 192.168.80.2:8000192168 80.3:8000192168 80.4:8000 Fastdfs. Tracker - the servers = 192.168.80.2:22122192168 80.3:22122192168 80.4:22122 fastdfs.http-secret-key=2scPwMPctXhbLVOYB0jyuyQzytOofmFCBIYe65n56PPYVWrntxzLIDbPdvDDLJM8QHhKxSGWTcr+9VdG3yptkw fastdfs.http-anti-steal-token=true
fastdfs.http-tracker-http-port=8080
fastdfs.network-timeout=30
fastdfs.connect-timeout=5
fastdfs.connection-pool-max-idle=18
fastdfs.connection-pool-min-idle=2
fastdfs.connection-pool-max-total=18
fastdfs.charset=UTF-8Copy the code

Or use application.yml

fastdfs:
  charset: UTF-8
  connect-timeout: 5
  http-secret-key: 2scPwMPctXhbLVOYB0jyuyQzytOofmFCBIYe65n56PPYVWrntxzLIDbPdvDDLJM8QHhKxSGWTcr+9VdG3yptkw
  network-timeout: 30
  http-anti-steal-token: truehttp-tracker-http-port: 8080 connection-pool-max-idle: 20 connection-pool-max-total: 20 connection-pool-min-idle: Nginx - the servers: 2 192.168.80.2:8000192168 80.3:8000192168 80.4:8000 tracker - the servers: 192.168.80.2:22122192168 80.3:22122192168 80.4:22122Copy the code
  • Create controller class test methods
// controllers.DownloadController.java
@Controller
@RequestMapping(value = "/download")
public class DownloadController {

    @Autowired
    private FastdfsClientService service;

    @ResponseBody
    @RequestMapping(value = "/image") public String image() throws Exception {// Data that has been uploaded before is stored in an SQL databasereturn service.autoDownloadWithToken("group1"."M00/00/00/wKhQA1ysjSGAPjXbAAVFOL7FJU4.tar.gz"."192.168.80.1"); }}Copy the code

Welcome Java engineers to join the Java Advanced Advanced Architecture: 809389099 group provides free Java architecture learning materials (which have high availability, high concurrency, high performance and distributed, Jvm performance tuning, Spring source code, MyBatis, Netty, Redis, Kafka, Mysql, Zookeeper, Tomcat, Docker, Dubbo, multiple knowledge architecture data, such as the Nginx) reasonable use their every minute and second time to learn to improve yourself, don’t use “no time” to hide his ideas on the lazy! While young, hard to fight, to the future of their own account!