基于spring boot与spring cloud的分布式微服务网站开发的学习总结

SSL

DOCKER

爬虫

单点登录

Wrapper

SpringCloud

rpc

IO

  • BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里使用那个经典的烧开水例子,这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

  • NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

  • AIO ( Asynchronous I/O):异步非阻塞I/O模型。异步非阻塞与同步非阻塞的区别在哪里?异步非阻塞无需一个线程去轮询所有IO操作的状态改变,在相应的状态改变后,系统会通知对应的线程来处理。对应到烧开水中就是,为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。

  • 同步和异步

    同步就是烧开水,需要自己去轮询(每隔一段时间去看看水开了没),异步就是水开了,然后水壶会通知你水已经开了,你可以回来处理这些开水了。

  • 阻塞和非阻塞

    阻塞就是说在煮水的过程中,你不可以去干其他的事情,非阻塞就是在同样的情况下,可以同时去干其他的事情。阻塞和非阻塞是相对于线程是否被阻塞。

NIO

NIO并不是Java独有的概念,NIO代表的一个词汇叫着IO多路复用。由操作系统提供的系统调用,早期这个操作系统调用的名字是select,演化成了Linux下的epoll和Mac里的kqueue,Netty就是基于Java NIO技术封装的一套框架。

NIO的全称是NoneBlocking IO,非阻塞IO,区别与BIO,BIO的全称是Blocking IO,阻塞IO。那这个阻塞是什么意思呢?

  1. Accept是阻塞的,只有新连接来了,Accept才会返回,主线程才能继

  2. Read是阻塞的,只有请求消息来了,Read才能返回,子线程才能继续处理

  3. Write是阻塞的,只有客户端把消息收了,Write才能返回,子线程才能继续读取下一个请求

  • nio事件机制伪代码

while true {
    events = takeEvents(fds)  // 获取事件,如果没有事件,线程就休眠
    for event in events {
        if event.isAcceptable {
            doAccept() // 新链接来了
        } elif event.isReadable {
            request = doRead() // 读消息
            if request.isComplete() {
                doProcess()
            }
        } elif event.isWriteable {
            doWrite()  // 写消息
        }
    }
}

Netty

通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能

  • 并发高,基于NIO

  • 传输快

  • 封装好

RabbitMQ

手动应答

将autoAck设置为false,调用channel.basicAck(envelope.getDeliveryTag(), false);来告诉消息服务器删除消息

deliveryTag(唯一标识 ID):当一个消费者向 RabbitMQ 注册后,会建立起一个 Channel ,RabbitMQ 会用 basic.deliver 方法向消费者推送消息,这个方法携带了一个 delivery tag, 它代表了 RabbitMQ 向该 Channel 投递的这条消息的唯一标识 ID,是一个单调递增的正整数,delivery tag 的范围仅限于 Channel

multiple:为了减少网络流量,手动确认可以被批处理,当该参数为 true 时,则可以一次性确认 delivery_tag 小于等于传入值的所有消息

Consumer raised exception, processing can restart if the connection factory

eureka配置

@EnableEurekaServer

@EnableEurekaClient @EnableDiscoveryClient

心跳机制,隔一段时间打印日志

负载均衡策略:ribbon默认使用轮询,微服务会被轮流调用

//eureka端,关闭自我保护,30秒主动失效
enable-self-preservation:false
eviction-interval-timer-in-ms: 30000 清理
//服务端,
lease-renewal-interval-in-seconds: 30//租期更新时间间隔(默认30秒)
lease-expiration-duration-in-seconds: 60//租期到期时间(默认90秒)
日志会打印Closing connections idle longer than 30000 SECONDS

zuul配置

token,前端计算,发送。后端接收,计算,比较。防止篡改。

路由网关让所有的微服务对外只有一个接口,只需访问一个网关地址,由网关将所有的请求代理到不同的服务中。自动路由映射到在Eureka Server上注册的服务。

@EnableZuulProxy启用路由代理。

http://localhost:8721/open/mosservice/mos/operationLog/exportOperationLog?operatorId=1&operatorName=&desc=&startTime=&endTime= 通过网关调用接口

生成requestId,存放到header中,服务调用接口时再从header中取,并且通过slf4j的mdc记录日志。

NGINX

由于防火墙的原因,我们并不能直接访问谷歌,那么我们可以借助VPN来实现,这就是一个简单的正向代理的例子。这里你能够发现,正向代理“代理”的是客户端,而且客户端是知道目标的,而目标是不知道客户端是通过VPN访问的。

安全地传输信息

JVM虚拟机

  • Xss规定了每个线程堆栈的大小。一般情况下256K是足够了。影响了此进程中并发线程数大小。

  • Xms初始的Heap的大小。

  • Xmx最大Heap的大小。

在很多情况下,-Xms和-Xmx设置成一样的。这么设置,是因为当Heap不够用时,会发生内存抖动,影响程序运行稳定性。

数据库

ALTER TABLE your_table_name alter COLUMN your_column_name type character varying(3000);

名字描述
character varying(n), varchar(n)变长,有长度限制
character(n), char(n)定长,不足补空白
text变长,无长度限制

左连接:左边有的,右边没有的为null

右连接:左边没有的,右边有的为null

内连接:显示左边右边共有的

${dto.sort} :无引号,#{dto.content} :带引号

LIKE CONCAT('%',#{dto.content},'%') :LIKE '%/_%'

Druid连接池

DRUID是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池

@Mapper
@Results(id = RESULT_MAPPING, value =
@ResultMap(RESULT_MAPPING)

一般情况下,Select Count (*)和Select Count(1)两着返回结果是一样的

MyISAM和InnoDB两者的应用场景:

1) MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。 2) InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。

HTTP

HttpGet方法提交的数据大小长度并没有限制,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览 器及服务器对它的限制。 如:IE对URL长度的限制是2083字节(2K+35)。

HTTP服务器之所以称为HTTP服务器,是因为编码解码协议是HTTP协议,如果协议是Redis协议,那它就成了Redis服务器,如果协议是WebSocket,那它就成了WebSocket服务器,等等。

Cookie

浏览器创建

Session

服务器创建

编程

  • 如果你需要运行java程序,只需安装JRE就可以了。如果你需要编写java程序,需要安装JDK。jre是为运行而生,jdk是为开发而生。

  • 函数用void类型声明代表不需要返回值。但是,有时候需要在函数内部强行终止函数继续运行下面的语句。这时用return语句。

  • 速度上是不会有区别的但是不会影响其他的接口查询速度如果连接池用完了,就对其他接口有影响了

判断奇数

public boolean isOdd(int i) {
    return (i & 1) == 1;
}

 

单例模式,就不能在外部来创建类对象,而是通过一个方法在类本身来创建

OrderEnum.valueOf(order.toUpperCase()) :

根据名字来获取枚举对象,如果根据名字找不到,会抛出异常,所以这个方法catch了一下,因为这个异常没必要抛到上层

try catch finally 用法

不管 try是否跑出异常,finally一定会执行的,因此 finally一定会打印,其次 在try中跑出异常,然后向上级汇报,当然汇报之前,会执行finally操作

  • 不管有没有出现异常,finally块中代码都会执行;

  • 当try和catch中有return时,finally仍然会执行;

  • finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,不管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;

  • finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

System.out.printf,(println ,print)有什么区别

  • printf可以按照格式输出

  • println可以在输出后回车换行

  • print就是单纯的输出

反斜杠\:用来转义,

1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串); 2)replaceAll的参数是regex,即基于规则表达式的替换,比如,可以通过replaceAll("\d", "*")把一个字符串所有的数字字符都换成星号;

false:

void inc(int num) {
    int num = 2; //error: variable 'num' is already defined in the scope
    if (num > 0) {
        int num = 3; //error: variable 'num' is already defined in the scope
    }
    System.out.println ("num: " + num);
}

true:

public class Shadow {
    int val;
​
    public Shadow(int val) {
        this.val = val;
    }
}

upcasting

  1. 把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。如Father father = new Son();

  2. 把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型,要向下转型,必须先向上转型为了安全可以用instanceof判断。如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son=(Son)father;其中father前面的(Son)必须添加,进行强制转换。

  3. upcasting 会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效,向上转型只能引用父类对象的属性,要引用子类对象属性,则要写getter函数。

  4. 向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。

for(;;)和while(true)的区别

| 编译前 | 编译后 | | ------------ | -------------------------------------------------- | | while (1); | mov eax,1 test eax,eax je foo+23h jmp foo+18h | | for (;;); | jmp foo+23h |

一目了然,for (;;)指令少,不占用寄存器,而且没有判断跳转,比while (1)好。也就是说两者在在宏观上完全一样的逻辑,但是底层完全不一样,for相对于来说更加简洁明了。

异常

java.io.IOException:文件名、目录名或卷标语法不正确。

java.util.zip.ZipException: invalid stored block lengths

org.springframework.beans.factory.NoSuchBeanDefinitionException:java.util.concurrent.ScheduledExecutorService,java.util.concurrent.ScheduledExecutorService

com.rabbitmq.client.ShutdownSignalException:yml中的签收模式失效,被注解注入的SimpleRabbitListenerContainerFactory覆盖,而它默认使用了自动签收。但是消费消息的时候又手动进行channel.basicAck(deliveryTag, false),于是导致了两次ack,所以报错。 解决方法是在rabbitmq的factory中指定ack模式。

注解

java中元注解有四个:  @Retention @Target @Document @Inherited

@Retention:注解的保留位置         

@Retention(RetentionPolicy.SOURCE)//注解仅存在于源码中,在class字节码文件中不包含@Retention(RetentionPolicy.CLASS)//默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得@Retention(RetentionPolicy.RUNTIME)//注解会在class字节码文件中存在,在运行时可以通过反射获取到

@Target:注解的作用目标

@Target(ElementType.TYPE)//接口、类、枚举、注解 @Target(ElementType.FIELD)//字段、枚举的常量 @Target(ElementType.METHOD) /方法 @Target(ElementType.PARAMETER)//方法参数 @Target(ElementType.CONSTRUCTOR) //构造函数 @Target(ElementType.LOCAL_VARIABLE)//局部变量 @Target(ElementType.ANNOTATION_TYPE)//注解 @Target(ElementType.PACKAGE)///包   

@Document:说明该注解将被包含在javadoc中,生成api帮助文档

@Inherited:说明子类可以继承父类中的该注解

@Scheduled cron表达式

@PropertySource(name = "bootstrap.yml", value = {"classpath:bootstrap.yml"}, ignoreResourceNotFound = false, encoding = "UTF-8")

 

Spring

如果使用 Spring,尽量使用面向接口编程,才能发挥 Spring IOC 作用,不用关心具体实现对象的生命周期, 好处是使用方便和内存占用优化。 大项复杂的项目需要,及一个接口后面可能对应着多个不同的实现。 多人分层合作,有人负责 Controller 层,有人负责 Service 层,有人负责 DAO 层,大家可以先定义好接口然后就 开始各写各的代码了,互不影响。 控制暴露给外部的内容。接口只会定义公开的部分,而如果直接使用实现对 象,会看到实现对象中的私有部分,这部分可能有些是重要的涉及到安全方面的信息。

@configuration

@EnableResponseBodyAdvice 自定义返回数据类型(响应头)

SpringBoot

 

  • Spring boot 是 Spring 的一套快速配置脚手架,可以基于spring boot 快速开发单个微服务;Spring

Cloud是一个基于Spring Boot实现的云应用开发工具;

  • Spring boot专注于快速、方便集成的单个个体,Spring Cloud是关注全局的服务治理框架;

  • spring boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring

Cloud很大的一部分是基于Spring boot来实现。

  • Spring boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring boot,属于依赖的

关系。

启动顺序

  1. FsFilterConfig CharacterEncodingFilter设置字符编码

  2. RabbitMqConfig

  3. SimpleThreadPoolService 创建线程池

  4. FsWebConfig

  5. FsStartUpListener

Spring Boot Actuator

Spring Boot Actuator可以帮助你监控和管理Spring Boot应用,比如健康检查、审计、统计和HTTP追踪等。所有的这些特性可以通过JMX或者HTTP endpoints来获得。

Endpoint

监控应用服务的运行状况,并集成在Mvc中提供查看接口。

/actuator/refresh

解析常用的actuator endpoint

/health endpoint

health endpoint通过合并几个健康指数检查应用的健康情况。

Spring Boot Actuator有几个预定义的健康指标比如DataSourceHealthIndicator, DiskSpaceHealthIndicator, MongoHealthIndicator, RedisHealthIndicator, CassandraHealthIndicator等。它使用这些健康指标作为健康检查的一部分。

举个例子,如果你的应用使用RedisRedisHealthindicator将被当作检查的一部分。如果使用MongoDB,那么MongoHealthIndicator将被当作检查的一部分。

你也可以关闭特定的健康检查指标,比如在prpperties中使用如下命令:

management.health.mongo.enabled=false

默认,所有的这些健康指标被当作健康检查的一部分。

@Transactional

Springboot,抛出业务异常后回滚,或在发生未被捕获的 RuntimeException 时回滚

如果类上加了@Transactional("defaultTransactionManager") ,就是说类里面的方法都用这个事务管理器,如果有方法单独用了其他管理器,就在方法上另外加一个@Transactional("secondTransactionManager")

@RestController注解

相当于@ResponseBody + @Controller合在一起的作用

@ExceptionHandler注解声明异常处理方法

@ControllerAdvice 注解定义全局异常处理类,处理response

  • supports 必须返回true,否则不会执行beforeBodyWrite方法

  • beforeBodyWrite

  • setEnvironment项目启动时执行一次

@ConfigurationProperties(prefix = "spring.datasource.shareniu")

@PropertySource( name="jdbc-bainuo-dev.properties",value= {"classpath:config/jdbc-bainuo-dev.properties"},ignoreResourceNotFound=false,encoding="UTF-8")

注解加载指定的属性文件,比如prefix = "spring.datasource.shareniu",CustomerDataSourceConfig1类中有一个url字段,则url字段需要匹配的属性是prefix+字段=spring.datasource.shareniu.url。

@Component

泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。

@Autowired

扫描,自动注入@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。

@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。

@Resources按名字,是JDK的,@Autowired按类型,是Spring的。

 

扩展Spring MVC

@EnableWebMvc

在配置类中通过@EnableWebMvc注解来实现完全自己控制的MVC的java配置类

使用HttpMessageConverter进行http序列化和反序列化

@RestController中有@ResponseBody,可以帮我们把User序列化到resp.body中。@RequestBody可以帮我们把req.body的内容转化为User对象,Http序列化/反序列化

@PostConstruct说明 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。

构造方法是容器实例selevlet 用的,init其实是构造方法调用的,简单说,先构造方法,然后init方法

InvocableHandlerMethod处理返回参数

invoke

invoke(class, method) 把方法参数化,Test类里有一系列名字相似的方法setValue1setValue2,把方法名存进数组v[],然后循环里invoke(test,v[i]),顺序调用全部setValue

其他

DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可使用多个DLL文件,一个DLL文件也可能被不同的应用程序使用,这样的DLL文件被称为共享DLL文件。

分布式

高性能系统的优化原则:

写入内存而不是写入硬盘

异步处理而不是同步处理

分布式处理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值