Kaynağa Gözat

add::新增相关md

tujidelv 6 yıl önce
ebeveyn
işleme
c928c5f660

+ 17 - 4
TOC.md

@@ -1,13 +1,24 @@
 - **Operating System**
-    - [Linux 札记:Shell 脚本](source/_posts/os-linux-shell.md)
-    - [Linux 札记:常用命令](source/_posts/os-linux-command.md)
-    - [Linux 札记:基础](source/_posts/os-linux-basic.md)
+    - [Linux 常用程序包的安装与配置](source/_posts/os-linux-packages-install.md)
+    - [Linux 系统管理:磁盘、文件系统、RAID、LVM2、程序包](source/_posts/os-linux-sysadmin-first.md)
+    - [Linux 系统入门:Shell 脚本](source/_posts/os-linux-shell.md)
+    - [Linux 系统入门:常用命令](source/_posts/os-linux-command.md)
+    - [Linux 系统入门:基础](source/_posts/os-linux-basic.md)
 - **Development Language**
+    - [性能调优之JVM](source/_posts/dl-java-jvm.md)
+    - [Java8新特性](source/_posts/dl-java-8.md)
     - [Markdown 札记](source/_posts/dl-markdown.md)
 - **Application Framework**
+    - [分布式系列之 Redis](source/_posts/af-redis.md)
+    - [分布式系列之 Zookeeper](source/_posts/af-zookeeper.md)
+    - [微服务架构之 Dubbo](source/_posts/dubbo.md)
+    - [微服务架构之 SpringCloud](source/_posts/af-springcloud.md)
+    - [微服务架构之 SpringBoot](source/_posts/af-springboot.md)
+    - [消息中间件之 RocketMQ](source/_posts/af-mq-rocketmq.md)
     - [NodeJS 札记](source/_posts/af-nodejs.md)
     - [Hexo 札记](source/_posts/af-hexo.md)
 - **Software Tool**
+    - [项目管理工具之Maven](source/_posts/st-maven.md)
     - [Eclipse 札记](source/_posts/st-eclipse.md)
     - [IDEA 札记:基础](source/_posts/st-idea-basic.md)
     - [IDEA 札记:进阶](source/_posts/st-idea-advanced.md)
@@ -21,4 +32,6 @@
     - [SSR 搭建:基础](source/_posts/si-ssr-basic.md)
     - [SSR 搭建:进阶](source/_posts/si-ssr-advanced.md)
 - **Typical Example**
-    - [可输入可选择可模糊查询的 select 下拉](source/_posts/te-select.md)
+    - [可输入可选择可模糊查询的 select 下拉](source/_posts/te-select.md)
+    - [Mysql 数据库自动备份脚本](source/_posts/te-db-backup.md)
+    - [CentOS7 添加开机启动服务/脚本](source/_posts/te-script-powerboot.md)

+ 1218 - 0
source/_posts/af-springboot.md

@@ -0,0 +1,1218 @@
+---
+title: 微服务架构之 SpringBoot
+date: 2019-04-04 18:17:48
+categories:
+- 应用框架
+tags:
+- 分布式
+---
+
+# 微服务架构之 SpringBoot
+
+## 目录
+
+- [简介](#简介)
+- [快速入门](#快速入门)
+- [正篇](#正篇)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介
+
+### `什么是SpringBoot`
+
+```
+SpringBoot是一个快速开发的框架,能够快速整合第三方框架,简化XML配置完全采用注解形式,内置Web服务器(Jetty和Tomcat),最终以java应用程序进行执行。
+SpringBoot不是微服务框架。
+```
+
+### `为什么要用SpringBoot`
+
+```
+解决传统SSM项目的开发效率低、Jar冲突、配置多的问题。
+```
+
+### `与SpringMVC、SpringCloud之间的关系`
+
+```
+SpringCloud:
+    是一套完整的微服务解决框架,采用Http+Json格式的通讯协议,底层依赖于SpringBoot框架(web组件集成springmvc),使用SpringMVC书写Http协议接口。
+    采用SpringBoot+Dubbo也能实现微服务。
+SpringMVC:
+    SpringBoot默认集成了SpringMVC作为web层的框架。
+总结:
+    如果需要做微服务的话,就需要整合SpringBoot+SpringCloud;如果项目中不需要实现微服务,可以只单纯使用SpringBoot而不使用SpringCloud。
+```
+
+## 快速入门
+
+1. 创建一个普通 maven 工程,packaging类型为jar(可省略)
+2. pom文件中引入SpringBoot相关依赖
+    ```
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.0.0.RELEASE</version>
+    </parent>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+    </dependencies>
+    ```
+    ```
+    spring-boot-starter-parent作用
+        统一整合第三方框架依赖信息,以后再申明其它dependency的时候就不需要写版本号了。
+    spring-boot-starter-web作用
+        把传统方式的SpringMVC依赖的所有jar全部给下载下来,
+    spring-boot-maven-plugin作用
+        如果直接通过Main启动spring,那么以下plugin必须要添加,否则是无法启动的。如果使用maven 的spring-boot:run的话是不需要此配置的。
+    ```
+3. 编写helloworld服务
+    ```
+    package top.lvzhiqiang.controller;
+    @RestController
+    @EnableAutoConfiguration
+    public class IndexController {
+    
+        @RequestMapping("/index")
+        public String index(){
+            return "hello springboot!";
+        }
+    
+        public static void main(String[] args) {
+            SpringApplication.run(IndexController.class,args);
+        }
+    }
+    ```
+    ```
+    @RestController的作用
+        表示该Controller下所有的方法返回JSON格式,可以直接编写Restful接口;省略了在方法上加上@ResponseBody。
+        如果项目中的类加上了此注解,说明这个项目可能是一个微服务项目,需要统一接口,提供服务接口。
+    @EnableAutoConfiguration的作用
+        表示让Spring Boot根据添加的jar依赖来对Spring框架进行自动配置。
+        由于spring-boot-starter-web添加了Tomcat和Spring MVC,所以auto-configuration将假定你正在开发一个web应用并相应地对Spring进行设置。
+    @Configuration的作用
+        底层含有@Component,标注在类上,相当于把该类作为spring的xml配置文件中的<beans>
+        用来来配置spring容器(应用上下文)
+    @Bean的作用
+        标注在方法上(返回某个实例的方法),相当于spring的xml配置文件中的<bean>
+        用来注册bean对象(实例化bean,并交给spring管理)
+    ```
+4. 启动应用
+    ```
+    方法1:
+        直接启动main方法,main方法中指定IndexController为启动入口,默认端口号为8080。
+    方法2:
+        @ComponentScan(basePackages = "top.lvzhiqiang.controller")
+        @EnableAutoConfiguration
+        public class App {
+        	public static void main(String[] args) {
+        		SpringApplication.run(App.class, args);
+        	}
+        }
+        单独写个类并使用@ComponentScan注解添加自动扫包范围。
+    方法3:
+        @SpringBootApplication
+        public class App {
+            public static void main(String[] args) {
+                SpringApplication.run(App.class, args);
+            }
+        }
+        单独写个类并使用@SpringBootApplication注解,等同于@ComponentScan + @EnableAutoConfiguration。
+        扫包范围:当前包下或者子包下所有的类都可以扫到。
+    ```
+
+## 正篇
+
+### Web开发
+
+- `静态资源访问`
+    ```
+    在我们开发Web应用的时候,需要引用大量的js、css、图片等静态资源。
+    Spring Boot默认提供静态资源目录位置需置于classpath(src/main/java或者src/main/resources)下,目录命名如下:
+        static、public、resources、META-INF/resources
+    ```
+- `渲染Web页面`
+    ```
+    如果需要返回html等页面时,Spring Boot提供了多种模板引擎,来帮助我们很快的上手开发动态网站。
+        Thymeleaf、FreeMarker、Velocity、Groovy、Mustache
+    Spring Boot建议使用模板引擎(例如FreeMarker),避免使用JSP,若一定要使用JSP将无法实现Spring Boot的多种特性。
+        如果使用模板引擎,它们默认的模板配置路径为:src/main/resources/templates。当然也可以修改这个路径。
+    ```
+- `使用Freemarker模板引擎渲染Web视图`
+    ```
+    1.pom文件引入FreeMarker的依赖包
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-freemarker</artifactId>
+        </dependency>
+    2.在src/main/resources/创建一个templates文件夹,在templates下新建ftlIndex.ftl
+        @Controller
+        @EnableAutoConfiguration
+        public class IndexController {
+            @RequestMapping("/ftlIndex")
+            public String ftlIndex(Model model) {
+                model.addAttribute("name", "张三");
+                model.addAttribute("sex", 1);
+                List<String> userList = new ArrayList<>();
+                userList.add("a");
+                userList.add("b");
+                userList.add("c");
+                model.addAttribute("userList", userList);
+                return "ftlIndex";
+            }
+            ...
+        }
+    3.在ftl文件中填充数据
+        ${name}
+        <#if sex == 1>男
+        <#elseif sex == 2>女
+        <#else>其他
+        </#if>
+        <#list userList as user>${user}
+        </#list>
+    4.新建src/main/resources/下新建application.properties文件进行Freemarker配置(可以不配置,采用默认)
+        spring.freemarker.allow-request-override=false
+        spring.freemarker.cache=true
+        spring.freemarker.check-template-location=true
+        spring.freemarker.charset=UTF-8
+        spring.freemarker.content-type=text/html
+        spring.freemarker.expose-request-attributes=false
+        spring.freemarker.expose-session-attributes=false
+        spring.freemarker.expose-spring-macro-helpers=false
+        #spring.freemarker.prefix=
+        #spring.freemarker.request-context-attribute=
+        #spring.freemarker.settings.*=
+        spring.freemarker.suffix=.ftl
+        spring.freemarker.template-loader-path=classpath:/templates/
+        #comma-separated list
+        #spring.freemarker.view-names= # whitelist of view names that can be resolved
+    ```
+- `使用JSP渲染Web视图`
+    ```
+    1.pom文件引入Jsp相关的依赖包
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-tomcat</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-jasper</artifactId>
+        </dependency>
+    2.新建src/main/resources/下新建application.properties文件进行Jsp配置
+        spring.mvc.view.prefix=/WEB-INF/jsp/
+        spring.mvc.view.suffix=.jsp
+    3.在src/main/webapp下创建/WEB-INF/jsp/目录,并在jsp目录下新建jspIndex.jsp
+        @Controller
+        @EnableAutoConfiguration
+        public class IndexController {
+            @RequestMapping("/jspIndex")
+            public String jspIndex() {
+                return "jspIndex";
+            }
+            ...
+        }
+    4.如果找不到页面,可在pom文件中改为war类型项目
+    ```
+- `全局捕获异常`
+    ```
+    @ControllerAdvice(basePackages = "top.lvzhiqiang.controller")
+    public class GlobalExceptionHandler {
+        @ExceptionHandler(RuntimeException.class)
+        @ResponseBody
+        public Map<String, Object> exceptionHandler() {
+            Map<String, Object> map = new HashMap<>();
+            map.put("errorCode", "101");
+            map.put("errorMsg", "系統错误!");
+            return map;
+        }
+    }
+    ```
+    ```
+    @ExceptionHandler表示拦截异常
+    @ControllerAdvice是controller的一个辅助类,最常用的就是作为全局异常处理的切面类
+        @ControllerAdvice可以指定扫描范围
+        @ControllerAdvice约定了几种可行的返回值,如果是直接
+            返回json,需要使用@ResponseBody进行json转换
+            返回页面,返回值类型为ModelAndView或者String
+    实际开发中,可在全局捕获异常中将异常日志信息写入nosql数据库中,如果是集群环境,可采用分布式日志收集系统(kafka,logstash等),方便排查
+    ```
+
+### 日志管理
+
+1. `使用log4j记录日志`
+    ```
+    1.pom文件引入log4j相关的依赖包
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <exclusions>
+                <!-- 排除自带的logback依赖 -->
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j</artifactId>
+            <version>1.3.8.RELEASE</version>
+        </dependency>
+    2.新建src/main/resources/下新建log4j.properties文件进行log4j配置
+        log4j.rootLogger=info,error,CONSOLE,DEBUG
+        log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+        log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+        log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
+        log4j.logger.info=info
+        log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
+        log4j.appender.info.layout=org.apache.log4j.PatternLayout
+        log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
+        log4j.appender.info.datePattern='.'yyyy-MM-dd
+        log4j.appender.info.Threshold = info
+        log4j.appender.info.append=true
+        log4j.appender.info.File=D:\\log4j\\springbootdemo\\info
+        log4j.logger.error=error
+        log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
+        log4j.appender.error.layout=org.apache.log4j.PatternLayout
+        log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
+        log4j.appender.error.datePattern='.'yyyy-MM-dd
+        log4j.appender.error.Threshold = error
+        log4j.appender.error.append=true
+        log4j.appender.error.File=D:\\log4j\\springbootdemo\\error
+        log4j.logger.DEBUG=DEBUG
+        log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender
+        log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout
+        log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
+        log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd
+        log4j.appender.DEBUG.Threshold = DEBUG
+        log4j.appender.DEBUG.append=true
+        log4j.appender.DEBUG.File=D:\\log4j\\springbootdemo\\debug
+    ```
+2. `使用AOP统一处理Web请求日志`
+    ```
+    1.pom文件新增aop依赖
+        <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+    2.aop代码
+        @Aspect
+        @Component
+        public class WebLogAspect {
+            private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
+        
+            @Pointcut("execution(public * top.lvzhiqiang.controller.*.*(..))")
+            public void webLog() {
+            }
+        
+            @Before("webLog()")
+            public void doBefore(JoinPoint joinPoint) throws Throwable {
+                // 接收到请求,记录请求内容
+                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+                HttpServletRequest request = attributes.getRequest();
+                // 记录下请求内容
+                logger.info("URL : " + request.getRequestURL().toString());
+                logger.info("HTTP_METHOD : " + request.getMethod());
+                logger.info("IP : " + request.getRemoteAddr());
+                Enumeration<String> enu = request.getParameterNames();
+                while (enu.hasMoreElements()) {
+                    String name = (String) enu.nextElement();
+                    logger.info("name:{},value:{}", name, request.getParameter(name));
+                }
+            }
+        
+            @AfterReturning(returning = "ret", pointcut = "webLog()")
+            public void doAfterReturning(Object ret) throws Throwable {
+                // 处理完请求,返回内容
+                logger.info("RESPONSE : " + ret);
+            }
+        }
+    ```
+3. `Spring Boot集成lombok让代码更简洁`
+    ```
+    0.IDE开发工具需要先安装lombok插件(lombok底层使用asm字节码技术,在编译时修改字节码文件,来生成相应的set,get等相应方法)
+    1.pom文件引入lombok相关的依赖包
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    2.实体类测试
+        @Slf4j
+        @Setter
+        @Getter
+        public class UserEntity {
+            // @Getter
+            // @Setter
+            private String userName;
+            // @Getter
+            // @Setter
+            private Integer age;
+        
+            @Override
+            public String toString() {
+                return "UserEntity [userName=" + userName + ", age=" + age + "]";
+            }
+        
+            public static void main(String[] args) {
+                UserEntity userEntity = new UserEntity();
+                userEntity.setUserName("zhangsan");
+                userEntity.setAge(20);
+                System.out.println(userEntity.toString());
+                log.info("####我是日志##########");
+            }
+        }
+    ```
+    ```
+    其他特性:
+        @Data: 自动生成set/get方法,toString方法,equals方法,hashCode方法,不带参数的构造方法
+        @Setter/@Getter: 自动生成set和get方法 
+        @ToString: 自动生成toString方法 
+        @NonNull: 让你不在担忧并且爱上NullPointerException 
+        @CleanUp: 自动资源管理,不用再在finally中添加资源的close方法 
+        @EqualsAndHashcode: 从对象的字段中生成hashCode和equals的实现 
+        @NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor: 自动生成构造方法
+        @Value: 用于注解final类 
+        @Builder: 产生复杂的构建器api类 
+        @SneakyThrows: 异常处理(谨慎使用) 
+        @Synchronized : 同步方法安全的转化 
+        @Log: 支持各种logger对象,使用时用对应的注解,如:@Log4j
+    ```
+    
+### 数据访问
+
+- `整合mybatis`
+    ```
+    1.pom文件引入mybatis相关的依赖包
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.21</version>
+        </dependency>
+    2.修改application.properties
+        spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/test
+        spring.datasource.username=root
+        spring.datasource.password=root
+        spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+    3.Mapper代码
+        public interface UserMapper {
+        	@Select("SELECT * FROM USERS WHERE NAME = #{name}")
+        	User findByName(@Param("name") String name);
+        	@Insert("INSERT INTO USERS(NAME, AGE) VALUES(#{name}, #{age})")
+        	int insert(@Param("name") String name, @Param("age") Integer age);
+        }
+    4.在启动类上加上@MapperScan(basePackages = "top.lvzhiqiang.mapper")
+        也可以在Mapper接口上加上@Mapper,不过这样比较繁琐
+    ```
+    ```
+    Mybatis整合分页插件(pageHelper)
+        PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件
+        支持常见的12种数据库。Oracle,MySql,MariaDB,SQLite,DB2,PostgreSQL,SqlServer等
+        支持多种分页方式
+        支持常见的 RowBounds(PageRowBounds),PageHelper.startPage方法调用,Mapper接口参数调用
+    ------------------
+    1.添加maven依赖
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.7</version>
+        </dependency>
+    2.添加配置
+        pagehelper.helperDialect=mysql
+        pagehelper.reasonable=true
+        pagehelper.supportMethodsArguments=true
+        pagehelper.params=count=countSql
+        pagehelper.page-size-zero=true
+    3.service层
+        public PageInfo<User> findUserList(int pageNo, int pageSize) {
+            // 开启分页插件,放在查询语句上面
+            PageHelper.startPage(pageNo, pageSize);
+            List<User> listUser = userMapper.findUserList();
+            // 封装分页之后的数据
+            PageInfo<User> pageInfoUser = new PageInfo<User>(listUser);
+            return pageInfoUser;
+        }
+        //以上方法上的公共代码可用模板设计模式或者aop思想抽出来
+    ```
+- `整合jdbcTemplate`
+    ```
+    1.pom文件引入jdbcTemplate相关的依赖包
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.21</version>
+        </dependency>
+    2.修改application.properties
+        spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/test
+        spring.datasource.username=root
+        spring.datasource.password=root
+        spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+    3.代码
+        @Service
+        public class UserServiceImpl implements UserService {
+        	@Autowired
+        	private JdbcTemplate jdbcTemplate;
+        	public void createUser(String name, Integer age) {
+        		jdbcTemplate.update("insert into users values(null,?,?);", name, age);
+        	}
+        }
+    ```
+- `整合多数据源`
+    ```
+    1.修改application.properties新增两个数据源
+        ###datasource1
+        spring.datasource.test1.driver-class-name = com.mysql.jdbc.Driver
+        spring.datasource.test1.jdbc-url = jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf-8
+        spring.datasource.test1.username = root
+        spring.datasource.test1.password = root
+        ###datasource2
+        spring.datasource.test2.driver-class-name = com.mysql.jdbc.Driver
+        spring.datasource.test2.jdbc-url = jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8
+        spring.datasource.test2.username = root
+        spring.datasource.test2.password = root
+    2.在top/lvzhiqiang/下新建datasource目录(任意),新建DataSourceConfig类,采用分包(业务)机制来读取不同的数据源
+        //datasource1
+        @Configuration
+        @MapperScan(basePackages = "top.lvzhiqiang.user1", sqlSessionFactoryRef = "test1SqlSessionFactory")
+        public class DataSource1Config {
+            @Bean(name = "test1DataSource")
+            @Primary
+            @ConfigurationProperties(prefix = "spring.datasource.test1")
+            public DataSource testDataSource() {
+                return DataSourceBuilder.create().build();
+            }
+            @Bean(name = "test1SqlSessionFactory")
+            @Primary
+            public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
+                    throws Exception {
+                SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
+                bean.setDataSource(dataSource);
+                //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));
+                return bean.getObject();
+            }
+            @Bean(name = "test1TransactionManager")
+            @Primary
+            public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
+                return new DataSourceTransactionManager(dataSource);
+            }
+        
+            @Bean(name = "test1SqlSessionTemplate")
+            public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory)
+                    throws Exception {
+                return new SqlSessionTemplate(sqlSessionFactory);
+            }
+        }
+        ------------------------------
+        //datasource2
+        @Configuration
+        @MapperScan(basePackages = "top.lvzhiqiang.user2", sqlSessionFactoryRef = "test2SqlSessionFactory")
+        public class DataSource2Config {
+            @Bean(name = "test2DataSource")
+            @ConfigurationProperties(prefix = "spring.datasource.test2")
+            public DataSource testDataSource() {
+                return DataSourceBuilder.create().build();
+            }
+            ...
+        }
+    3.创建分包Mapper
+        public interface User1Mapper {
+        	@Insert("insert into users values(null,#{name},#{age});")
+        	public int addUser(@Param("name") String name, @Param("age") Integer age);
+        }
+    4.多数据源事务注意事项
+        在多数据源的情况下,使用@Transactional注解时,应该指定事务管理器
+        @Transactional(transactionManager = "test2TransactionManager")
+    ```
+
+### 事务管理
+
+- `SpringBoot整合事物管理`
+    ```
+    springboot默认集成并开启事物,只要在方法上加上@Transactional即可
+    ```
+- `SpringBoot分布式事物管理`
+    ```
+    针对多数据源的分布式事务解决方案:jta+atomikos
+    针对微服务的分布式事务解决方案:mq或者tcc等
+    ```
+    ```
+    1.pom文件引入atomikos相关的依赖包
+        <dependency>
+        	<groupId>org.springframework.boot</groupId>
+        	<artifactId>spring-boot-starter-jta-atomikos</artifactId>
+        </dependency>
+    2.新增多数据源配置信息,修改application.properties
+        # Mysql 1
+        mysql.datasource.test1.url = jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf-8
+        mysql.datasource.test1.username = root
+        mysql.datasource.test1.password = root
+        mysql.datasource.test1.minPoolSize = 3
+        mysql.datasource.test1.maxPoolSize = 25
+        mysql.datasource.test1.maxLifetime = 20000
+        mysql.datasource.test1.borrowConnectionTimeout = 30
+        mysql.datasource.test1.loginTimeout = 30
+        mysql.datasource.test1.maintenanceInterval = 60
+        mysql.datasource.test1.maxIdleTime = 60
+        # Mysql 2
+        mysql.datasource.test2.url =jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8
+        mysql.datasource.test2.username =root
+        mysql.datasource.test2.password =root
+        mysql.datasource.test2.minPoolSize = 3
+        mysql.datasource.test2.maxPoolSize = 25
+        mysql.datasource.test2.maxLifetime = 20000
+        mysql.datasource.test2.borrowConnectionTimeout = 30
+        mysql.datasource.test2.loginTimeout = 30
+        mysql.datasource.test2.maintenanceInterval = 60
+        mysql.datasource.test2.maxIdleTime = 60
+    3.读取多数据源配置信息,可在top/lvzhiqiang/下新建config目录(任意),新建2个config类
+        @Data
+        @ConfigurationProperties(prefix = "mysql.datasource.test1")
+        public class DBConfig1 {
+        	private String url;
+        	private String username;
+        	private String password;
+        	private int minPoolSize;
+        	private int maxPoolSize;
+        	private int maxLifetime;
+        	private int borrowConnectionTimeout;
+        	private int loginTimeout;
+        	private int maintenanceInterval;
+        	private int maxIdleTime;
+        	private String testQuery;
+        }
+        ----------------------
+        @Data
+        @ConfigurationProperties(prefix = "mysql.datasource.test2")
+        public class DBConfig2 {
+        	private String url;
+        	private String username;
+        	private String password;
+        	private int minPoolSize;
+        	private int maxPoolSize;
+        	private int maxLifetime;
+        	private int borrowConnectionTimeout;
+        	private int loginTimeout;
+        	private int maintenanceInterval;
+        	private int maxIdleTime;
+        	private String testQuery;
+        }
+    4.将多数据源注册到atomikos中去,在top/lvzhiqiang/下新建datasource目录(任意),新建DataSourceConfig类
+        @Configuration
+        @MapperScan(basePackages = "top.lvzhiqiang.test01", sqlSessionTemplateRef = "testSqlSessionTemplate")
+        public class MyBatisConfig1 {
+        	@Primary
+        	@Bean(name = "testDataSource")
+        	public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
+        		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
+        		mysqlXaDataSource.setUrl(testConfig.getUrl());
+        		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
+        		mysqlXaDataSource.setPassword(testConfig.getPassword());
+        		mysqlXaDataSource.setUser(testConfig.getUsername());
+        		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
+        
+        		AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
+        		xaDataSource.setXaDataSource(mysqlXaDataSource);
+        		xaDataSource.setUniqueResourceName("testDataSource");
+        
+        		xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
+        		xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
+        		xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
+        		xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
+        		xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
+        		xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
+        		xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
+        		xaDataSource.setTestQuery(testConfig.getTestQuery());
+        		return xaDataSource;
+        	}
+        	@Primary
+        	@Bean(name = "testSqlSessionFactory")
+        	public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource") DataSource dataSource)
+        			throws Exception {
+        		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
+        		bean.setDataSource(dataSource);
+        		return bean.getObject();
+        	}
+        	@Primary
+        	@Bean(name = "testSqlSessionTemplate")
+        	public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory)
+        	        throws Exception {
+        		return new SqlSessionTemplate(sqlSessionFactory);
+        	}
+        }
+        ----------------------
+        @Configuration
+        @MapperScan(basePackages = "top.lvzhiqiang.test02", sqlSessionTemplateRef = "test2SqlSessionTemplate")
+        public class MyBatisConfig2 {
+        	@Bean(name = "test2DataSource")
+        	public DataSource testDataSource(DBConfig2 testConfig) throws SQLException {
+        		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
+        		mysqlXaDataSource.setUrl(testConfig.getUrl());
+        		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
+        		...
+        	}
+            ...
+        }
+    5.在启动类加上此注解以开启读取配置文件
+        @EnableConfigurationProperties(value = { DBConfig1.class, DBConfig2.class })
+    ```
+
+### 监控管理
+
+- `Actuator监控应用`
+    ```
+    什么是SpringBoot监控中心
+        Actuator是spring boot的一个附加功能,可帮助你在应用程序生产环境时监视和管理应用程序。
+        特别对于微服务管理十分有意义,缺点是没有可视化界面(返回json格式)。
+        默认情况下,监控中心只提供3个接口权限。
+        在SpringBoot2.0后,监控中心接口地址发生变化,需要在访问接口前面中上/actuator。
+    主要用途
+        针对微服务服务器监控,包括服务器的内存变化(堆内存、线程、日志管理等)
+        检测服务配置连接地址(懒加载形式)是否可用(模拟访问)
+        统计当前Spring容器中有多少个bean
+        统计SpringMVC有多少个@RuquestMapping(http接口)
+    应用场景
+        生产环境
+    ```
+    ```
+    1.添加maven依赖
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+    2.yml配置
+        ###通过下面的配置启用所有的监控端点,默认情况下,这些端点是禁用的
+        management:
+            endpoints:
+                web:
+                    exposure:
+                        include: "*"
+    3.开始访问(通过actuator/+端点名就可以获取相应的信息)
+        /actuator/beans	显示应用程序中所有Spring bean的完整列表。
+        /actuator/mappings	显示所有@RequestMapping的url完整列表。
+        /actuator/configprops	显示所有配置信息。
+        /actuator/env	显示所有的环境变量。
+        /actuator/health	显示应用程序运行状况信息,up表示成功,down失败。
+        /actuator/info	查看自定义应用信息(显示在配置文件配置info开头的配置信息)     
+    ```
+- `Admin-UI分布式微服务监控中心`
+    - Admin-UI底层基于actuator实现能够返回界面展示监控信息,原理是将所有服务的监控中心管理存放在admin-ui平台上。
+    ---
+    ```
+    Admin-UI-Server
+    --------------------
+    1.添加maven依赖
+        <dependency>
+            <groupId>de.codecentric</groupId>
+            <artifactId>spring-boot-admin-starter-server</artifactId>
+            <version>2.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jolokia</groupId>
+            <artifactId>jolokia-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.googlecode.json-simple</groupId>
+            <artifactId>json-simple</artifactId>
+            <version>1.1</version>
+        </dependency>
+    2.yml配置
+        spring:
+            application:
+                name: spring-boot-admin-server
+    3.启动server端
+        @Configuration
+        @EnableAutoConfiguration
+        @EnableAdminServer
+        public class AdminServerApplication {
+        	public static void main(String[] args) {
+        		SpringApplication.run(AdminServerApplication.class, args);
+        	}
+        }
+    4.访问
+        http://localhost:8080
+    ```
+    ```
+    Admin-UI-Client
+    --------------------
+    1.添加maven依赖
+        <dependency>
+            <groupId>de.codecentric</groupId>
+            <artifactId>spring-boot-admin-starter-client</artifactId>
+            <version>2.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jolokia</groupId>
+            <artifactId>jolokia-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.googlecode.json-simple</groupId>
+            <artifactId>json-simple</artifactId>
+            <version>1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+    2.yml配置
+        spring:
+            boot:
+                admin:
+                    client:
+                        url: http://localhost:8080    ###配置client端注册到admin-ui平台
+        server:
+            port: 8081
+        management:
+            endpoints:
+                web:
+                    exposure:
+                        include: "*"
+                endpoint:
+                    health:
+                        show-details: ALWAYS
+    3.启动client端
+        @SpringBootApplication
+        public class AppClient {
+        	public static void main(String[] args) {
+        		SpringApplication.run(AppClient.class, args);
+        	}
+        }
+    ```
+
+### 性能优化
+
+- `JVM参数调优(运行优化)`
+    ```
+    -Xms和-Xmx最好设置成一样,不然会频繁造成GC
+    外部运行调优使用:java -server -Xms32m -Xmx32m  -jar springboot.jar
+    ```
+- `扫包优化(启动优化,非运行优化)`
+    ```
+    针对大项目时不要用@SpringBootApplication注解,会扫描到无用的包,可以采用@ComponentScan来扫描指定的包
+    ```
+- `将Servlet容器变成Undertow`
+    ```
+    默认情况下,Spring Boot 使用 Tomcat 来作为内嵌的 Servlet 容器,可以将 Web 服务器切换到 Undertow 来提高应用性能。
+        Undertow 是一个采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于NIO的非堵塞机制。
+        Undertow 是红帽公司的开源产品,是 Wildfly 默认的 Web 服务器。
+    可用jmeter作吞吐量测试,结果是tomcat吞吐量为5000,undertow为8000
+    ```
+    ```
+    1.从依赖信息里移除Tomcat
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    2.添加Undertow依赖
+        <dependency>
+        	<groupId>org.springframework.boot</groupId>
+        	<artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+    ```
+
+### 其他内容
+
+- `使用@Scheduled创建定时任务`
+    ```
+    在启动类中加入@EnableScheduling注解,启用定时任务的配置
+    -------------------
+    @Component
+    public class ScheduledTasks {
+        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+        @Scheduled(fixedRate = 5000)
+        public void reportCurrentTime() {
+            System.out.println("现在时间:" + dateFormat.format(new Date()));
+        }
+    }
+    ```
+- `使用@Async异步执行方法`
+    ```
+    在启动类加上@EnableAsync来开启异步调用,并在需要执行异步的方法上加上@Async
+        @Async注解使用AOP技术在运行时创建一个单线程来执行这个方法
+    ```
+- `使用@Value自定义参数`
+    ```
+    application.properties文件
+        name=lvzhiqiang.top
+    代码中
+    	@Value("${name}")
+    	private String name;
+        @ResponseBody
+    	@RequestMapping("/getValue")
+    	public String getValue() {
+    		return name;
+    	}
+    ```
+- `区分不同环境配置文件`
+    ```
+    1.在src/main/resources下新建各个环境的配置文件
+        application-dev.properties:开发环境
+        application-uat.properties:测试环境
+        application-pre.properties:生产环境
+    2.在application.properties中进行切换
+        spring.profiles.active=uat
+    ```
+- `修改端口号`
+    ```
+    server.port=8888
+    server.context-path=/springbootdemo
+    ```
+- `Spring Boot yml 使用`
+    ```
+    SpringBoot默认读取application.yml|properties
+    YML比properties配置文件更加简约(结构)
+    ---------------
+    server:
+      port: 8081
+      context-path: /springbootdemo
+    ```
+- `发布打包`
+    ```
+    jar类型打包方式
+        1.使用mvn celan  package 打包
+        2.使用java –jar 包名
+    war类型打包方式
+        1.使用mvn celan  package 打包
+        2.将war包放入到tomcat webapps下运行即可
+        注意:springboot2.0内置tomcat8.5.25,建议使用外部Tomcat9.0版本运行即可,否则报错版本不兼容。
+    ```
+    ```
+    如果执行java -jar命令提示没有主清单属性时,可在pom文件中新增如下代码
+        <build>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <configuration>
+                        <source>1.8</source>
+                        <target>1.8</target>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-maven-plugin</artifactId>
+                    <configuration>
+                        <mainClass>top.lvzhiqiang.StartApp</mainClass>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <goals>
+                                <goal>repackage</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+            </plugins>
+        </build>
+    ```
+- `热部署`
+    ```
+    1.什么是热部署
+        在应用程序不停止的情况下,实现新的部署
+    2.热部署原理
+        使用类加载器重新读取字节码文件到JVM中去
+    3.纯手写实现一个热部署功能
+        监听class文件是否发生改变(版本号或者修改时间),如果class文件发生改变,就使用classloader进行得新读取
+    4.优缺点
+        适合本地开发,提高运行效率,不用重启服务器;缺点是项目比较大时,非常卡,比较占内存.
+    ```
+    ```
+    1.引入devtools依赖
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional>
+            <scope>true</scope>
+        </dependency>
+    2.Devtools原理
+        1.devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),注意:因为其采用的虚拟机机制,该项重启是很快的。  
+        2.devtools可以实现页面热部署(即页面修改后会立即生效,这个可以直接在application.properties文件中配置spring.thymeleaf.cache=false来实现(这里注意不同的模板配置不一样) 
+    3.不推荐使用
+    ```
+- `整合拦截器`
+    ```
+    1.创建拦截器
+        @Slf4j
+        @Component
+        //创建模拟登录拦截器,验证请求是否有token参数
+        public class LoginIntercept implements HandlerInterceptor {
+            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+                    throws Exception {
+                log.info("开始拦截登录请求....");
+                String token = request.getParameter("token");
+                if (StringUtils.isEmpty(token)) {
+                    response.getWriter().println("not found token");
+                    return false;
+                }
+                return true;
+            }
+        }
+    2.注册拦截器
+        @Configuration
+        public class WebAppConfig {
+        	@Autowired
+        	private LoginIntercept loginIntercept;
+        	@Bean
+        	public WebMvcConfigurer WebMvcConfigurer() {
+        		return new WebMvcConfigurer() {
+        			public void addInterceptors(InterceptorRegistry registry) {
+        				registry.addInterceptor(loginIntercept).addPathPatterns("/*");
+        			};
+        		};
+        	}
+        }
+    ```
+    ```
+    拦截器与过滤器区别
+        拦截器是AOP( Aspect-Oriented Programming)的一种实现,底层通过动态代理模式完成。
+        (1)拦截器是基于java的反射机制的,而过滤器是基于函数回调。
+        (2)拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。
+        (3)拦截器只能对Controller请求起作用,而过滤器则可以对几乎所有的请求起作用。
+        (4)在Controller的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
+    过滤器应用场景:设置编码字符、过滤铭感字符
+    拦截器应用场景:拦截未登陆用户、审计日志
+    ```
+    
+### 2.0版本新特性
+
+- `以Java 8 为基准`
+    ```
+    Spring Boot 2.0 要求 Java 版本必须 8 以上, Java 6 和 7 不再支持。
+    ```
+- `内嵌容器包结构调整`
+    ```
+    为了支持reactive使用场景,内嵌的容器包结构被重构了的幅度有点大。EmbeddedServletContainer被重命名为WebServer,
+    并且org.springframework.boot.context.embedded 包被重定向到了org.springframework.boot.web.embedded包下。
+    举个例子,如果你要使用TomcatEmbeddedServletContainerFactory回调接口来自定义内嵌Tomcat容器,你现在应该使用TomcatServletWebServerFactory。
+    ```
+- `Servlet-specific 的server properties调整`
+    ```
+    大量的Servlet专属的server.* properties被移到了server.servlet下:
+        Old property	New property
+        server.context-parameters.*	server.servlet.context-parameters.*
+        server.context-path	server.servlet.context-path
+        server.jsp.class-name	server.servlet.jsp.class-name
+        server.jsp.init-parameters.*	server.servlet.jsp.init-parameters.*
+        server.jsp.registered	server.servlet.jsp.registered
+        server.servlet-path	server.servlet.path
+    由此可以看出一些端倪,那就是server不再是只有servlet了,还有其他的要加入。
+    ```
+- `Actuator 默认映射`
+    ```
+    actuator的端点(endpoint)现在默认映射到/application,比如,/info 端点现在就是在/application/info。但你可以使用management.context-path来覆盖此默认值。
+    ```
+- `Spring Loaded不再支持`
+    ```
+    由于Spring Loaded项目已被移到了attic了,所以不再支持Spring Loaded了。现在建议你去使用Devtools。Spring Loaded不再支持了。
+    ```
+- `支持Quartz Scheduler`
+    ```
+    Spring Boot 2.0针对Quartz调度器提供了支持。你可以加入spring-boot-starter-quartz starter来启用。而且支持基于内存和基于jdbc两种存储。
+    ```
+- `OAuth 2.0 支持`
+    ```
+    Spring Security OAuth 项目中的功能将会迁移到Spring Security中。将会OAuth 2.0。
+    ```
+- `支持Spring WebFlux`
+    ```
+    WebFlux 模块的名称是 spring-webflux,名称中的 Flux 来源于 Reactor 中的类 Flux。该模块中包含了对反应式 HTTP、服务器推送事件和
+     WebSocket 的客户端和服务器端的支持。对于开发人员来说,比较重要的是服务器端的开发,这也是本文的重点。在服务器端,WebFlux 支持两种
+     不同的编程模型:第一种是 Spring MVC 中使用的基于 Java 注解的方式;第二种是基于 Java 8 的 lambda 表达式的函数式编程模型。这两种
+     编程模型只是在代码编写方式上存在不同。它们运行在同样的反应式底层架构之上,因此在运行时是相同的。WebFlux 需要底层提供运行时的支持,
+     WebFlux 可以运行在支持 Servlet 3.1 非阻塞 IO API 的 Servlet 容器上,或是其他异步运行时环境,如 Netty 和 Undertow。
+    ```
+- `版本要求`
+    ```
+    Jetty
+        要求Jetty最低版本为9.4。
+    Tomcat
+        要求Tomcat最低版本为8.5。
+    Hibernate
+        要求Hibernate最低版本为5.2。
+    Gradle
+        要求Gradle最低版本为3.4。
+    SendGrid
+        SendGrid最低支持版本是3.2。为了支持这次升级,username和password已经被干掉了。因为API key现在是唯一支持的认证方式。
+    ```
+    
+### 手写springboot框架
+
+- springboot核心原理
+    ```
+    基于springmvc无配置文件完全注解化(纯java)+内置tomcat-embed-core来实现springboot框架,main函数启动
+    快速整合第三方框架
+        原理:Maven继承依赖关系
+    完全无配置文件采用注解化
+        原理:使用java代码(spring3内置注解)来对springmvc容器进行初始化
+    内置web服务器
+        原理:Java提供内置Tomcat容器框架,使用java语言创建并操作tomcat容器,加载class文件
+    ```
+- 内置web服务器
+    ```
+    1.添加pom依赖
+        <!--Java语言操作tomcat -->
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-core</artifactId>
+            <version>8.5.16</version>
+        </dependency>
+        <!-- spring-web -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>5.0.4.RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
+        <!-- spring-mvc -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <version>5.0.4.RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
+        <!-- tomcat对jsp支持 -->
+        <dependency>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>tomcat-jasper</artifactId>
+            <version>8.5.16</version>
+        </dependency>
+    2.创建servlet类
+        public class IndexServet extends HttpServlet {
+        	@Override
+        	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        		doPost(req, resp);
+        	}
+        	@Override
+        	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        		resp.getWriter().print("springboot2.0");
+        	}
+        }
+    3.创建tomcat运行
+        private static int PORT = 8080;// 端口号
+        private static String CONTEXTPATH = "/demo";// 项目名称
+    
+        public static void main(String[] args) throws LifecycleException {
+            // 创建Tomcat服务器
+            Tomcat tomcatServer = new Tomcat();
+            // 设置Tomcat端口号
+            tomcatServer.setPort(PORT);
+            tomcatServer.getHost().setAutoDeploy(false);
+            // 创建Context上下文
+            StandardContext standardContext = new StandardContext();
+            standardContext.setPath(CONTEXTPATH);
+            standardContext.addLifecycleListener(new FixContextListener());
+            // tomcat容器添加standardContext
+            tomcatServer.getHost().addChild(standardContext);
+            // 创建servlet
+            tomcatServer.addServlet(CONTEXTPATH, "IndexServet", new IndexServet());
+            // 添加servleturl映射
+            standardContext.addServletMappingDecoded("/index", "IndexServet");
+            tomcatServer.start();
+            tomcatServer.getServer().await();
+        }
+    ```
+- 完全无配置文件采用注解化
+    ```
+    1.加载SpringMVC的DispatcherServlet
+        AbstractAnnotationConfigDispatcherServletInitializer这个类负责配置DispatcherServlet、初始化Spring MVC容器和Spring容器。
+        getRootConfigClasses()方法用于获取Spring应用容器的配置文件,这里我们给定预先定义的RootConfig.class;
+        getServletConfigClasses负责获取Spring MVC应用容器,这里传入预先定义好的WebConfig.class;
+        getServletMappings()方法负责指定需要由DispatcherServlet映射的路径,这里给定的是"/",意思是由DispatcherServlet处理所有向该应用发起的请求。
+        
+        public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
+        	// 加载根容器
+        	protected Class<?>[] getRootConfigClasses() {
+        		return new Class[] { RootConfig.class };
+        	}
+            // 加载SpringMVC容器
+        	protected Class<?>[] getServletConfigClasses() {
+        		return new Class[] { WebConfig.class };
+        	}
+        	// SpringMVCDispatcherServlet 拦截的请求
+        	protected String[] getServletMappings() {
+        		return new String[] { "/" };
+        	}
+        }
+    2.加载SpringMVC容器
+        @Configuration
+        @EnableWebMvc
+        @ComponentScan("top.lvzhiqiang.controller")
+        public class WebConfig extends WebMvcConfigurerAdapter {
+            // 创建SpringMVC视图解析器
+        	@Bean
+        	public ViewResolver viewResolver() {
+        		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
+        		viewResolver.setPrefix("/WEB-INF/views/");
+        		viewResolver.setSuffix(".jsp");
+        		viewResolver.setExposeContextBeansAsAttributes(true);//可以在JSP页面中通过${}访问beans
+        		return viewResolver;
+        	}
+        }
+    3.加载RootConfig容器
+        @Configuration
+        @ComponentScan(basePackages = "top.lvzhiqiang")
+        public class RootConfig {
+        }
+    4.运行
+        public static void main(String[] args) throws ServletException, LifecycleException {
+            start();
+        }
+        public static void start() throws ServletException, LifecycleException {
+            // 创建Tomcat容器
+            Tomcat tomcatServer = new Tomcat();
+            // 端口号设置
+            tomcatServer.setPort(9090);
+            // 读取项目路径,主要用来加载一些静态资源
+            StandardContext ctx = (StandardContext) tomcatServer.addWebapp("/", new File("src/main").getAbsolutePath());
+            // 禁止重新载入
+            ctx.setReloadable(false);
+            // class文件读取地址
+            File additionWebInfClasses = new File("target/classes");
+            // 创建WebRoot
+            WebResourceRoot resources = new StandardRoot(ctx);
+            // tomcat内部读取Class执行
+            resources.addPreResources(new DirResourceSet(resources, "/WEB-INF/classes", additionWebInfClasses.getAbsolutePath(), "/"));
+            tomcatServer.start();
+            // 异步等待请求执行
+            tomcatServer.getServer().await();
+        }
+    ```
+
+## 参考链接
+
+## 结束语
+
+- 未完待续...

+ 20 - 0
source/_posts/af-zookeeper.md

@@ -0,0 +1,20 @@
+---
+title: 分布式协调工具之 Zookeeper
+date: 2019-04-08 19:24:23
+categories:
+- 应用框架
+tags:
+- 分布式
+---
+
+# 分布式协调工具之 Zookeeper
+
+## 目录
+
+- [简介](#简介)
+- [快速入门](#快速入门)
+- [正篇](#正篇)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介

+ 169 - 0
source/_posts/dl-java-8.md

@@ -0,0 +1,169 @@
+---
+title: Java8新特性
+date: 2019-03-30 15:04:29
+categories:
+- 开发语言
+tags:
+- java
+---
+
+# Java8 新特性
+
+## 目录
+
+- [简介](#简介)
+- [正篇](#正篇)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介
+
+- 整理下 Java8 的所有新特性。 
+    - `Lambda表达式`
+    - `Stream API`
+    - 全新时间日期 API
+    - ConcurrentHashMap
+    - MetaSpace
+- Java8 的新特性对 java 的影响。
+    - 更安全(Optional)
+    - 更效率(HashMap,HashSet,ConcurrentHashMap,MetaSpace)
+    - 简化书写(Lambda,Stream API)
+
+## 正篇
+
+### `Lambda 表达式`
+
+```
+一、简介:
+    Lambda表达式相当于匿名内部类的更简化的写法,并且可以像数据一样进行传递。
+    它需要函数式接口的支持。
+二、基础语法:
+    Java8中引入了一个新的操作符 "->",该操作符被称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分成两部分:
+        左侧:指定了Lambda表达式需要的所有参数 
+        右侧:指定了Lambda体,即Lambda表达式要执行的功能。
+    上联:左右遇一括号省
+    下联:左侧推断类型省
+    横批:能省则省
+```
+```
+语法格式一:无参数,无返回值,Lambda体只需一条语句
+    Runnable r1 = () -> System.err.println("Hello Lambda!r1");
+    r1.run();
+语法格式二:有一个参数,无返回值
+    Consumer<String> con = (arg) -> System.err.println("hello " + arg);
+	con.accept("consumer!");
+    
+    若只有一个参数,参数的小括号可以省略不写
+        Consumer<String> con = arg -> System.err.println("hello " + arg);
+语法格式三:有两个以上的参数,有返回值,并且Lambda体中有多条语句
+    Comparator<Integer> com = (x, y) -> {
+        System.out.println("函数式接口");
+        return Integer.compare(x, y);
+    };
+    
+    若Lambda体中只有一条语句,return和大括号都可以省略不写
+        Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
+语法格式四:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器根据程序的上下文推断出参数的数据类型,即“类型推断”
+    Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);
+    
+    例如:
+        String[] str = {"aaa","bbb","ccc"};
+        List<String> list = new ArrayList<>();
+```
+
+### `函数式接口`
+
+```
+一、简介
+    1. 只包含一个抽象方法的接口,称为函数式接口。 
+    2. 可以通过Lambda表达式来创建该接口的对象。(若Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)。
+    3. 可以在任意函数式接口上使用@FunctionalInterface注解,可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。
+二、自定义函数式接口
+    @FunctionalInterface
+    public interface MyFun<T>{
+        public T getValue(T t);
+    }
+    public String toUpperString(MyFun<String> mf, String str){
+        return mf.getValue(str);
+    }
+    @Test
+    public void test(){
+        String newStr = toUpperString((x) -> str.toUpperCase, "abcdeF");
+    }
+```
+```
+Java8内置四大核心函数式接口
+    Consumer<T> 消费型接口
+        包含方法: void accept(T t)
+    Supplier<T> 供给型接口
+        包含方法:T get();
+    Function<T, R> 函数型接口
+        包含方法:R apply(T t);
+    Predicate<T> 断言型接口
+        包含方法:boolean test(T t)
+-------------------
+@Test
+public void test1(){
+    happy(10000, (m) -> System.out.println("团建每次消费:" + m + "元"));
+} 
+public void happy(double money, Consumer<Double> con){
+    con.accept(money);
+}
+@Test
+public void test2(){
+    String newStr = strHandler("\t\t\t 函数型接口   ", (str) -> str.trim());
+    System.out.println(newStr);
+}
+public String strHandler(String str, Function<String, String> fun){
+    return fun.apply(str);
+}
+...
+```
+
+### `方法引用与构造器引用`
+
+```
+方法引用:若Lambda体中的功能,已经有方法提供了实现,可以使用方法引用(可以将方法引用理解为Lambda表达式的另外一种表现形式)
+    对象::实例方法
+    类::静态方法
+    类::实例方法
+注意:
+    ①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
+    ②若Lambda的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
+------------------
+Consumer<String> con = (x) -> System.out.println(x);
+    等价于:Consumer<String> con = System.out::println;
+BinaryOperator<Double> bo = (x,y) -> Math.pow(x,y);
+    等价于:BinaryOperator<Double> bo = Math::pow;
+BiPredicate<String,String> bp = (x,y) -> x.equals(y);
+    等价于:BinaryOperator<Double> bo = String::equals;
+```
+```
+构造器引用:构造器的参数列表,需要与函数式接口中参数列表保持一致!
+    ClassName::new 
+------------------
+Function<Integer,MyClass> fun = (x) -> new MyClass(x);
+    等价于:Function<Integer,MyClass> fun = Myclass::new;
+```
+```
+数组引用:
+    type[] :: new
+------------------
+Function<Integer,String[]> fun = (x) -> new String[x];
+    等价于:Function<Integer,String[]> fun = String[]::new;
+```
+
+###  `Stream API`
+
+### `接口中的默认方法与静态方法`
+
+### `新时间日期 API`
+
+### `其他新特性`
+
+
+## 参考链接
+
+## 结束语
+
+- 未完待续...

+ 145 - 0
source/_posts/git-navi.md

@@ -0,0 +1,145 @@
+---
+title: 个人网址导航
+date: 2018-12-15 15:32:46
+notshow: true
+categories:
+tags:
+---
+
+# 个人网址导航
+
+## 目录
+
+- [简介](#简介)
+- [列表](#列表)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介
+
+记录一些常用的网址,方便查找。
+
+## 列表
+
+### 精华帖...
+
+- [中国2018社会热点大事记-月光博客](https://www.williamlong.info/archives/5567.html)
+- [罗振宇2018“时间的朋友”跨年演讲精华版全文|罗振宇|时间的朋友|演讲_新浪科技_新浪网](http://tech.sina.com.cn/i/2019-01-01/doc-ihqhqcis2043090.shtml)
+- [一个越南新娘在中国的26年](http://renjian.163.com/18/1123/14/E1A8RTTI000181RV.html "一个越南19岁少女被卖到了中国,做家务,生孩子,用她后来赚的钱偿还了父亲买她时花的钱。她的女儿记录了母亲被卖到中国这26年发生的故事。想不到当今的社会买新娘这种事在偏远地区如此平常,希望作者的文章能够引起社会关注。")
+- [结婚十年被绿的彻底  后续2 就是这么狗血(文章较长) - 步行街主干道 - 虎扑社区](https://bbs.hupu.com/24236799.html "虎扑用户发布,写的很长,文采也不错。")
+- [腾讯的历史 - 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2018/12/tencent.html)
+- [如何开始零基础学英语,是先学音标,还是先看语法,还是先背单词?](https://mp.weixin.qq.com/s/Ak_Me0a4ADrOISIeqj-iXQ)
+- [妻子举报大连海关“科级”丈夫:睡了14名“代购”,其中1人是处女](https://weibo.com/ttarticle/p/show?id=2309404325189360998090)
+- [第91届奥斯卡金像奖全程回顾_电影节专题_电影网_1905.com](http://www.1905.com/special/filmfest/91thoscars/)
+
+### 知乎&&豆瓣...
+
+- [知乎封神榜 - 您的知乎之旅从此开始](http://www.zhihufans.com/index.php)
+- [煎蛋 - 地球上没有新鲜事](http://jandan.net/new "煎蛋以译介方式传播网络新鲜资讯")
+---
+- [在去和男友约会路上与滴滴司机C震!性开放时代C轨C震有错?](https://www.douban.com/note/715956852/)
+- [豆瓣2018年度电影榜单・携程冠名](https://movie.douban.com/annual/2018)
+- [豆瓣2017年度电影榜单](https://movie.douban.com/annual/2017)
+- [豆瓣2016年度电影榜单](https://movie.douban.com/annual2016)
+- [豆瓣2015年度电影榜单](https://movie.douban.com/annual2015)
+- [豆瓣2014年度电影榜单](https://movie.douban.com/review2014)
+---
+- [如何评价deepfakes用深度学习技术所合成的明星AV?](https://www.zhihu.com/question/264019472)
+- [水野朝阳哪位大神能评价下以及预测发展?](https://www.zhihu.com/question/37161602 "美图欣赏:https://movie.douban.com/celebrity/1363672/")
+- [超级超级贵的丝袜到底有什么不一样的地方?](https://www.zhihu.com/question/28753270 "为什么男人和女人都喜欢丝袜呢?首先是因为人类的的原始欲望,出生与子宫,喜欢全身被覆盖。其次穿着丝袜能够展示身材,对男性是一种性暗示。")
+- [文学作品里有哪些经典开场白?](https://www.zhihu.com/question/27884620)
+- [有一个漂亮的室友是一种什么样的体验?](https://www.zhihu.com/question/37006507)
+- [风清扬和东方不败的武功谁更厉害?](https://www.zhihu.com/question/20771438)
+- [美国人在日常生活中浏览的是哪些网站?](https://www.zhihu.com/question/65992444)
+- [有哪些是你踏入社会才明白的道理?](https://www.zhihu.com/question/51671791)
+- [撞见父母啪啪啪怎么办?](https://www.zhihu.com/question/28870980)
+- [什么是好的开放式厨房设计?](https://www.zhihu.com/question/31329403)
+- [郭靖和杨过谁厉害?](https://www.zhihu.com/question/20247512)
+- [如何评价秀色、冰恋、慕残?](https://www.zhihu.com/question/29874865)
+- [女生被外科男医生检查肛门,觉得难堪心里过不去坎怎么办?](https://www.zhihu.com/question/25527623)
+- [你们有刮阴毛的习惯吗?长期刮好吗?](https://www.zhihu.com/question/34942339)
+- [有哪些不知名的女生照片让你特别心动念念不忘珍藏至今,一直想知道她的名字?](https://www.zhihu.com/question/267460120)
+- [享受日本风俗店的服务,是种怎样的体验?](https://www.zhihu.com/question/36527695)
+- [大胸女生如何穿衣搭配?](https://www.zhihu.com/question/26297181)
+- [为什么部分很漂亮的女性会去当性工作者?](https://www.zhihu.com/question/29115889)
+- [大三学生手头有 6000 元,有什么好的理财投资建议?](https://www.zhihu.com/question/19982269)
+- [如何评价微博出现的各种福利姬?](https://www.zhihu.com/question/39689716)
+- [超级超级贵的丝袜到底有什么不一样的地方?](https://www.zhihu.com/question/28753270)
+
+### 微博福利...
+
+- [第一届女子健身身材大赛](https://weibo.com/5998187176/H8ANUbDYU)
+- [第一届120斤肉肉女孩大赛!只要身体健康,瘦和胖一样很美,自信的女孩最可爱!](https://weibo.com/5998187176/H6LFZdJ3K)
+- [第一届男孩子女孩子正装大赛!!正装太迷人了! ](https://weibo.com/5998187176/H3gQy0DSt "微博colouration前几天新开的主题,第一届男孩子女孩子正装大赛。这次玩起了制服诱惑,参加的美女们质量都不错哦。既然博主吸引了一帮美女粉丝,那么不管是比基尼还是正装,穿上去都好看咯。")
+- [第一届最甜笑容大赛!!甜甜的笑容超治愈!!](https://weibo.com/5998187176/GFJtB7vVr)
+- [第一届宠物大赛!!来晒晒自己的宝贝!!](https://weibo.com/5998187176/H6joz97Dc)
+- [你最性感而又不失保守的照片是哪张? ​​​​](https://weibo.com/1740806873/Guauhitiu)
+- [网友:看看胸 女:滚 网友:美胸比赛 女:[图片消息] ](https://weibo.com/6514368732/Hgd5Qitmj)
+---
+- [比特币和区块链啥原理?矿机挖矿咋回事?李永乐老师讲比特币第一集](https://weibo.com/tv/v/HgaNTlNgG?fid=1034:4338546413377740)
+- [比特币交易如何防伪?私钥公钥地址啥意思?李永乐老师讲比特币第二集](https://weibo.com/tv/v/HgkzP4q2d?fid=1034:4338921413505538)
+---
+- [买家秀](https://h5.m.taobao.com/ocean/privatenode/shop.html?sellerId=2193570902 "比如搜索商品关键字,找到商品卡片页中的店铺名称,复制名字中的连接,包含有店铺ID的一串数字,替换即可")
+- [淘宝官方出品图片墙,撩汉出品买家秀汇总](https://h5.m.taobao.com/ocean/privatenode/shop.html?sellerId=673336836)
+- [淘宝官方出品图片墙,妖怪森林买家秀汇总](https://h5.m.taobao.com/ocean/privatenode/shop.html?sellerId=109043255)
+- [媚媚内衣实验室](https://market.m.taobao.com/apps/abs/9/41/index?wh_weex=true&pageId=6273&wx_navbar_hidden=true&wx_navbar_transparent=true&accountId=1994013081&content_id=217303897213)
+
+### B站&&纪录片...
+
+- <a href="javascript:void(0);" title="日文看不懂不要禁,打开弹幕看野生字幕组翻译。第一次见面就接吻,会坠入爱河吗。">岛国的无节操综艺节目</a>
+    - [第一弹](https://www.bilibili.com/video/av17848815 "【第①弹】【高能预警/霓虹节目】刚见面就接吻的话,会迅速堕入爱河吗?职业选手就是不一般!_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili")
+    - [第三弹(推荐)](https://www.bilibili.com/video/av18666545 "【第③弹】【高能预警/霓虹节目】刚见面就接吻的话,会迅速堕入爱河吗?超辣女大学生vs肌肉男_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili")
+    - [第四弹](https://www.bilibili.com/video/av18718674 "【第④弹】【高能预警/霓虹节目】刚见面就接吻的话,会迅速堕入爱河吗?『职场同僚版』_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili")
+- [西南联大](https://v.qq.com/detail/f/fw4hh6seulgqm3k.html "讲述中国历史上一所传奇大学的历史。一所仅存八年的大学,却涵盖了中国当代在学术上的所有名人。")
+
+### 福利吧
+
+- [在线工具:趣味生成器,好玩停不下来!](http://fulibus.net/shengchengqi.html)
+- [【安卓、PC】BhVip团队破解福利软件更新合集](http://fulibus.net/bhvip.html)
+- [安卓:日本版抖音+美国版抖音(破解版不锁区)](http://fulibus.net/tiktok.html)
+- [网页视频嗅探插件猫抓+m3u8视频批量下载合并](http://fulibus.net/m3u8.html)
+- [功能强大的TUMBLR批量搬运软件–TumblThree](http://fulibus.net/tumblthree.html)
+- [安卓神器JAViewer更新2.0版本,可在线播放](http://fulibus.net/viewer.html)
+- 福利吧论坛
+    - [[林正英电影合集全46集][1981-1994 1080P/720P x264 AAC MKV][国粤中字][152G]](http://www.wnflb.com/thread-126092-1-1.html)
+    - [m3u8资源在线看,工具+资源](http://www.wnflb.com/thread-125569-1-1.html)
+    - [[周星驰高清电影合集][1988-2008 蓝光1080P MKV][国粤双语/中字][654G]](http://www.wnflb.com/thread-126140-1-1.html)
+
+### 在线工具站
+
+- [在线工具 - aTool - 最全面的工具集合](http://www.atool.org/)
+- [GIF在线压缩_GIF裁剪制作工具_视频转GIF软件_GIF之家](https://tool.gifhome.com/)
+- [Tinypng工具用于压缩你的图片,减少服务器占用](https://tinypng.com/ "或者https://tinyjpg.com/,方便各位压缩各种图片,压缩比例超过60%,完全免费!一次最多可压缩20张图片!")
+- [Css在线解压缩/整理/格式化 - 在线工具](https://tool.lu/css/ "将复制好的css粘贴进去,点击压缩;压缩完成后,全选复制压缩后的css代码。")
+- [Javascript在线解压缩 - 在线工具](https://tool.lu/js/ "将复制好的js 粘贴进去,点击净化;需要注意的是,有些js代码压缩后,会无效,所以请自行尝试!")
+- [IconPng.com 爱看图标网,免费中文图标搜索引擎!](https://www.icontuku.com/ "收录了99832个免费的PPT图标ICON素材及网页设计图标资源,具有按分类、色系、标题、系列搜索图标的功能,帮助您以最快的速度找到喜欢的图标ICONS。")
+- [emoji短网址 - MEZW](https://e.mezw.com/ "将普通网站的链接转换为emoji链接。emoji源自日本,中文称作表情符号,QQ、微信、iMessage等沟通中都会使用emoji。")
+- [王斌给您对对联 !](https://ai.binwang.me/couplet/ "V2EX原贴:用深度学习做了一个自动对对联的系统(https://www.v2ex.com/t/401537?p=3)")
+- [Gif图片添加字幕 - 应景图](http://www.yingjingtu.com/)
+- [小鸡词典 - 最全的网络流行语词典](https://jikipedia.com/ "很多流行的词语还没有收录到各大词典,却可以在小鸡词典搜索到;不少词条搞笑无厘头,撰写词条还会获得红包。")
+- [四大名著,中国四大名著,四大名著小说](http://www.sdmz.net/ "这是一个关于地理的网站,介绍了四大名著西游、三国、红楼、水壶中的地图、人物关系图等,电子地图还可以进行互动。")
+- [免费在线logo设计,标志设计,网站标志设计,公司标志设计,免费](https://www.logoko.com.cn/ "强大的免费在线LOGO生成工具,输入品牌或名字,选择所在行业,系统会自动根据设定设计LOGO风格,当然你也可以后期修改。")
+
+### 番茄站
+
+- [Wayback Machine](https://web.archive.org/ "用于备份网络上所有网站的内容,包括网站内的其他链接url。它会扫描机会所有网站,并每隔一段时间对每个网站进行备份,存在它自己的服务器上。目前,它已经存储了600多亿条url。")
+- [Shadowsocks 一键安装脚本(四合一)  |  秋水逸冰](https://teddysun.com/486.html)
+- Youtube
+    - [北京老大爷谈性张口就来,黄段子才是顺口溜!电影院里还那啥~](https://www.youtube.com/watch?v=wZsdOvwkfCY)
+    - [和陌生人说话完整版 20180927期 “小混混”搏命伊拉克:我只有死在那儿才值400万](https://www.youtube.com/watch?v=USTtGV1Vyac&t=19s)
+    - [东北饭店,你瞅啥,瞅你咋地,劝都劝不住,直接酒瓶的轮上,满脑出血](https://www.youtube.com/watch?v=DjYdo0dNW8Y)
+    - [铁牛私房课-性爱教学](https://www.youtube.com/playlist?list=PLasRUr-dn8CkU7d7g8EpHIX9uVwqxxxGD)
+- Pornhub
+    - [JAPANESE ANAL MASTURBATION SOLO GIRL](https://www.pornhub.com/view_video.php?viewkey=ph5c51d89ae6c70)
+    - [ZIAxNOA](https://www.pornhub.com/model/ziaxnoa)
+    - [BLOWJOB SKILL](https://www.pornhub.com/view_video.php?viewkey=ph5c1b804ad3492)
+    - [Y GIRLFRIEND IS HARD ON ME IN BED, AND MY GIRLFRIEND IS EXCITED](https://www.pornhub.com/view_video.php?viewkey=ph5ab787f0f0bc7)
+- Twitter
+    - [森罗万象](https://twitter.com/287076147/)
+
+## 参考链接
+
+## 结束语
+
+- 未完待续...
+

+ 86 - 0
source/_posts/os-linux-packages-install.md

@@ -0,0 +1,86 @@
+---
+title: Linux 常用程序包的安装与配置
+date: 2019-03-09 17:07:04
+categories:
+- 操作系统
+tags:
+- linux
+---
+
+# Linux 常用程序包的安装与配置
+
+## 目录
+
+- [简介](#简介)
+- [正篇](#正篇)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介
+
+整理在 Linux 环境下常用软件包的安装和配置.
+
+## 正篇
+
+### `JDK的安装和配置`
+
+1. 检查 CentOS 有没有安装其他版本的 JDK,例如 opentJDK等等
+    ```
+    # java -version
+    # rpm -qa | grep "java"
+    -----------------------
+    注:如果有的话,可配合rpm命令或者yum命令先卸载掉,其中yum命令能自动解决依赖等问题.
+        eg:# rpm -e --nodeps tzdata-java-2016j-1.el6.noarch java-1.6.0-openjdk-1.6.0.41-1.13.13.1.el6_8.x86_64 java-1.7.0-openjdk-1.7.0.131-2.6.9.0.el6_8.x86_64
+    ```
+2. 下载 JDK 程序包,rpm或者tar.gz格式的都可以
+    ```
+    方法1:
+        1. 去jdk官网找到指定版本的jdk,并复制其链接地址
+        2. wget -P /opt/setups/ https://download.oracle.com/otn-pub/java/jdk/8u201-b09/42970487e3af4f5aa5bca3f542482c60/jdk-8u201-linux-x64.tar.gz?AuthParam=1552124414_039c05a3b27cb7d09e715788bf78b6e0
+        3. 重命名即可
+    方法2:
+        1. 去jdk官网找到指定版本的jdk,下载到本地
+        2. 通过rz等上传工具将程序包上传到/opt/setups目录中去
+    ```
+3. 解压到指定目录
+    ```
+    # mkdir -pv /usr/program
+    # tar -zxf jdk-8u201-linux-x64.tar.gz -C /usr/program
+    ```
+4. 配置环境变量,使用vim编辑/etc/profile.d/my.sh文件
+    ```
+    # JDK
+    JAVA_HOME=/usr/program/jdk1.8.0_201
+    JRE_HOME=$JAVA_HOME/jre
+    PATH=$JAVA_HOME/bin:$PATH
+    CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
+    export JAVA_HOME
+    export JRE_HOME
+    export PATH
+    export CLASSPATH
+    ```
+5. 重新读取配置文件,使之生效
+    ```
+    # source /etc/profile.d/my.sh
+    ```
+6. 测试是否安装成功
+    ```
+    # java -version
+    ```
+    
+### `RocketMQ的集群部署`
+
+详见"消息中间件之 RocketMQ"章节
+
+### `Redis的集群部署`
+
+详见"分布式缓存框架之 Redis&Ehcache"章节
+
+
+## 参考链接
+
+<https://github.com/judasn/Linux-Tutorial>
+
+## 结束语
+
+- 未完待续...

+ 1173 - 0
source/_posts/os-linux-sysadmin-first.md

@@ -0,0 +1,1173 @@
+---
+title: Linux 系统管理:磁盘、文件系统、RAID、LVM2、程序包
+date: 2019-01-21 21:19:31
+categories:
+- 操作系统
+tags:
+- linux
+---
+
+# Linux 系统管理
+
+## 目录
+
+- [简介](#简介)
+- [正篇](#正篇)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介
+
+与系统管理相关...
+```
+磁盘管理、文件系统管理
+RAID基础原理、LVM2
+网络管理:TCP/IP协议、Linux网络属性配置
+程序包管理:rpm, yum
+进程管理:htop, glance, tsar等
+sed和awk
+Linux系统开机流程
+内核管理基础知识:编译内核、模块
+Linux系统裁剪:kernel+busybox
+```
+
+## 正篇
+
+### 磁盘管理
+
+```
+I/O设备:
+    磁盘:用来实现本地数据的持久存储功能
+    网卡:通过网络交换数据
+    键盘、鼠标、显示器等
+-----------------
+I/O设备在硬件层次上有I/O Ports来标识,即当前主机上的I/O设备地址
+I/O设备在操作系统层次上有设备文件来标识
+-----------------
+块设备:block device,存取单位“块”,支持以"block"为单位进行随机访问,磁盘
+字符设备:character device,存取单位“字符”,支持以"character"为单位进行线性访问,键盘
+```
+- `设备文件`
+    ```
+    特殊文件
+    只有元数据(inode),而没有数据
+    关联至一个设备驱动程序,进而能够跟与之对应硬件设备进行通信
+    -----------------
+    设备号:
+        主设备号:major number, 标识设备类型,进而确定要加载的驱动程序
+        次设备号:minor number, 标识同一类型下的不同设备
+    -----------------
+    设备文件的命名:由ICANN
+        /dev/DEV_FILE
+    ```
+- `硬盘接口类型`
+    ```
+    并行:
+        IDE:早期的个人桌面常用接口,后升级为SATA,133MB/s
+        SCSI(Small Computer System Interface):与IDE同时代的企业级接口,640MB/s
+            使用时长,读写方面大概相当于IDE接口的4-8倍,它的rpm(转速,rotations per minute)很高
+    串行:
+        SATA:6Gbps/8
+        SAS:6Gbps/8
+        USB:480MB/s
+
+    以上皆为接口速率,非硬件设备速率
+    ```
+- `磁盘设备的设备文件命名`
+    ```
+    CentOS5:
+        IDE: /dev/hd[a-z]
+        SCSI, SATA, SAS, USB: /dev/sd[a-z]
+    CentOS6以后,全都统一为/dev/sd[a-z]
+        不同设备:a-z
+            /dev/sda, /dev/sdb, ...
+        同一设备上的不同分区(每个分区分完以后都会被当作一个独立设备来管理):1,2, ...
+            主+扩展:/dev/sda[1-4]
+            逻辑:/dev/sda[5]
+    ```
+- `机械式硬盘`
+    ```
+    磁道:track
+        扇区:sector,512bytes,现在最大可以到4K
+    柱面:cylinder
+        分区根据柱面划分,一个柱面只能属于一个分区,多个柱面由外而内组合在一起当作一个分区来使用,靠外柱面的这些分区读写性能好一点
+    -----------------
+    0磁道0扇区:512bytes,被预留出来,不属于任何分区,常被成为MBR
+        MBR: Master Boot Record,主引导记录,引导启动OS
+            446bytes: bootloader, 引导加载器程序
+            64bytes:分区表,记录分了哪几个区,每个区从哪开始从哪结束
+                16bytes: 标识一个分区,所以一个磁盘最多只能有4个主分区
+            2bytes: 55AA,MBR有效性标记
+
+        4个主分区:
+            3主分区+1扩展分区(切割1个或多个逻辑分区)
+                扩展分区不能直接当空间使用,只是分区表的一个扩展指向
+    -----------------
+    现代的MBR机制无法识别2T以上的磁盘空间;
+    现在的硬盘由UEFI进行引导并结合GPT机制以后,能支持更多的磁盘分区,能识别2T以上的磁盘空间
+    ```
+- `分区管理工具(fdisk, parted, sfdisk)`
+    ```
+    fdisk:历久弥坚的,各大Linux发行版都默认有提供,能满足大多数场景中的管理需要,对于一块硬盘来讲,最多只能管理15分区。
+    ----------------------------
+    查看指定设备磁盘分区信息:
+        # fdisk -l [device...]
+            后面不跟设备则显示所有设备的磁盘分区信息
+    创建/管理分区:
+        # fdisk device
+            交互式界面,有许多子命令
+                p: print, 显示磁盘已有分区
+                n: new, 新建分区
+                w: write, 保存(写入磁盘)并退出
+                q: quit,  不保存(放弃更新)退出
+                ------------
+                m: 获取帮助
+                d: delete,删除分区
+                l: 列出所有分区ID
+                t: 调整分区ID
+    查看内核是否已经识别新的分区:
+        # cat /proc/partitions
+    通知内核重新读取硬盘分区表:
+        对于已经有分区处于使用状态的磁盘来讲,新建分区后需要让内核重读其分区表
+        CentOS 5:
+            # partprobe [DEVICE]
+        CentOS 6:
+            # partx -a [DEVICE]
+                -n M:N
+            # kpartx -af [DEVICE]
+    ```
+    
+### 文件系统管理
+
+```
+Linux支持众多类型的文件系统: ext2, ext3, ext4, xfs, btrfs, reiserfs, jfs, swap
+    ext2,ext3,ext4: ext2,ext3在centos5上流行;ext4在centos6上流行,在centos7上依然可以使用
+    xfs, btrfs: xfs在centos6上支持,centos7上流行;btrfs是centos7上自带的非常流行的非常强大的支持64位的空间可自动扩展的文件系统
+    swap: 交换分区,缓解物理内存资源不够用的情况
+    iso9660:光盘
+Windows:fat32(在linux上被识别为vfat), ntfs(linux对ntfs的支持还不是特别好)
+Unix: FFS, UFS, JFS2
+网络文件系统:NFS, CIFS
+集群文件系统:GFS2, OCFS2
+分布式文件系统:ceph, moosefs, mogilefs, GlusterFS, Lustre
+---------------------------
+根据其是否支持"journal(日志)"功能:
+    日志型文件系统: ext3, ext4, xfs, ...
+        系统检测速度快,但每次文件的写操作都会多一次IO操作,因此性能上可能不如非日志型文件系统好,不过到现在为止这种差别是微乎其微的,但带来的好处却是显而易见的.
+        推荐使用
+    非日志型文件系统: ext2, vfat
+---------------------------
+文件系统的组成部分:
+    内核中的模块:ext4, xfs, vfat, ...
+        Linux内核是模块化的,这些模块支持动态装载和卸载;文件系统可能会被直接打包进内核,也可以被编译成内核模块;即任何一个文件系统想要被使用,对应的内核模块一定要被装载
+        查看内核中已装载的所有模块:# lsmod
+    用户空间的管理工具:mkfs.ext4, mkfs.xfs, mkfs.btrfs, mkfs.vfat, ...
+Linux的虚拟文件系统:VFS
+    程序员和各个文件系统的中间层
+---------------------------
+查看系统支持哪些文件系统类型:
+    # cat /proc/filesystems
+---------------------------
+超级块用来存储整个分区当中的整个结构划分的,例如有多少个块组,每个块组有多少个块,每个块有多大,每个组当中有多少块被占用多少块是free的等等
+为防止超级块损坏,需要对超级块做备份,通常格式化以后会显示超级块的位置(存放在块组当中的某些位置)
+---------------------------
+Linux启动过程:
+    1.加电自检
+    2.装载bootloader
+    3.而后bootloader去装载用户所选定的操作系统的内核(应用程序)
+    4.内核自身完成初始化以后,取得系统控制权,首先去装载根文件系统(rootfs)所在的分区,该分区跟内核所在的分区可以不是同一个分区
+        /etc,/bin,/sbin,/lib,/lib64,/proc,/sys,/dev等都在该分区上,且这些目录不能单独分区
+    5.内核启动/sbin/init程序,由它代替内核来完成一切跟用户相关的程序的启动
+        # pstree
+```
+- `创建文件系统(格式化)`
+    ```
+    即需要用户空间的管理工具来调用内核中所提供的功能方能实现我们所期望拥有到的文件系统所谓的管理功能
+    ---------------------------
+    mkfs:build a Linux filesystem
+        (1) # mkfs.FS_TYPE /dev/DEVICE
+        (2) # mkfs -t FS_TYPE /dev/DEVICE
+
+        -L 'LABEL': 设定卷标,将来可以根据卷标来对这个分区执行调用操作
+        -f:强制
+    mke2fs:ext系列文件系统专用管理工具
+        -t {ext2|ext3|ext4}:指定文件系统 
+        -b {1024|2048|4096}:指定块大小,块是分区格式化以后的一个单独存储单位,一般包含2个、4个或8个扇区,即块大小为1k,2k,4k;
+        -L 'LABEL',设定卷标
+        -j: journal,相当于 -t ext3
+            mkfs.ext3 = mkfs -t ext3 = mke2fs -j = mke2fs -t ext3
+        -i #: 为数据空间中每多少个字节创建一个inode;此大小不应该小于block的大小;一个块只能属于一个文件,一个文件至少包含一个块
+        -N #:为数据空间创建个多少个inode;
+        -m #: 为管理人员预留的空间占据的百分比;默认为5
+        -O FEATURE[,...]:启用指定特性
+            -O ^FEATURE:关闭指定特性
+    mkswap:创建交换分区
+        # mkswap [options] device
+            -L 'LABEL'
+        前提:调整其分区的ID为82;
+    ```
+- `其它常用工具`
+    ```
+    blkid:查看块设备属性信息
+        # blkid [OPTION]... [DEVICE]
+            -U UUID: 根据指定的UUID来查找对应的设备
+            -L LABEL:根据指定的LABEL来查找对应的设备
+    e2label:管理ext系列文件系统的LABEL
+        # e2label DEVICE [LABEL]
+            除了可以查看块设备的LABEL,还可以设定LABEL,避免将来需要修改LABEL时要重新格式化了
+    tune2fs:重新设定ext系列文件系统的可调整参数的值(块大小无法调整)
+        # tune2fs [OPTION]... DEVICE
+            -l:查看指定文件系统超级块信息;super block
+            -L 'LABEL':修改卷标
+            -m #:修预留给管理员的空间百分比
+            -j: 将ext2升级为ext3
+            -O [^]FEATURE: 文件系统属性启用或禁用
+            -o [^]mount-options: 调整文件系统的默认挂载选项
+            -U UUID: 修改UUID号
+    dumpe2fs:查看ext系列文件系统的超级块信息,还能查看文件系统的组织结构信息(块组)
+        # dumpe2fs [OPTION]... DEVICE
+            -h:只查看超级块信息
+    ```
+- `文件系统检测`
+    ```
+    因进程意外中止或系统崩溃等情况导入写入操作非正常中止时,或者非法关机时,可能会导致文件损坏;此时,应该修复文件系统
+    虽然开机以后会自动检测,但是自动检测会导致开机速度过慢,因此很多非关键性的文件系统建议开机时不自动检测,而是开机以后可以手动检测
+    ---------------------------
+    fsck: File System CheCk
+        (1) # fsck.FS_TYPE /dev/DEVICE
+        (2) # fsck -t FS_TYPE /dev/DEVICE
+
+        -a: 自动修复错误
+        -r: 交互式修复错误
+
+        Note: FS_TYPE一定要与分区上已有的文件系统类型相同;
+    e2fsck:ext系列文件专用的检测修复工具
+        -y:自动回答为yes; 
+        -f:强制进行检测修复;
+    ```
+- `文件系统挂载`
+    ```
+    将额外的文件系统(分区)与根文件系统上某现存的目录建立起关联关系,进而使得此目录做为其它文件系统的访问入口的行为(过程)称之为挂载;
+        目录中(挂载点)的原有文件在挂载完成后会被临时隐藏
+        即把要关联的设备关联至挂载点(另一个文件系统的访问入口)
+    默认只有管理员才有权限;
+    解除此关联关系的过程称之为卸载;
+    根文件系统(rootfs)无需挂载,它是由内核探测来实现装载的;
+    ---------------------------
+    挂载:mount DEVICE MOUNT_POINT
+        查看所有已经挂载的设备:
+                # cat /etc/mtab
+                # mount
+                    通过查看/etc/mtab文件显示当前系统已挂载的所有设备
+                # cat /proc/mounts
+                    查看内核追踪到的已挂载的所有设备
+        # mount [-fnrsvw] [-t vfstype] [-o options] device dir
+            device:指明要挂载的设备;
+                (1) 设备文件:例如/dev/sda5
+                (2) 卷标:-L 'LABEL', 例如 -L 'MYDATA'
+                (3) UUID, -U 'UUID':例如 -U '0c50523c-43f1-45e7-85c0-a126711d406e'
+                (4) 伪文件系统名称:proc, sysfs, devtmpfs, configfs
+            dir:挂载点
+                事先存在;建议使用空目录;
+
+            常用命令选项:
+                -t vfstype:指定要挂载的设备上的文件系统类型,可省略,会自动调用blkid命令来判断此目录的文件系统的类型;
+                -r: readonly,只读挂载;
+                -w: read and write, 读写挂载;
+                -n: 挂载时,不更新/etc/mtab文件;
+                -a:自动挂载所有支持自动挂载的设备;(定义在了/etc/fstab文件中,且挂载选项中有“自动挂载”功能)
+                -L 'LABEL': 以卷标指定要挂载的设备;
+                -U 'UUID': 以UUID指定要挂载的设备;
+                -B, --bind: 绑定目录到另一个目录上;
+
+            -o options:(文件系统挂载时所启用的特性)
+                async:异步模式;性能高,安全可靠性低
+                sync:同步模式;性能差,安全可靠性高
+                atime/noatime:文件和目录被访问时是否更新最近一次的访问时间戳
+                diratime/nodiratime:目录被访问时是否更新最近一次的访问时间戳
+                auto/noauto:是否支持(mount的-a选项)自动挂载
+                exec/noexec:是否支持将文件系统上应用程序运行为进程
+                dev/nodev:是否支持在此文件系统上使用设备文件;
+                suid/nosuid:是否支持在此设备的文件上使用suid
+                remount:重新挂载,通常用于不卸载的情况下重新指定挂载选项
+                ro:只读
+                rw:读写
+                user/nouser:是否允许普通用户挂载此设备
+                acl:启用此文件系统上的acl功能,默认不支持
+
+                注意:上述选项可多个同时使用,彼此使用逗号分隔;
+                      默认挂载选项:defaults
+                            rw, suid, dev, exec, auto, nouser, and async
+                      eg:# mount -o remount,ro /dev/sda3
+    ---------------------------
+    卸载:
+        # umount DEVICE
+        # umount MOUNT_POINT
+        
+        进程正在使用中的设备无法被卸载;挂载点没有被进程访问时方可以卸载
+        查看哪些进程正在访问指定文件系统:
+            # fuser -v MOUNT_POINT
+        终止所有正在访问指定的文件系统的进程:
+            # fuser -km MOUNT_POINT
+    ---------------------------
+    挂载交换分区:
+        启用:# swapon [OPTION]... [DEVICE]
+                -a:激活所有的交换分区;
+                -p PRIORITY:指定优先级;
+        禁用:# swapoff [OPTION]... [DEVICE]
+                -a:禁用所有;
+    ---------------------------
+    挂载光盘设备:
+        光盘设备文件:
+            IDE: /dev/hdc
+                对于红帽系列,RHEL6或CentOs6以后,统一为sr0...
+            SATA: /dev/sr0
+
+            符号链接文件:/dev/cdrom,/dev/cdrw,/dev/dvd,/dev/dvdrw
+        # mount -r /dev/cdrom /media/cdrom
+        # umount /dev/cdrom
+    ```
+    ```
+    自动挂载的设备的配置文件:/etc/fstab
+         使用mount命令手动挂载的文件系统在系统重启以后会失效(不会被自动挂载),需要添加至/etc/fstab文件中才能自动挂载
+         因为系统初始化过程的脚本会读取此文件(每行定义一个要挂载的文件系统),并尝试使用mount/swapon来实现额外文件系统的挂载
+         ---------------------------
+         UUID=3437f1a0-f850-4f1b-8a7c-819c5f6a29e4 /   ext4    defaults,discard,noatime      1 1
+         UUID=ad1361f7-4ab4-4252-ba00-5d4e5d8590fb /boot   ext3    defaults     1 2
+         
+         6字段:
+            要挂载的设备或伪文件系统:
+               设备文件、LABEL(LABEL="")、UUID(UUID="")、伪文件系统名称(proc, sysfs)
+            挂载点:
+            文件系统类型:
+            挂载选项:
+                defaults,挂载选项可以有多个,彼此间使用逗号分隔;
+            转储频率:
+                0:从不转储(不做备份)
+                1: 每天转储
+                2: 每隔一天转储
+            自检次序:
+                0:不自检,一般来讲,额外创建的文件系统都无须自动自检,也不要转储
+                1:首先自检,通常只有根文件系统(rootfs)需要首先自检
+                2:次级自检,不同的设备可以使用同一个自检次序
+                ...
+    ```
+- `磁盘空间查看工具`
+    ```
+    查看内存及交换分区的使用信息:
+        # free [OPTION]
+            -m: 以MB为单位
+            -g: 以GB为单位
+        注:其中"+/- buffer/cached"的userd和free的值为Mem的值+/-(buffers+cached)的值
+    查看文件系统空间占用等信息:
+        # df [OPTION]
+            -h: human-readable,人类易读的
+            -i:inodes instead of blocks,显示inode的使用信息而非默认的磁盘空间使用信息
+            -P: 以Posix兼容的格式输出,每个设备信息显示在同一行,防止路径长的设备多行显示
+    查看某目录总体空间占用状态
+        # du [OPTION]... DIR
+            -h: human-readable
+            -s: summary,不加此选项默认显示DIR下的每个文件的大小,加上此选项显示此目录及目录下所有文件的大小之和
+    ```
+- `文件系统上的其它概念`
+    ```
+    存储空间:
+        元数据区:
+            元数据:存放文件的大小,时间戳,权限,属主、属组以及对应的数据存储在哪些磁盘块上
+                注:文件名虽然是元数据,但并不包含在Inode当中
+            Inode: Index Node, 索引节点
+                每一个能存储单个文件的所有属性信息(元数据)并按照特定格式组织的这么一个存储空间,被称之为一个Inode
+                每个文件系统上可能有N个Inode,为了方便引用某一个Inode,会给Inode进行编号,每个inode都有其编号,可通过ls -i来查看
+            地址指针:
+                直接指针:直接指向几个磁盘块,由于Inode在指向Block(引用Block编号)的空间是有限的,这样引用的块的数量较少
+                间接指针:Inode存储的是指向另一块的区域,这样能引用更多的Block
+                三级指针:
+        数据区:
+            数据:
+    -----------------------------------
+    bitmap:位图索引
+        inode bitmap
+            对位标识每个inode空闲与否的状态信息
+        block bitmap
+        
+        所以每个文件系统格式化以后,就分了n个block,并将这些block分成了N个块组,块组中包含元数据区和数据区,元数据区存放了Inode 
+        table(存放Inode)以及为Inode和Block做索引的位图,而每个块组中的布局结构信息信息是保存在各自块组的GDT(块组描述符)当中
+            包括块组从第几个块开始到第几个块结束,其中哪一个块存的是Inode位图,哪一个块存的是Block位图,哪些块存的是Inode table的,剩余的哪些块是用来存放数据的
+    -----------------------------------
+    目录也是一个文件,在磁盘上也占据磁盘块,也包括元数据和数据,数据区存储的是(直接附属于此目录)文件名以及文件名对应的Inode编号
+        相当于前面所说的"路径映射"
+    -----------------------------------
+    链接文件:
+        硬链接:指向同一个inode的多个不同路径。创建文件的硬链接即为为inode创建新的引用路径,因此会增加其引用计数。
+            不能够对目录进行,容易导致循环引用;但目录也是有硬链接的,不过是文件系统自带的固有属性(.和..)
+            不能跨分区进行;
+            
+            通俗的讲就是两个路径的文件名指向同一个inode,此时,一个文件就称为另一个文件的硬链接
+        软链接(符号链接):指向的是另一个文件的路径。其链接文件的大小为指向的路径字符串的长度,不增加或减少目标文件inode的引用计数。
+            能够对目录进行;
+            能跨分区进行;
+    # ln [-sv] SRC DEST   将源文件链接至哪个地方
+        -s:symbolic link,不加-s就是硬链接,加-s就是创建符号链接
+        -v: verbose,显示过程
+    -----------------------------------
+    文件管理操作对文件的影响:
+        文件删除:inode被标记为空闲(可用状态从1改为0),此inode指向的磁盘块被标记为空闲(可用状态从1改为0)。
+            如果inode被引用了多次(Inode内部有计数器),且此次删除未使得其引用计数降为0的话,Inode是不会被标记为未用的,这意味着文件被删除仅删除了一个访问路径。
+        文件复制:创建一个新的空文件,并将原文件中的所有数据在新文件指向的磁盘块中再写一次的过程。
+            所以这个操作包括读出数据,再写入数据的这么一个过程,所以速度比较慢,即使是在同一个分区中进行。
+        文件移动:如果在同一个分区移动,移动文件仅是改变了文件访问路径;如果是跨分区移动,在新分区创建文件,从原分区上把数据复制过去,删除原分区数据。
+            所以同分区移动速度快;跨分区移动速度慢,跟文件复制没太大区别。
+    练习:
+    -----------------------------------
+        1、创建一个20G的文件系统,块大小为2048,文件系统ext4,卷标为TEST,要求此分区开机后自动挂载至/testing目录,且默认有acl挂载选项;
+            (1) 创建20G分区:
+            (2) 格式化:
+                mke2fs -t ext4 -b 2048 -L 'TEST' /dev/DEVICE
+            (3) 编辑/etc/fstab文件
+                LABEL='TEST' 	/testing 	ext4 	defaults,acl 	0 0
+            (4) 测试
+                mount
+        2、写一个脚本,完成如下功能:
+            (1) 列出当前系统识别到的所有磁盘设备;
+                fdisk -l /dev/[hs]da
+            (2) 如磁盘数量为1,则显示其空间使用信息;否则,则显示最后一个磁盘上的空间使用信息;
+                disks=$(fdisk -l $(fdisk -l /dev/[sh]d[a-z] | grep -o "^Disk /dev/[sh]d[a-z]" | wc -l)
+                if [ $disks -eq 1 ]; then 
+                    fdisk -l /dev/[hs]da
+                else 
+                    fdisk -l $(fdisk -l /dev/[sh]d[a-z] | grep -o "^Disk /dev/[sh]d[a-z]" | tail -1 | cut -d' ' -f2)
+                fi
+    ```
+- `btrfs文件系统管理与应用`
+    ```
+    概述:
+        btrfs(B-tree FS,Butter FS,Better FS)在CentOS7上是技术预览版.采用GPL授权,由Oracle在2007年研发的64位FS.
+        主要设计目标是用来取代Linux的ext3/4系列FS.
+    核心特性:
+        多物理卷支持:支持将多个底层物理设备组织成同一个FS来直接使用;原生支持RAID功能,以及联机“添加”、“移除”、“修改”物理卷;
+        写时复制更新机制(CoW):修改文件时先复制一份,对目标新复制的一份进行更新,将文件名指向的原空间改为指向新空间,万一改错了还能恢复更新前的文件;
+            这种机制在需要快速修复文件的场景中是极其有用的
+        数据及元数据校验码机制(checksum):存储文件时将数据以及元数据的校验码通过文件某些属性来保存下来,读取文件时方便快速去检测该文件是否受损了并进行自动修复;
+            这种机制极大的保证了数据的可靠性
+        子卷(sub_volume):在一个卷上可以创建多个子卷,每一个子卷单独使用和挂载;
+        快照:子卷的一个非完全副本,基于Cow机制来实现,与LVM中的快照基本相同,但它比LVM有个增强的特性(增量快照机制),支持快照的快照;
+        透明压缩机制:当存储文件时想节约空间,能自动能够通过占据cpu的时钟周期来完成数据压缩以后存储,对用户来讲是不知道的,在读取时又能自动解压缩;
+            这种机制会消耗更多的cpu时钟周期
+    ```
+    ```
+    现在的工具大多数都是将多个命令(或功能)合并成一个命令,而后将每一个功能使用子命令来实现,btrfs命令就是这样的
+    --------------------------------------
+    文件系统创建:
+        mkfs.btrfs [options...] <devices...>
+            -L 'LABEL': 指定卷标
+            -d <type>: 指明数据是如何存放的,支持raid0, raid1, raid5, raid6, raid10, single
+            -m <profile>: 指明元数据是如何存放的,支持raid0, raid1, raid5, raid6, raid10, single, dup
+            -O <feature>: 在格式化时直接开启btrfs的哪些特性,老版本内核未必支持所有特性
+                -O list-all: 列出支持的所有feature;
+        eg:mkfs.btrfs -L mydata /dev/sdb /dev/sdc
+    文件系统挂载:
+        mount -t btrfs /dev/sdb MOUNT_POINT
+        
+        透明压缩机制:mount命令在CentOS上支持的子选项'compress'
+            mount -o compress={lzo|zlib} DEVICE MOUNT_POINT
+            
+        单独挂载btrfs的子卷时,需要先将btrfs的父卷umount,再挂载子卷;只挂载父卷时,子卷中的数据通过父卷后面的路径都能访问到
+            umount /mydata
+            mount -o subvol=logs /dev/sdb /mnt
+            
+            因此在CentOS7上指明要安装btrfs时,可以在btrfs上创建多个子卷,一个叫做root,用来挂载/,一个叫做usr,用来挂载/usr等等,那个时候可以只用来挂载子卷而不挂载父卷.
+
+    将ext系列文件系统转换成btrfs:
+        # btrfs-convert /dev/sdd1
+    将btrfs重新降级回ext系列FS:     
+        # umount /dev/sdd1
+        # btrfs-convert -r /dev/sdd1
+    --------------------------------------
+    btrfs常用子命令:可用'man btrfs-子命令'查看说明
+        btrfs subvolume:管理btrfs当中的子卷
+            create:创建子卷,而非创建子目录
+                eg:# btrfs subvolume create /mydata/logs
+            delete:可通过其路径删除子卷,前提时先要挂载父卷
+                eg:# btrfs subvolume delete /mydata/logs
+            list:列出btrfs当中的所有子卷
+                eg:# btrfs subvolume list /
+                eg:# btrfs subvolume list /mydata
+            show:查看btrfs当中某个子卷的详细信息
+            snapshot:针对btrfs当中的子卷创建快照,快照卷与子卷必须在同一个父卷中
+                eg:# btrfs subvolume snapshot /mydata/logs /mydata/logs_snapshot
+                eg:# btrfs subvolume delete /mydata/logs_snapshot
+        btrfs filesystem:管理btrfs自己的
+            df:查看已挂载的btrfs的空间使用率情况
+            show:查看已有的btrfs属性信息
+            sync:将这个文件系统缓存的数据都同步到磁盘上去
+            resize:调整大小
+            label:指明或显示卷标
+        btrfs device:管理btrfs的底层设备
+            add:新增物理卷
+            delete:移除物理卷,不会影响其中原有的数据,拆除时会自动移动这个设备上的数据其他设备上去,比LVM2强大
+        btrfs balance:管理btrfs的数据均衡操作(重新均衡数据)
+            start:启动balance
+                -dconvert=single:修改数据的存储类型,移除物理卷时需要先做此操作
+                -mconvert=raid1:修改元数据的存储类型,移除物理卷时需要先做此操作
+            pause:暂停
+            resume:继续
+            status:
+    ```
+
+### RAID 基础原理
+
+```
+RAID全称Redundant Arrays of Inexpensive Drives,廉价冗余磁盘阵列
+                           Independent 独立冗余磁盘阵列
+Berkeley: A case for Redundant Arrays of Inexpensive Disks RAID
+    这篇论文阐述了将多块廉价的硬盘(IDE接口)按照某种特别的结构给组织起来当作一个设备来使用,从而能够根据不同的组合方式来提高其IO能力或者提高其耐用性。
+
+    提高IO能力:
+        磁盘并行读写;将来去买RAID控制器时,尤其是带内存的,要检查有没有供电功能
+    提高耐用性:
+        磁盘冗余来实现
+        不会因为磁盘损坏而导致业务终止或数据丢失,但是人为的损坏丢失跟磁盘损坏没关系,该备份的策略一个也不能少
+
+    RAID实现的方式:
+        外接式磁盘阵列(硬件实现):通过扩展卡提供适配能力,在BIOS当中实现
+        内接式RAID(硬件实现):主板集成RAID控制器,在BIOS当中实现
+        Software RAID:主机压根没有硬件设备支持,可通过软件的方式实现RAID
+            在OS中看到的是多个基本的磁盘设备、磁盘分区等,而后将这多个块设备可以组织一个单独的设备使用,即为软RAID
+```
+```
+级别:level,多块磁盘组织在一起的工作方式有所不同
+    单一类型:
+        RAID-0:0, 条带卷,strip; 将文件切割成chunk,分散到各个磁盘上
+            读、写性能提升;
+            无容错能力
+            可用空间:N*min(S1,S2,...)
+            最少磁盘数:2, 2+
+        RAID-1: 1, 镜像卷,mirror;将文件切割成chunk,每个磁盘都要保存
+            读性能提升、写性能略有下降;
+            有冗余能力
+            可用空间:1*min(S1,S2,...)
+            最少磁盘数:2, 2+
+        ...
+        RAID-4: 至少3块盘,将文件chunk,第一块盘存chunk1,第二块盘存chunk2,第三块盘存前2块盘的chunk的校验码(异或操作:1101, 0110, 1011)
+            读、写性能提升;
+            有容错能力(最多坏一块磁盘)
+            可用空间:(N-1)*min(S1,S2,...)
+            最少磁盘数:3, 3+
+        RAID-5:由于RAID-4有一块盘是做为集中校验盘,有可能会有性能瓶颈存在,所以在RAID-4的基础上改进,采用轮流做校验盘的机制
+            读、写性能提升;
+            有容错能力(最多坏一块磁盘)
+            可用空间:(N-1)*min(S1,S2,...)
+            最少磁盘数:3, 3+
+        RAID-6: 在RAID-5的基础上,采用2块盘作为循环校验盘
+            读、写性能提升;
+            有容错能力(最多坏两块磁盘)
+            可用空间:(N-2)*min(S1,S2,...)
+            最少磁盘数:4, 4+
+    混合类型: 
+        RAID-10: 先将所有硬盘两两一组作为镜像卷,再在此基础上做成条带卷
+            读、写性能提升;
+            有容错能力:每组镜像最多只能坏一块;
+            可用空间:N*min(S1,S2,...)/2
+            最少磁盘数:4, 4+
+        RAID-01: 先将所有硬盘分为2组,每组做成条带卷,再在此基础上做成镜像卷
+        RAID-50:
+        RAID-7: 某个公司的独有技术,是一个文件服务器,IO能力非常好,价格非常贵
+        JBOD:Just a Bunch Of Disks
+            功能:将多块磁盘的空间合并成一个大的连续空间使用;
+            可用空间:sum(S1,S2,...)
+    常用级别:RAID-0, RAID-1, RAID-5, RAID-10, RAID-50, JBOD
+```
+```
+CentOS 6上的软件RAID的实现
+    结合内核中的md(multi devices)模块
+         md: 支持将任何块设备组织成RAID
+
+    mdadm:模式化的工具
+        命令的语法格式:mdadm [mode] <raiddevice> [options] <component-devices>
+            <raiddevice>: /dev/md#,md设备的设备文件,一般在/dev目录下,以md开头,后跟一个数字来区别
+            <component-devices>: 任意块设备,可以是整个分区或者整个磁盘
+        支持的RAID级别:LINEAR(JBOD), RAID0, RAID1, RAID4, RAID5, RAID6, RAID10等等; 
+
+        模式:
+            创建:-C,创建RAID
+            装配: -A,重新识别此前实现的RAID
+                在某OS上创建的软件RAID,被迁移到其它主机上,并启动OS之后,Linux auto detect
+            监控: -F
+            管理:-f, -r, -a
+        查看当前系统上所有已启用的软件RAID设备及其相关信息(观察md的状态): 
+            # cat /proc/mdsta
+
+        创建模式: -C,需先将块设备的分区ID调整为'fd'(Linux raid auto)
+            -n #: 使用#个块设备来创建此RAID;
+            -l #:指明要创建的RAID的级别;
+            -a {yes|no}:自动创建目标RAID设备的设备文件;
+            -c CHUNK_SIZE: 指明块大小;
+            -x #: 指明空闲盘的个数;
+            
+            例如:创建一个10G可用空间的RAID0;
+                # mdadm -C /dev/md0 -a yes -n 2 -l 0 /dev/sdb{1,2}
+            例如:创建一个10G可用空间的RAID5;
+                3*5G,6*2G:(n-1)*2G
+                # mdadm -C /dev/md1 -a yes -n 3 -l 5 -x 1 /dev/sda{3,5,6} /dev/sdb3
+                # cat /proc/mdsta
+                # mke2fs -t ext4 /dev/md1
+                # mount /dev/md1 /mydata
+                # mount
+                # df -lh
+        管理模式:
+            -f: 标记指定磁盘为损坏
+                # mdadm /dev/md1 -f /dev/sda3
+                # watch -n1 "cat /proc/mdsta"
+                # mdadm -D /dev/md1
+            -a: 添加磁盘
+                # mdadm /dev/md1 -a /dev/sda3
+            -r: 移除磁盘
+                # mdadm /dev/md1 -r /dev/sda3
+        显示指定的软RAID的详细信息:-D
+            # mdadm -D /dev/md#
+        停止md设备:-S
+            # mdadm -S /dev/md#
+        重新启用RAID:
+            # mdadm -A /dev/md# /dev/DEVICE...
+            mdadm的配置文件/etc/mdadm.conf
+```
+
+### LVM2
+    
+```
+LVM: Logical Volume Manager(逻辑卷管理器), Version: 2
+    与软RAID很类似,使用纯软件的方式组织一个或多个底层硬件设备为一个抽象的逻辑设备来使用的解决方案
+    主要作用是支持动态扩展或收缩,以及支持快照功能
+结合内核中的dm(device mapper)模块
+     dm: 将一个或多个底层块设备组织成一个逻辑设备的模块;
+原理:
+    1. 将底层硬盘设备(磁盘或者分区或者RAID)在逻辑卷的架构中创建成PV(物理卷)
+    2. 将PV中所提供的存储空间划分成大小相同的N个存储单元PE(Physical Extent,物理盘区),并将存储单元合并在一个高层上,形成一个组件VG(卷组),卷组可以有多个物理卷
+        注:PE大小是在PV加入到VG之后决定的;VG的大小也可以通过增加PV来扩展或收缩
+    3. VG有点类似于扩展分区,没办法直接格式化使用,需要再次划分成逻辑分区
+    4. 在VG的基础上再次创建多个LV(逻辑卷)组件,这才是真正意义上的逻辑卷,每一个LV都是一个独立的文件系统,可以被格式化挂载使用
+        即指定特定数量的PE来组成一个逻辑存储空间的过程,逻辑卷的大小可以动态扩展或收缩而不影响到里面原先的数据
+        一旦PE分配给逻辑卷使用,此时PE叫做LE,
+    --------------------------------
+    所以在安装红帽系列OS并选择自动创建分区时,它首先创建一个boot分区,将其他剩余的空间统统创建为一个PV,再将这个PV创建为一个VG,在VG当中创建多个LV,
+    一个LV用来当/,一个LV用来当SWAP,一个LV用来当USR,一个LV用来当VAR等等
+LV的访问路径:
+    1. /dev/mapper/VG_NAME-LV_NAME
+		/dev/mapper/vol0-root
+	2. /dev/VG_NAME/LV_NAME
+		/dev/vol0/root
+    此两者均为符号链接,指向的文件为/dev/dm-#
+```
+```
+pv管理工具:pvcreate, pvs, pvdisplay, pvremove, pvmove, pvscan
+    # pvs:显示pv的简要信息
+    # pvdisplay:显示pv的详细信息
+
+    # pvcreate /dev/DEVICE: 创建pv
+        需先将块设备的分区ID调整为'8e'(Linux LVM)
+    # pvremove
+        先做vgremove
+vg管理工具:vgcreate, vgs, vgdisplay, vgremove, vgextend, vgreduce, vgscan
+    # vgs
+    # vgdisplay
+
+    # vgcreate  [-s #[kKmMgGtTpPeE]] VolumeGroupName  PhysicalDevicePath [PhysicalDevicePath...]
+    # vgextend  VolumeGroupName  PhysicalDevicePath [PhysicalDevicePath...]
+    # vgreduce  VolumeGroupName  PhysicalDevicePath [PhysicalDevicePath...]
+        先做pvmove,将pv上的pe移动至同一个卷组当中的其他pv上去
+    # vgremove
+        先做lvremove
+lv管理工具:lvcreate, lvs, lvdisplay, lvremove, lvextend, lvreduce, lvscan, lvmconf
+    # lvs
+    # lvdisplay
+
+    # lvcreate -L #[kKmMgGtTpPeE] -n LV_NAME VolumeGroupName
+    # lvremove /dev/VG_NAME/LV_NAME
+        如果已经挂载过,需要先卸载再remove
+    
+    扩展逻辑卷:逻辑卷支持在线修改大小
+        # lvextend -L [+]#[kKmMgGtTpPeE] /dev/VG_NAME/LV_NAME
+            扩展物理边界
+            先确定扩展的目标大小;并确保对应的卷组中有足够的空闲空间可用;如原大小为2G, 目标为4G,则可写为'-L +2G'或者'-L 4G'
+        # resize2fs /dev/VG_NAME/LV_NAME
+            扩展逻辑边界
+            重新修改逻辑卷的大小,没指定大小即使用这个分区上所有的可用大小
+    缩减逻辑卷:缩减很危险!!!!,所以缩减要离线
+        # umount /dev/VG_NAME/LV_NAME
+            先卸载文件系统
+        # e2fsck -f /dev/VG_NAME/LV_NAME
+            执行强制检测并修复
+        # resize2fs /dev/VG_NAME/LV_NAME #[mMgGtT]
+            缩减逻辑边界
+            先确定缩减后的目标大小;并确保对应的目标逻辑卷大小中有足够的空间可容纳原有所有数据;
+        # lvreduce -L [-]#[kKmMgGtTpPeE] /dev/VG_NAME/LV_NAME
+            缩减物理边界
+        # mount /dev/VG_NAME/LV_NAME MOUNT_POINT
+            重新挂载
+            
+    创建快照卷:snapshot
+        工作机制:
+            快照卷刚创建时没有任何数据,只是将逻辑卷数据的元数据备份一份,将快照卷挂载后,通过快照卷也能访问原卷中的数据,所以快照卷其实是
+            原卷的另一个访问入口而已;同时立即创建逻辑卷元数据的一个监视器,随时监控着对方的元数据, 当监控到某一刻某个文件要变化
+            时,先将这个文件复制一份到快照卷上,然后原卷的数据再变化,将来通过快照卷访问数据时,没变化的仍通过原卷找文件,而发生变化的则访问
+            本卷中的数据;所以这样使得快照卷的空间体积很小,仅存储了快照创建以后原卷中发生变化的文件,没变化的仍找原卷.
+        注:快照卷是对某逻辑卷进行的,因此必须跟目标逻辑卷在同一个卷组中(类似于硬链接不能跨分区进行);无须指明卷组;
+        
+        # lvcreate -s -L #[kKmMgGtTpPeE] -n snapshot_lv_name -p r original_lv_name
+            eg:lvcreate -s -L 512M -n mylv-snap -p r /dev/myvg/mylv
+        # mount /dev/myvg/mylv-snap /mnt
+```
+
+### 程序包管理
+
+```
+API:Application Programming Interface
+    POSIX:Portable(可移植) OS
+    
+    程序源代码(C, C++, perl等) --> 预处理 --> 编译(gcc) --> 汇编(将目标代码转换成二进制指令的过程) --> 链接 --> 执行
+        动态(共享)编译:程序研发时调用了库函数,程序单独编译完后,明确指明库的调用入口(例如/lib或/lib64下的.so文件),程序要运行必要要把库装在进内存
+            能够大大节约内存资源
+        静态编译:程序在编译时直接把要调用的库复制到程序内部来,程序体积比动态编译体积大
+            程序挪到任何系统上都能运行,缺点是对内存和体积都不利
+ABI:Application Binary Interface
+    Windows与Linux不兼容,但可以使用库级别的虚拟化让二者兼容起来.
+    库级别的虚拟化:能够使Windows系统上的应用程序(exe)运行在Linux系统上(elf),反之亦然.
+        Linux: WINE(能够虚拟windows运行环境)
+        Windows: Cywin(能够虚拟linux运行环境)
+虽然通过库级别的虚拟化技术能使程序在多平台上运行,但库可能是个小众产品,其次稳定性还有待考证,因此并不建议这样使用;但很多时候应用程序在一次编译以后
+期望能在各种平台上运行,可以提供更高级别的应用级别接口,例如JAVA的JVM. 
+    这样用JAVA语言写的程序就不用直接跑在系统调用/库调用之上,只要跑在JVM之上就能执行.
+因此应用程序的开发可分为:
+    系统级开发:面对系统调用/库调用来实现,linux内核是由99%的c和1%的汇编写成的
+        C,C++,
+    应用级开发:面对特定应用程序自己专有的开发环境来实现
+        Java,Python,Ruby,Php,Perl
+```
+```
+linux应用程序的组成部分:二进制程序、库文件、配置文件、帮助文件
+	二进制程序:可执行文件,一个应用程序可有多个二进制程序
+		/bin,/sbin,/usr/bin,/usr/sbin,/usr/local/bin,/usr/local/sbin
+	库文件:可执行文件,不能独立执行,只能被能独立运行的程序调用时执行,一般有2类,一类是多个程序之间的共享库,一类是自己能够被其他人做二次开发时调用的接口
+		/lib,/lib64,/usr/lib,/usr/lib64,/usr/local/lib,/usr/local/lib64
+	配置文件:可被查看其内容的文件
+		/etc,/etc/DIRECTORY,/usr/local/etc
+	帮助文件:可被查看其内容的文件
+		/usr/share/man,/usr/share/doc,/usr/local/share/man,/usr/local/share/doc
+	--------------------	
+    查看二进制程序所依赖的库文件:
+        # ldd /PATH/TO/BINARY_FILE
+    管理及查看本机装载的库文件:
+        # ldconfig 
+            /sbin/ldconfig -p: 显示本机已经缓存的所有可用库文件名及文件路径映射关系;
+        配置文件为:/etc/ld.so.conf, /etc/ld.so.conf.d/*.conf
+        缓存文件:/etc/ld.so.cache
+程序包管理器:
+    将编译好的应用程序的各组成文件(包括二进制程序,库文件,配置文件,帮助文件)打包成一个或几个程序包文件,从而方便快捷地实现程序包的安装、卸载、查询、升级和校验等管理操作.
+    不同的发行版所用的包管理器是不一样的.
+    --------------------
+    1、程序的组成清单 (每个包独有)
+        文件清单
+        安装或卸载时运行的脚本
+    2、数据库(公共)
+        程序包名称及版本
+        依赖关系
+        功能性说明
+        安装生成的各文件的文件路径及校验码信息
+    --------------------
+    debian,ubuntu:
+        包管理器:dpt
+            dpkg-deb/apt-get:deb包管理器前端工具
+        包格式:.deb
+    rhel,fedora,centos,S.u.S.e:
+        包管理器:rpm(Redhat Package Manager),RPM is Package Manager
+            yum:rpm包管理器的前端工具(补充和丰富了rpm的功能,而不是取代rpm的)
+            zypper: suse上的rpm包管理器的前端管理工具
+            dnf: Fedora 22+上的rpm包管理器的前端管理工具
+        包格式:.rpm
+```
+- `rpm包的简介`
+    ```
+    源代码:
+        name-VERSION.tar.{gz,bz2,xz}
+            VERSION: major.minor.release
+    rpm包命名方式:
+        name-VERSION-release.arch.rpm
+            VERSION: major.minor.release,同源代码
+            release:rpm包自身的发行号,与程序源码的发行号无关,仅用于标识对rpm包不同制作的修订;同时,release还包含此包适用的OS
+                OS例如centos5,el7(RHEL7)等等
+            arch:适用于的硬件平台
+                x86: i386, i486, i586, i686等;
+                x86_64: x64, x86_64, amd64
+                powerpc: ppc
+                noarch: 跟平台无关,依赖于虚拟机
+                
+             例如:
+                bash-4.2.3-3.centos5.x86_64.rpm
+                zlib-1.2.7-13.el7.i686.rpm
+        一个程序有20个功能:常用功能有8个,特殊A:3个,特殊B:6个,二次开发相关功能:3
+            分包机制:拆包
+                核心包,主包:命名与源程序一致
+                    bash-4.2.3-3.centos7.x86_64.rpm
+                子包,支包:
+                    bash-a-4.2.3-3.centos7.x86_64.rpm
+                    bash-b-4.2.3-3.centos7.x86_64.rpm
+                    bash-devel-4.2.3-3.centos7.x86_64.rpm
+        包之间:存在依赖关系
+            X, Y, Z
+    获取rpm程序包的途径:
+        (1) 系统发行版的光盘或官方服务器(例如CentOS镜像站点等);
+        (2) 项目官方站点
+        (3) 第三方组织:很多第三方机构或个人制作并公开发布许多rpm包
+            可靠的途径:来源合法性及完整性可以保证
+                Fedora-EPEL
+            搜索引擎:尽量不要使用,来源合法性及完整性难以保证
+                http://pkgs.org
+                http://rpmfind.net
+                http://rpm.pbone.net
+        (4) 自己制作
+    rpm包来源合法性验正及完整性验正:
+        完整性验正:SHA256(单向加密)
+        来源合法性验正:RSA(公钥加密)
+        --------------------
+        包的制作者会在包制作完成后,使用单向加密算法计算并提取原始数据的特征码,而后使用自己的私钥加密这段特征码,最后附加在原始数据后面(数字签名)。
+        验正过程:
+            前提:必须有可靠机制获取到包制作者的公钥;
+            1、使用制作者的公钥解密加密的特征码,能解密则意味着来源合法;
+            2、使用与制作者同样的意向加密算法提取原始数据的特征码,并与解密出来的特征码作比对,相同,则意味着完整性没问题;
+        
+        具体做法之一:
+            首先在当前系统上导入包的制作者的公钥:
+                rpm --import /PATH/FROM/GPG-PUBKEY-FILE
+                
+                显示所有已经导入的gpg格式的公钥:# rpm -qa gpg-pubkey*
+                显示密钥的详细信息:# rpm -qi gpg-pubkey-NAME
+            自动检查包:
+                安装过程中会自动执行
+            手动检查包:
+                rpm -K /path/to/package_file
+                rpm --checksig /path/to/package_file
+                    不检查包完整性:
+                        rpm -K --nodigest
+                    不检查来源合法性:
+                        rpm -K --nosignature
+ 
+            Tips:CentOS 7发行版光盘提供的密钥文件是`RPM-GPG-KEY-CentOS-7`
+    管理rpm程序包的方式:
+        使用包管理器:rpm
+        使用前端工具:yum, dnf
+    ```
+- `rpm命令的使用`
+    ```
+    CentOS系统上rpm命令管理程序包:
+        安装、升级、查询、卸载、校验、数据库维护(重建)
+    ---------------------------
+    安装:
+        rpm {-i|--install} [install-options] PACKAGE_FILE ...
+            -v: verbose
+            -vv: 
+            -h: 以#显示程序包管理执行进度;每个#表示2%的进度
+ 
+            常用组合选项:-ivh
+
+            [install-options]
+                --test: 测试安装,但不真正执行安装过程;dry run模式;
+                --nodeps:忽略依赖关系安装;能安装上,但有可能无法运行;
+                --replacepkgs: 重新安装;如果原有配置文件作了修改,很有可能不执行替换,而是将应该安装生成的配置文件重命名为.rpmnew;
+
+                --nosignature: 不检查来源合法性;
+                --nodigest:不检查包完整性;
+
+                --noscipts:不执行程序包脚本片断;
+                    %pre: 安装前脚本; --nopre
+                    %post: 安装后脚本; --nopost
+                    %preun: 卸载前脚本; --nopreun
+                    %postun: 卸载后脚本;  --nopostun
+    升级:新版本替换老版本
+        rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...
+        rpm {-F|--freshen} [install-options] PACKAGE_FILE ...
+            upgrage:安装有旧版程序包,则“升级”;如果不存在旧版程序包,则“安装”;
+            freeshen:安装有旧版程序包,则“升级”;如果不存在旧版程序包,则不执行升级操作;
+ 
+            常用组合选项:
+                1、升级或安装:-Uvh
+                2、纯升级:-Fvh
+
+            [install-options]
+                --oldpackage:降级;
+                --force: 强制升级;
+        注意:
+            (1) 不要对内核做升级操作,很有可能系统启动不了;Linux支持多内核版本并存,因此,直接安装新版本内核即可;
+            (2) 如果原程序包的配置文件安装后曾被修改,升级时,新版本的提供的同一个配置文件并不会直接覆盖老版本的配置文件,而把新版本的文件重命名(FILENAME.rpmnew)后保留;
+    查询:基于数据库的
+        rpm {-q|--query} [select-options] [query-options]
+            查询某包是否安装:# rpm -q package_name...
+            [select-options]
+                -a: 查询所有已经安装的包,可配合grep进行条件过滤
+                -f /path/to/some_file: 查看指定的文件由哪个程序包安装生成
+                -p /PATH/TO/PACKAGE_FILE:针对尚未安装的程序包文件做查询操作
+     
+                --whatprovides CAPABILITY:查询指定的CAPABILITY(功能)由哪个包所提供
+                --whatrequires CAPABILITY:查询指定的CAPABILITY(功能)被哪个包所依赖
+            [query-options]
+                --changelog package_name:查询rpm包制作的changlog
+                -c package_name: 查询某包安装生成了哪些配置文件
+                -d package_name: 查询某包安装生成了哪些帮助文件
+                -i package_name: information,查询包的描述信息
+                -l package_name: 查询某包安装生成了哪些文件;
+                --scripts package_name:查询程序包自带的脚本片断
+                    preinstall:安装前脚本
+                    postinstall: 安装后脚本
+                    preuninstall: 卸载前脚本
+                    postuninstall: 卸载后脚本
+                -R: 查询指定的程序包所依赖的CAPABILITY;
+                --provides: 列出指定程序包所提供的CAPABILITY;
+                
+            常用组合选项:
+                -qi PACKAGE, -qf FILE, -qc PACKAGE, -ql PACKAGE, -qd PACKAGE
+                -qpi PACKAGE_FILE, -qpl PACKAGE_FILE, ...
+                -qa
+    卸载:
+        rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--notriggers] [--test] PACKAGE_NAME ...
+            --nodeps:忽略依赖关系卸载;能卸载,但依赖于此包的程序包可能会运行不正常;
+        注意:
+            如果包的配置文件安装后曾被改动过,卸载时,此文件将不会卸载,而是被重命名并保留,例如warning: /etc/zprofile saved as /etc/zprofile.rpmsave
+    校验:用于检查包安装生成的文件属性是否发生变化
+        rpm {-V|--verify} [select-options] [verify-options]
+           S file Size differs
+           M Mode differs (includes permissions and file type)
+           5 digest (formerly MD5 sum) differs
+           D Device major/minor number mismatch
+           L readLink(2) path mismatch
+           U User ownership differs
+           G Group ownership differs
+           T mTime differs
+           P caPabilities differ
+        注意:
+            某属性无变化,显示为.
+    数据库重建:
+        数据库目录:/var/lib/rpm
+
+        rpm {--initdb|--rebuilddb}
+            initdb: 初始化
+                如果事先不存在数据库,则新建之;否则,则不新建,即不执行任何操作;
+            rebuilddb:重建
+                无论当前存在与否,直接重新创建数据库来覆盖原有的数据库;
+    ```
+- `yum命令的使用`
+    ```
+    why:
+        rpm包管理器在实现程序管理时会有一些问题,比如必须手动解决依赖关系,非常麻烦,虽然在安装时可以忽略依赖关系,但在使用时可能存在问题.
+        所以需要有高于rpm或者deb这种本身底层的管理器,能实现在前端自动解决依赖关系,来完成程序的安装,解决用户的后顾之忧.所以yum等工具出现了.
+        但yum虽然解决了依赖关系,但它的工作机制和设计体系是有一定问题的,比如安装过程当中半道终止的话,下次再安装时将会无法解决,它无法分析上次是否安装成功与否.
+        因此dnf的出现主要是为了解决yum所面临的这个问题的.
+    what:
+        yum,全称Yellow dog Updater, Modified
+        是一个基于RPM包管理的前端包管理器(工具),能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包.
+        它是由Yellow dog研发的,并非是取代rpm的,必须依赖于rpm才能存在的.
+    ---------------------------
+    yum工作机制:yum自身并非cs架构,而是yum所依赖的这种文件访问机制是cs架构的.
+        1.当用户使用yum命令要去安装一个程序包时,即yum客户端接受到安装程序包的指令,
+        2.首先会尝试着根据yum配置文件去找指定的远程仓库,以获取仓库的元数据信息,并缓存至本地/var/cache/yum,
+        3.yum客户端程序在本地分析元数据文件,并结合本地系统环境(已安装的包)做出要安装的程序包的决策(依赖关系等),
+        4.根据决策联系Yum仓库,下载各程序包缓存于本地后,一并进行类似于rpm命令的安装操作.
+        5.yum安装完成以后,会自动删除程序包缓存以节约空间,元数据文件一般会存在本地,下次安装时会先对比此文件本地与仓库的校验码,相同则不更新,不同则更新,以节约网络带宽.
+    yum仓库:rpm包的文件服务器
+        yum仓库的组成:
+            1.各个rpm包;
+            2.元数据文件(包名、版本信息、各包所包含的文件列表、依赖关系、包分组信息),放置于特定目录(repodata)下.
+                centos5: xml, centos6,7: sqlite
+                createrepo: 制作yum仓库元数据的工具
+        yum仓库的协议:repodata目录所在父目录就是一个可用仓库
+            ftp     ftp://server/path/to/repository
+            http    http://server/path/to/repository
+            nfs 	nfs://server/nfs_path
+            file    file:///path/to/repository
+        使用Centos镜像光盘搭建本地yum源(仓库):
+            (1) 将默认Yum源备份(可选)
+                # mkdir /opt/centos-yum.bak
+                # mv /etc/yum.repos.d/* /opt/centos-yum.bak/
+            (2) 在虚拟机上挂载CentOS镜像文件至某目录,例如/media/cdrom
+                # mount -r -t iso9660 /dev/cdrom /media/cdrom
+            (3) 编写repo文件并指向镜像的挂载目录
+                # vim /etc/yum.repos.d/local.repo
+                [local]
+                name=local
+                baseurl=file:///media/cdrom
+                gpgcheck=0
+                enabled=1
+            (4) 清除本地缓存
+                # yum clean all
+            (5) 虽然本地yum源安装软件速度快,但可能有些包没有,所以添加aliyun,163等yum源用作第二考虑yum源
+                # cat /etc/redhat-release
+                # wget -O /etc/yum/repos.d/CentOS{5,6,7}-Base-aliyun.repo http://mirrors.aliyun.com/repo/Centos-{5,6,7}.repo
+                # wget -O /etc/yum/repos.d/CentOS{5,6,7}-Base-163.repo http://mirrors.163.com/.help/CentOS{5,6,7}-Base-163.repo
+            (6) 修改Yum源的优先级(当既有本地源又有163,aliyun等源时,希望先用本地源去安装,本地找不到可用的包再使用163,aliyun等源去安装软件)
+                (1) 查看系统是否安装了优先级的插件
+                    # rpm -qa | grep "yum-plugin-"
+                        看看有没有yum-plugin-priorities.noarch插件
+                    # yum search yum-plugin-priorities
+                        用search查看是否有此插件可用
+                (2) 安装yum-plugin-priorities.noarch插件
+                    # yum -y install yum-plugin-priorities.noarch
+                (3) 查看插件是否启用
+                    # cat /etc/yum/pluginconf.d/priorities.conf
+                        1为启用,0为禁用
+                (4) 修改本地Yum源优先使用
+                    # vim /etc/yum.repos.d/local.repo
+                        在原基础上加入priority=1,数字越小优先级越高
+                        可以继续修改其他源的priority值,经测试仅配置本地源的优先级为priority=1就会优先使用本地源了
+        自建yum源:
+            (1) 安装httpd程序,并启动服务,并设置开机自启
+                # yum install httpd
+                # service httpd start
+                # chkconfig httpd on
+            (2) httpd的文档根目录为/var/www/html,创建子目录,存放某相关的所有rpm包
+            (3) 为仓库生成元数据文件,以使能够作为仓库使用
+                # yum install createrepo
+                # createrepo /path/to/rpm_repo/
+            (4) 配置yum客户端使用此仓库即可
+    yum客户端:
+        配置文件: 
+            /etc/yum.conf:主配置文件(中心配置文件),为所有仓库提供公共配置
+                可使用whatis/man yum.conf查看帮助手册
+            /etc/yum.repos.d/*.repo:一个或几个相关仓库的配置信息可保存为一个文件,文件名都以.repo结尾,为仓库的指向提供配置
+        仓库指向的定义:
+            [repositoryID]
+            name=Some name for this repository
+            baseurl=url://path/to/repository/
+            enabled={1|0}
+            gpgcheck={1|0}
+            gpgkey=URL
+            enablegroups={1|0}
+            mirrorlist=URL to a file
+                mirrorlist  Specifies a URL to a file containing a list of baseurls
+            failovermethod={roundrobin|priority}
+                默认为:roundrobin,意为随机挑选;
+            cost={1..n}
+                默认为1000,指定访问此仓库的开销
+        yum的repo配置文件中可用的变量:
+            $releasever: 程序的版本,对Yum而言指的是redhat-release版本;只替换当前OS的发行版的主版本号; 
+            $arch: 系统架构(平台)
+            $basearch: 系统基本架构(平台),如i686,i586等的基本架构为i386;
+            $YUM0-9: 在系统中定义的环境变量,可以在yum中使用;
+    ```
+    ```
+    yum客户端命令的使用:
+        yum [options] [command] [package ...]
+    ---------------------------
+    yum的options选项:
+        --nogpgcheck:禁止进行gpg check;
+        -y: 自动回答为“yes”;
+        -q:静默模式;
+        --disablerepo=repoidglob:临时禁用此处指定的repo;
+        --enablerepo=repoidglob:临时启用此处指定的repo;
+        --noplugins:禁用所有插件;
+    ---------------------------
+    1、列出所有可用repo列表
+        yum repolist {enabled|disabled|all}
+    2、列出rpm包(可配合less查看)
+        yum list {all|installed|available}
+        yum list KEYWORD*
+    3、查询指定的特性(可以是某文件)是由哪个程序包安装生成的
+        yum provides|whatprovides /path/to/somefile
+    4、清理本地缓存
+        yum clean {all|packages|metadata|expire-cache|rpmdb|plugins}
+    5、安装程序包
+        yum install package_name [package_name...]
+            如果从其它处获得一个rpm包,且此包依赖于其它包(在仓库中),也可以使用'yum install /path/to/packe_file'来安装本地程序包
+        yum reinstall package_name [package_name...]   (重新/覆盖安装)
+    6、升级程序包
+        yum check-update: 检查可用的升级包
+        yum update package_name
+        yum downgrade package_name  (降级)
+    7、查看程序包的描述信息
+        yum info package_name
+    8、卸载程序包
+        yum remove|erase package_name
+    9、以指定的关键字搜索程序包名及summary信息
+        yum search string1 [string2] [...]
+    10、查看指定包所依赖的capabilities:
+        yum deplist package1 [package2] [...]
+    11、查看yum事务历史(yum每一次的安装/更新操作都会开启yum事务)
+        yum	history [info|list|packages-list|packages-info|summary|addon-info|redo|undo|rollback|new|sync|stats]
+    12、包组管理的相关命令
+        yum grouplist
+        yum groupinfo "GROUP NAME"
+        yum groupinstall "GROUP NAME"
+        yum groupupdate "GROUP NAME"
+        yum groupremove "GROUP NAME"
+    ```
+- `源程序包编译安装`
+    ```
+    源代码组织格式:
+        多文件:文件中的代码之间,很可能存在跨文件依赖关系;
+
+        C、C++:make (configure --> Makefile.in(makefile文件的模板) --> makefile)
+        java:maven
+     开源程序源代码的获取:
+        官方自建站点:
+            apache.org (ASF)
+            mariadb.org
+            ...
+        代码托管:
+            SourceForge
+            Github.com
+            code.google.com
+    C代码编译安装三步骤:
+        建议:安装前查看INSTALL,README
+        前提:提供开发工具及开发环境
+            开发工具:make(项目管理工具), gcc(gnu c complier,编译工具)等
+                autoconf: 生成configure脚本,即生成编译环境检查及编译功能配置脚本
+                automake:生成Makefile.in模板文件
+            开发环境:开发库,头文件
+                glibc:标准库
+            -------------------------    
+            通过“包组”提供开发组件
+                CentOS 6: "Development Tools", "Server Platform Development",
+        (1) ./configure脚本:
+            (1) 通过选项传递参数,指定编译特性(启用特性、安装路径等);执行时会参考用户的指定以及Makefile.in文件生成makefile;
+            (2) 检查依赖到的外部环境;
+            -------------------------
+            ./configure脚本的使用:
+                1、获取其支持使用的选项
+                    ./configure --help
+                2、较通用的一些选项
+                    安装路径相关:
+                        --prefix=/path/to/somewhere: 指定默认安装位置;默认为/usr/local/
+                        --sysconfdir=/path/to/somewhere: 指定配置文件安装路径
+                    指定启用/禁用的特性:
+                        --enable-FEATURE: 例如--enable-fpm
+                        --disable-FEATURE: 例如--disable-socket
+                    指定所依赖的功能、程序或文件:
+                        --with-FUNCTION[=/path/to/somewhere]
+                        --without-FUNCTION
+                        --with-PACKAGE[=ARG]
+                        --without-PACKAGE
+        (2) make:
+            根据makefile文件并调用相应的编译器来构建应用程序;
+        (3) make install:调用install命令来复制文件到指定位置当中去
+    安装后的配置:
+        程序运行:
+            (1) 导出二进制程序目录至PATH环境变量中,(让二进制程序直接运行,而无须输入路径)
+                编辑文件/etc/profile.d/NAME.sh
+                    export PATH=/PATH/TO/BIN:$PATH
+            (2) 导出帮助手册
+                编辑/etc/man.config文件
+                    添加一个MANPATH,路径为新安装的程序的man目录
+        程序开发:如果其它应用程序依赖此程序的开发环境,或针对此程序做二次开发
+            (1) 导出库文件路径
+                编辑/etc/ld.so.conf.d/NAME.conf,指定让系统搜索定制的路径
+                    添加新的库文件所在目录至此文件中;
+                触发系统重新搜索所有的库文件并生成缓存
+                    ldconfig [-v]
+            (2) 导出头文件
+                系统找头文件的路径是:/usr/include
+                基于链接的方式实现:
+                    ln -sv /usr/local/nginx/include /usr/include/nginx
+    ```
+
+## 参考链接
+
+## 结束语
+
+- 未完待续...

+ 58 - 0
source/_posts/te-db-backup.md

@@ -0,0 +1,58 @@
+---
+title: Mysql 数据库自动备份脚本
+date: 2019-03-09 15:23:53
+categories:
+- 经典示例
+tags:
+- linux
+---
+
+# Mysql 数据库自动备份脚本
+
+## 目录
+
+- [简介](#简介)
+- [正篇](#正篇)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介
+
+线上环境对 mysql 数据库的备份.
+
+## 正篇
+
+1. 将如下内容保存为 sh 文件,并保存至相关目录,例如:mysql-backup.sh
+    ```
+    #!/bin/bash
+    # Mysql 数据库自动备份脚本
+
+    # 数据库认证
+    host=localhost
+    username=root
+    password=123456
+    db_name=test
+    # 备份路径
+    backup_dir=/data/backup/mysql
+    # 日期格式
+    date=$(date +"%Y%m%d")
+    # Dump数据库到SQL文件
+    mysqldump -h$host -u$username -p$password $db_name > $backup_dir/$db_name-$date.sql
+    #写创建备份日志
+    echo "create $backup_dir/$db_name-$date.sql" >> $backup_dir/log.txt
+     
+    # 备份清理
+    # 删除5天之前的就备份文件
+    find $backup_dir/* -mtime +5 -exec rm {} \;
+    ```
+2. 通过 `crontab -e` 命令打开定时任务配置文件,添加如下代码,即可实现每天定时备份 mysql 数据库
+    ```
+    # 每天的23点50分执行备份
+    50 23 * * * /data/backup/mysql-backup.sh
+    ```
+
+## 参考链接
+
+## 结束语
+
+- 未完待续...

+ 67 - 0
source/_posts/te-script-powerboot.md

@@ -0,0 +1,67 @@
+---
+title: CentOS7 添加开机启动服务/脚本
+date: 2019-03-09 15:27:42
+categories:
+- 经典示例
+tags:
+- linux
+---
+
+ CentOS7 添加开机启动服务/脚本
+
+## 目录
+
+- [简介](#简介)
+- [正篇](#正篇)
+- [参考链接](#参考链接)
+- [结束语](#结束语)
+
+## 简介
+
+线上环境对服务/脚本的自启动设置.
+
+## 正篇
+
+- `添加开机自启服务`
+    ```
+    在CentOS 7中添加开机自启服务非常方便,只需要两条命令(以Jenkins为例):
+        systemctl enable/disable jenkins.service #设置jenkins服务为自启动服务
+        systemctl start/restart/stop/status jenkins.service #启动jenkins服务
+    兼容CentOS 6:
+        service network start/restart/stop/status
+        chkconfig network on/off
+        chkconfig --list
+    ```
+
+- `添加开机自启脚本`
+    ```
+    在centos7中增加脚本有两种常用的方法,以脚本autostart.sh为例:
+        #!/bin/bash
+        #description:开机自启脚本
+        /usr/local/tomcat/bin/startup.sh  #启动tomcat
+     -------------------   
+    方法一:
+        1、赋予脚本可执行权限(/opt/script/autostart.sh是你的脚本路径)
+            chmod +x /opt/script/autostart.sh
+        2、打开/etc/rc.d/rc.local或/etc/rc.local文件,在末尾增加如下内容
+            su - user -c '/opt/script/autostart.sh'
+        3、在centos7中,/etc/rc.d/rc.local的权限被降低了,所以需要执行如下命令赋予其可执行权限
+            chmod +x /etc/rc.d/rc.local
+    方法二:
+        1、将脚本移动到/etc/rc.d/init.d或/etc/init.d目录下
+            mv /opt/script/autostart.sh /etc/rc.d/init.d
+        2、增加脚本的可执行权限
+            chmod +x  /etc/rc.d/init.d/autostart.sh
+        3、添加脚本到开机自动启动项目中
+            cd /etc/rc.d/init.d
+            chkconfig --add autostart.sh
+            chkconfig autostart.sh on
+    ```
+
+## 参考链接
+
+<https://blog.csdn.net/wang123459/article/details/79063703?utm_source=copy>
+
+## 结束语
+
+- 未完待续...