add kownledge ahout mechine learning2

This commit is contained in:
simple321vip
2026-08-25 22:44:19 +08:00
parent 909c458b07
commit 3aa2f9e4e3
12 changed files with 0 additions and 2283 deletions
-199
View File
@@ -1,199 +0,0 @@
# Golang
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`2023022315480800000000000001` · 排序:12 · 文章数:4
## 目录
1. [3. grpc xds](#3-grpc-xds)
2. [2. grpc health check](#2-grpc-health-check)
3. [1. grpc protoc](#1-grpc-protoc)
4. [4. Go](#4-go)
---
## 1. 3. grpc xds
<sub>bid: `2023022315480900000000000020`</sub>
该写点什么么...
---
## 2. 2. grpc health check
<sub>bid: `2023022315484500000000000019`</sub>
##
---
## 3. 1. grpc protoc
<sub>bid: `2023022315507600000000000021`</sub>
## base consepts
- protobuf
我们可以查看官方文档 [protobuf guides](https://protobuf.dev/programming-guides/proto3/)
简单来说就是一种以 .proto 结尾文件,遵循protocol buffer language 语法,其中包含一个或者多个message和service。
**notice_service.proto**
syntax = "proto3";
package notice.service.v1;
option go_package ="violin-notice/pkg/service/notice.service.v1";
message NoticeMessage {
};
message NoticeResponse {};
service NoticeService {
rpc SendNotice(NoticeMessage) returns (NoticeResponse) {}
}
- protoc
[protoc guides](https://github.com/bufbuild/protoc-gen-validate)
作为可执行程序,其作用是将上面的我们定义的.proto文件转换成对应语言的grpc 可用的文件,我们通过对这些文件进行扩展来实现我们想要的场景。
protoc --go_out=./gen --go_opt=paths=source_relative --go-grpc_out=./gen --go-grpc_opt=paths=source_relative notice_service.proto
执行上面命令会生成go语言的两个文件
notice_service_grpc.pb.go
notice_service.pb.go
我们只需要自己写一个notice_service.go 来扩展上述两个文件即可。
**package notice_service_v1**
import (
"context"
"gopkg.in/gomail.v2"
"log"
"violin-home.cn/common/logs"
)
type NoticeService struct {
UnimplementedNoticeServiceServer
}
func New() *NoticeService {
return &NoticeService{}
}
func (*NoticeService) SendNotice(
ctx context.Context, msg *NoticeMessage) (*NoticeResponse, error) {
// to write logic
return &NoticeResponse{}, nil
}
## 如何使用grpc
grpc 存在client和server
---
## 4. 4. Go
<sub>bid: `2023030213489100000000000022`</sub>
## 1. 概述
一些简单的概念介绍可以通过下面网站学习到。
[golang 菜鸟教程](https://www.runoob.com/go/go-tutorial.html)
## 2. package
golang的包管理模式是树形的,并且有以下规约:
**1**
树形结构的根节点是main,即项目根目录。
**2**
文件中的包定义 一定是和该文件所处的文件夹相同
**3**
文件中定义的函数,如果是像作为第三方包引用,函数的首字母必须大写
# violin-controller 工程为例 https://github.com/simple321vip/violin-controller
ls
main.go controller.go controller_test.go 都是 根目录下的文件,所以他们的package 都是 main
请注意 包 的名字只能是该文件夹的名字,并不包括父级路径
**4 引包**
引包 包括第三方包 和 项目自定义包
在mod模式下,第三方包存在 \$GOPATH/pkg/mod
而自定义包 引入的时候直接从采用 项目相对路径的方式引入
## 3. 变量与指针
变量分为 值变量和指针变量
## 4. 函数
**1. main()** 函数
程序入口函数
**2. init()** 函数
每一个源文件都可以包含一个init函数,init意为初始化,也表明init函数会在main函数执行之前执行。
**3. go func()** 函数
并发编程 即异步
**4. func() {}()** 匿名函数
匿名函数可以通过变量指向匿名函数,可以匿名函数直接执行
// 声明一个函数变量
f := func() int {
return 1
}
// 调用函数
f()
// 也可以直接执行匿名函数
func() int {
return 1
}()
**5. func sample() func() int {}** 通过匿名函数实现闭包
package main
import "fmt"
func getSequence() func() int {
i:=0
return func() int {
i+=1
return i
}
}
func main(){
/* nextNumber 为一个函数,函数 i 为 0 */
nextNumber := getSequence()
/* 调用 nextNumber 函数,i 变量自增 1 并返回 */
fmt.Println(nextNumber())
fmt.Println(nextNumber())
fmt.Println(nextNumber())
/* 创建新的函数 nextNumber1,并查看结果 */
nextNumber1 := getSequence()
fmt.Println(nextNumber1())
fmt.Println(nextNumber1())
}
---
-659
View File
@@ -1,659 +0,0 @@
# Java and Spring
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`00000000000002` · 排序:1 · 文章数:14
## 目录
1. [Springboot AbstractApplicationContext](#springboot-abstractapplicationcontext)
2. [Map Set List](#map-set-list)
3. [Java8 AQS](#java8-aqs)
4. [Java8 Stream](#java8-stream)
5. [Spring superinterface](#spring-superinterface)
6. [Springboot DefaultSingletonBeanRegistry](#springboot-defaultsingletonbeanregistry)
7. [Springboot SpringApplication](#springboot-springapplication)
8. [Springboot AbstractBeanFactory](#springboot-abstractbeanfactory)
9. [Springboot AbstractAutowireCapableBeanFactory](#springboot-abstractautowirecapablebeanfactory)
10. [Springboot AbstractBeanDefinition](#springboot-abstractbeandefinition)
11. [Springboot ConfigurationClassPostProcessor](#springboot-configurationclasspostprocessor)
12. [Spring ASM](#spring-asm)
13. [PostProcessorRegistrationDelegate](#postprocessorregistrationdelegate)
14. [Spring Aop](#spring-aop)
---
## 1. Springboot AbstractApplicationContext
<sub>bid: `00000000000003`</sub>
## AbstractApplicationContext
AbstractApplicationContext 是 SpringBoot的 核心应用上下文父类。
## x.1 properties
### beanFactoryPostProcessors
### environment
## x.2 methods
### refresh
refresh 是 Springboot启动中核心方法。
- prepareRefresh
- obtainFreshBeanFactory
- prepareBeanFactory
- postProcessBeanFactory
- invokeBeanFactoryPostProcessors
- registerBeanPostProcessors
- onRefresh
- finishBeanFactoryInitialization
- finishRefresh
---
## 2. Map Set List
<sub>bid: `2022051816085000000000000006`</sub>
### 1. Summary
我们在开发过程在,最常见的三种数据存储结构就是 Map Set 和List了
这三种结构最明显的特征就是Map 是键值,Set是对象存储唯一,List是有序数组
### Map<K, V>
键值存储,主键不允许重复
添加元素 使用put方法,如果key重复,则value被覆盖
### Set<E>
对象存储,对象不允许重复
/**
* if this set did not already contain the specified element will return {@code true}
* f this set already contains the element, the call leaves the set
* unchanged and returns {@code false}
*/
public boolean add(E e)
### List<E>
list是由数组构成的,这就意味着,list是有顺序的,因为数组在内存中是一段连续的内存。
---
## 3. Java8 AQS
<sub>bid: `2022052314143400000000000014`</sub>
## AQ
---
## 4. Java8 Stream
<sub>bid: `2022060810550500000000000022`</sub>
## S
---
## 5. Spring superinterface
<sub>bid: `2022120915183100000000000001`</sub>
## summary
## 1. Aware(感知)
Spring Ioc 是解耦行为,我们的业务代码其实是没有感知或者意识到spring框架的存在。如果我们需要使用spring Ioc中的资源时候,我们就需要有意识的去获取这个资源,而Aware 就是这样的存在。
@Service
public class AppContextAware implements ApplicationContextAware {
ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
public void hello(){
//user为容器中存在的bean
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
//获取容器的环境、User.name为设置好的属性
Environment environment = applicationContext.getEnvironment();
String property = environment.getProperty("User.name");
System.out.println(" 属性:"+property);
}
}
一些常用的Aware interface
BeanNameAware
ApplicationContextAware
ResourceLoaderAware
EnvironmentAware
## 2. BeanFactory
BeanFactory 提供了获取bean和判断bean的方法,包括
getBean(String beanName)
getBean(String beanName, Class<T> requiredType)
getBean(Class<T> requiredType)
containsBean(String name)
isSingleton(String name)
isPrototype(String name)
sTypeMatch(String name)
getType(String name)
String[] getAliases(String name);
## 3. BeanPostProcessor
## 4. BeanFactoryPostProcessor
## 5. ApplicationContext
## 6. InitializingBean
---
## 6. Springboot DefaultSingletonBeanRegistry
<sub>bid: `2022121513519200000000000002`</sub>
## DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistry 是Springboot bean 自动装配的核心实现类。
顾名思义,是默认的单例bean 注册器。
## x.1 properties
### dependentBeanMap
存放(依赖对象key -> 被依赖Set)的 ConcurrentHashMap
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
### dependenciesForBeanMap
存放(被依赖对象key -> 依赖Set)的 ConcurrentHashMap
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
###
## x.2 methods
### registerDependentBean
我们知道Spring DI 依赖注入,此方法就是依赖注入的核心组成。注意,这段逻辑是加锁的,即存在并行处理逻辑。
Springboot 在 AbstractApplicationContext 进行 refresh 操作时候,在最后一步会实例化bean,参照AbstractApplicationContext.finishBeanFactoryInitialization 方法,此方法的流程我们会在xxx讲解。源码如下
/**
* Register a dependent bean for the given bean。
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
DI 在此处的实现逻辑可以通过下面例子来通俗说明:
① A对象 依赖 B对象
② A对象 依赖 C对象
③ D对象 依赖 B对象
所以 必须要提前先把 B 对象和 C对象进行实例化后,才能 创建A对象和 D对象。
我们从RootBeanDefinition中获取 dependsOn的数组,遍历调用registerDependentBean方法
参数beanName是依赖对象,即 B 或者 C,参数dependentBeanName是被依赖对象A
1. 传入参数是 (B,A) 时,为 B 创建一个 LinkedHashSet,并在该Set中存放A, 并把 B -> Set的映射关系放入dependentBeanMap中。
紧接着 为 A 创建一个 LinkedHashSet, 并在该Set中存放B,并把 A -> Set的映射关系放入dependenciesForBeanMap中。
2. 传入参数是 (C, A) 时,为 C 创建一个 LinkedHashSet,并在该Set中存放A, 并把 C -> Set的映射关系放入dependentBeanMap中。
因为 dependenciesForBeanMap 已经存在了 A -> Set这个映射,我们只需将 C 也存入这个Set就可以。
3. 传入参数是 (B, D) 时,因为 dependentBeanMap 已经存在了 B -> Set这个映射,我们只需将 D 也存入这个Set就可以。
紧接着 为 D 创建一个 LinkedHashSet, 并在该Set中存放B,并把 D -> Set的映射关系放入dependenciesForBeanMap中。
`注意` 依赖和被依赖总是成对出现的,dependentBeans.add(dependentBeanName) 返回 false,视为添加失败,即视为已经存在,根据 依赖和被依赖总是成对出现的,所以后面dependenciesForBean.add(canonicalName) 这部分就没必要执行了,因为执行了也没有意义,所以直接 return了。毕竟dependenciesForBean中已经存在了canonicalName。
---
## 7. Springboot SpringApplication
<sub>bid: `2022121513597200000000000003`</sub>
## SpringApplication
## x.1 properties
### sources
### environment
### webApplicationType
###
## x.2 methods
### run
1. 创建 DefaultBootstrapContext
2. 获取 SpringApplicationRunListeners
3. 转换 ApplicationArguments 将commandLine args
4. 装备环境 ConfigurableEnvironment
5. 配置忽略bean情报 configureIgnoreBeanInfo
6. 创建 ApplicationContext
7. 准备 ApplicationContext prepareContext
设置上下文环境,加载source
8. 刷新 ApplicationContext
9. 刷新后处理
---
## 8. Springboot AbstractBeanFactory
<sub>bid: `2022121515315000000000000004`</sub>
## AbstractBeanFactory
## x.2 methods
### doGetBean
AbstractBeanFactory 的核心方法 doGetBean,doGetBean方法是由getBean调用的,如果有dependsOn存在,就会将注册依赖, 然调用getBean(dep),从而形成了递归操作。
当不存dependsOn的时候mbd.isSingleton 时候,就会调用 getSingleton方法,子类会回调createBean(beanName, mbd, args)方法,去创建bean。
源码
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType) {
String beanName = transformedBeanName(name);
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
---
## 9. Springboot AbstractAutowireCapableBeanFactory
<sub>bid: `2022121523309700000000000005`</sub>
## AbstractAutowireCapableBeanFactory
父类是AbstractBeanFactory,实现了AutowireCapableBeanFactory 的方法,其中最主要的还是createBean方法。
源码
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
---
## 10. Springboot AbstractBeanDefinition
<sub>bid: `2022121523361800000000000006`</sub>
## AbstractBeanDefinition
AbstractBeanDefinition 定义了 一个bean的各种描述。
## x.1
### String[] dependsOn
### Resource resource
###
---
## 11. Springboot ConfigurationClassPostProcessor
<sub>bid: `2022121612282000000000000009`</sub>
## ConfigurationClassPostProcessor
这一节主要讲的是ConfigurationClassPostProcessor和他的一些生态。
他的生态有
- ConfigurationClassParser 真正的处理者。
- ComponentScanAnnotationParser 扫描classpath,把beanName加入到registry的beanDefinitionMap中。
- doProcessConfigurationClass 是该 postProcessor最核心的处理方法
/**
* Apply processing and build a complete {@link ConfigurationClass} by reading the
* annotations, members and methods from the source class. This method can be called
* multiple times as relevant sources are discovered.
* @param configClass the configuration class being build
* @param sourceClass a source class
* @return the superclass, or {@code null} if none found or previously processed
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
---
## 12. Spring ASM
<sub>bid: `2022121615335100000000000010`</sub>
## asm
在spring中其实很少听到asm这个关键字,asm -> Assembly,跟多是指汇编语言。
spring也是用到asm,而且asm包是spring-core的组成部分。spring asm 大体上跟 原生的asm 都是差不多了。
(参照链接)[ https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/asm/package-summary.htm ]
package org.springframework.asm
Spring's repackaging of ASM 9.x (with Spring-specific patches; for internal use only).
This repackaging technique avoids any potential conflicts with dependencies on ASM at the application level or from third-party libraries and frameworks.
As this repackaging happens at the class file level, sources and javadocs are not available here.
从package-info可以看出,repackaging,avoids any potential conflicts
---
## 13. PostProcessorRegistrationDelegate
<sub>bid: `2022121915527600000000000011`</sub>
## PostProcessorRegistrationDelegate
作为 Delegate 提供了 静态方法 invokeBeanFactoryPostProcessors。
主要是将beanFactory和beanFactoryPostProcessors做matching,
然后对beanFactoryPostProcessors做遍历调用postProcessBeanFactory(beanFactory)
## ConfigurationClassPostProcessor
postProcessBeanFactory(beanFactory)
processConfigBeanDefinitions(beanFactory)
核心的 处理方法,
---
## 14. Spring Aop
<sub>bid: `2022122715594900000000000012`</sub>
## Aop
Aspect Oriented Programming的缩写,意为:面向切面编程。
Spring aop 作为spring的一个模块,在springboot中是在bean的实例化中使用的。
AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
# 实现了Aware接口<BeanNameAware><BeanClassLoaderAware><BeanFactoryAware>会invoke对应的set方法。
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
# beanPostProcesser的before方法。
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
# 实现了InitializingBean接口的会invoke afterPropertiesSet方法。
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
# beanPostProcesser的after方法。
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
else {
advised.addAdvisor(this.advisor);
}
return bean;
}
}
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != bean.getClass().getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
# ProxyFactory 其实就是创建动态代理或者Cglib的 InvocationHandler调用Proxy.newProxyInstance返回代理对象
return proxyFactory.getProxy(classLoader);
}
// No proxy needed.
return bean;
}
---
@@ -1,745 +0,0 @@
# Kubernetes 最佳实践
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`2022050319356100000000000001` · 排序:4 · 文章数:8
## 目录
1. [Mongo Replica 集群搭建](#mongo-replica-集群搭建)
2. [kubernetes nfs](#kubernetes-nfs)
3. [Mongo Replica 集群搭建-1](#mongo-replica-集群搭建-1)
4. [kubernetes](#kubernetes)
5. [kubeadm](#kubeadm)
6. [kubernetes containerd](#kubernetes-containerd)
7. [新增加work节点](#新增加work节点)
8. [kubelet](#kubelet)
---
## 1. Mongo Replica 集群搭建
<sub>bid: `2023033021115000000000000029`</sub>
## Replica Set 集群搭建
本篇文章记录了基于mongodb-kubernetes-operator【Replica Set】模式集群搭建。
[1]()
[2](https://github.com/mongodb/mongodb-kubernetes-operator)
[3](https://github.com/mongodb/mongodb-kubernetes-operator/blob/master/docs/install-upgrade.md#install-the-operator-using-kubectl)
### 1. 事前准备
> kubernetes 版本: 1.23.9
> mongodb 版本:6.0.2
> nfs: 提前搭建好了kubernetes的nfs系统(具体搭建可以参照)。
### 2. github项目mongodb-kubernetes-operator
[项目地址](https://github.com/mongodb/mongodb-kubernetes-operator)
我们使用mongodb 官网推荐的 mongodb-kubernetes-operator 来进行集群安装。
[document](https://github.com/mongodb/mongodb-kubernetes-operator/blob/master/docs/install-upgrade.md#install-the-operator-using-kubectl)
我们事先把 mongodb-kubernetes-operator 项目中我们要使用的yaml文件复制到我们的工作目录 mongo, 需要的文件夹如下:
+ mongo
+ config/crd/bases/
+ config/rbac/
+ config/manager/
+ config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml
+ deploy/clusterwide/
$ pwd
/usr/local/kubernetes/mongo
$ ls
config deploy
### 3. 按照document依次进行安装
#### 3.1 创建 mongodb 使用的namespace
kubectl create ns kube-mongo
#### 3.2 创建集群rbac 权限
# 修改 deploy/clusterwide/cluster_role_binding.yaml 中namespace 为 3.1 中我我们创建的 [kube-mongo]
kubectl apply -f deploy/clusterwide
kubectl apply -k config/rbac --namespace kube-mongo
#### 3.3 创建 crd
kubectl apply -f config/crd/bases/mongodbcommunity.mongodb.com_mongodbcommunity.yaml
#### 3.4 安装operator
kubectl create -f config/manager/manager.yaml --namespace kube-mongo
#### 3.5 安装mongodb
修改 config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml文件
- 修改 MongoDBCommunity 资源
我们修改 metadata.name=violin-mongodb
我们修改 spec.version= "6.0.2"
我们修改 spec.users.name[0].passwordSecretRef.name= kube-mongo-pw
- 修改 Secret 资源
我们修改 metadata.name= kube-mongo-pw
我们修改 stringData.password= "任意随意写了吧"
然后进行安装
kubectl apply -f config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml --namespace kube-mongo
#### 3.6 重新创建pvc
由于我使用的是自定义的storageclass,pvc 处于 pending状态,我们删除掉pvc
kubectl delete pvc data-volume-violin-mongodb-0 -n kube-mongo
kubectl delete pvc logs-volume-violin-mongodb-0 -n kube-mongo
我们创建新的pvc定义文件:
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-volume-violin-mongodb-0
namespace: kube-mongo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: managed-nfs-storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-volume-violin-mongodb-1
namespace: kube-mongo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: managed-nfs-storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-volume-violin-mongodb-2
namespace: kube-mongo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: managed-nfs-storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: logs-volume-violin-mongodb-0
namespace: kube-mongo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: managed-nfs-storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: logs-volume-violin-mongodb-1
namespace: kube-mongo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: managed-nfs-storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: logs-volume-violin-mongodb-2
namespace: kube-mongo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: managed-nfs-storage
我们 创建 pvc
kubectl apply -f pvc.yaml
# 查看pvc 是否已
kubectl get pvc -n kube-mongo
kube-mongo data-volume-violin-mongodb-0 Bound pvc-1ac1a5fd-389c-496d-a47c-7df11d5f5a34 10Gi RWO managed-nfs-storage 41m
kube-mongo data-volume-violin-mongodb-1 Bound pvc-39008253-8702-4cc5-876a-0561850929bb 10Gi RWO managed-nfs-storage 61m
kube-mongo data-volume-violin-mongodb-2 Bound pvc-a7e867d3-b499-486a-9b39-a42ac5a00b43 10Gi RWO managed-nfs-storage 61m
kube-mongo logs-volume-violin-mongodb-0 Bound pvc-209ed46c-d558-4a09-8a2f-edfddbed610c 1Gi RWO managed-nfs-storage 41m
kube-mongo logs-volume-violin-mongodb-1 Bound pvc-664b307f-ab95-4af3-8851-17a3ecd2b57c 1Gi RWO managed-nfs-storage 61m
kube-mongo logs-volume-violin-mongodb-2 Bound pvc-a8f3a8d2-337d-4470-9ef4-5dbe18a4100a 1Gi RWO managed-nfs-storage 61m
### 4. 关于删除资源的问题。
我们创建operator 或者 statefuset 出错的时候,可以重新删除他们。
#### 4.1 删除 operator
kubectl delete deployments.apps mongodb-kubernetes-operator -n kube-mongo
#### 4.1 删除 statefulset
kubectl delete statefulsets.apps violin-mongodb -n kube-mongo
### 5. 关于 mongosh的使用
kubectl get secret <connection-string-secret-name> -n <my-namespace> -o json | jq -r '.data | with_entries(.value |= @base64d)'
kubectl get secret violin-mongodb-admin-my-user -n kube-mongo -o json | jq -r '.data | with_entries(.value |= @base64d)'
---
## 2. kubernetes nfs
<sub>bid: `2023040608509800000000000030`</sub>
## 1 概述
---
&emsp;&emsp;本篇文章记录了violin-home网站NFS系统搭建过程。
采用腾讯云的3台公网云轻量服务器(ubuntu系统)
> NFS服务需要开启 mountd,nfs,nlockmgr,portmapper,rquotad这5个服务.
&emsp;&emsp;其中
# 查看服务使用端口
# nfs : 2049
# portmapper: 111
# mountd, nlockmgr, rquotad 是随机的
# 所以事先要做好端口规划, 在轻量云服务器上开放对应的端口.
```bash
rpcinfo -p
```
## 2 nfs 服务器搭建
---
# install server
apt-get install nfs-kernel-server
# enable and start server
systemctl enable nfs-server
systemctl start nfs-server
# confirm nfs-server status
# create storage
mkdir -p /data/nfs-volume && chmod -R 777 /data/nfs-volume
# edit config file
cat > /etc/exports << EOF
/data/nfs-volume 49.233.4.79(rw,sync,no_root_squash) 43.138.55.43(rw,sync,no_root_squash) 43.138.73.106(rw,sync,no_root_squash)
EOF
# view nfs port usage
rpcinfo -p
# set port infomation for mountd、rquotad ser
# edit nfs-common status
vi /etc/default/nfs-common
STATDOPTS="--port 31000"
# edit nfs-kernel-server status
vi /etc/default/nfs-kernel-server
RPCMOUNTDOPTS="--manage-gids -p 31001"
# edit nlockmgr ,就算进行了这一步操作,也可能不生效。
vi /etc/modprobe.d/options.conf
options lockd nlm_udpport=31002 nlm_tcpport=31002
# to add locked
vi /etc/modules
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
lockd
vi /etc/sysctl.conf
fs.nfs.nlm_udpport=31002
fs.nfs.nlm_tcpport=31002
# enable sysctl.conf
/sbin/sysctl -p
# reload server and service
systemctl reload nfs-server
systemctl restart rpcbind.service
systemctl restart nfs.service
# view nfs port usage again
rpcinfo -p
# to confirm client ip
showmount -e 49.233.4.79
# Export list for 49.233.4.79:
# /data/nfs-volume 43.138.73.106,43.138.55.43,49.233.4.79
## 3 nfs 客户端搭建
---
&emsp;&emsp;下面操作需要在每台node上操作,包括master节点。
# install client
apt-get install nfs-common
# create mount path for client(we use different path to server)
mkdir /opt/nfs-volume
# mount
mount -t nfs 49.233.4.79:/data/nfs-volume /opt/nfs-volume
df -h | tail -1
# config auto mount for client
cat >> /etc/fstab << EOF
49.233.4.79:/data/nfs-volume /opt/nfs-volume defaults,_netdev 0 0
EOF
## 4
---
## 3. Mongo Replica 集群搭建-1
<sub>bid: `2023040623407900000000000031`</sub>
## Replica Set 集群搭建
本篇文章记录了基于 helm bitnami/mongodb chat的【Replica Set】模式集群搭建。
[参照文档](https://github.com/bitnami/charts/tree/main/bitnami/mongodb)
### 1. 事前准备
> kubernetes 版本: 1.23.9
> mongodb 版本:6.0.2
> nfs: 提前搭建好了kubernetes的nfs系统(具体搭建可以参照)。
> storageclass: 提前准备好了基于nfs的storageclass。
> helm: 已经安装了helm
### 2. 添加bitnami repo
helm repo add bitnami https://charts.bitnami.com/bitnami
### 3. 查询 mongodb 相关资源
helm repo update
helm search repo mongodb
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/mongodb 13.9.4 6.0.5 MongoDB(R) is a relational open source NoSQL da...
bitnami/mongodb-sharded 6.3.3 6.0.5 MongoDB(R) is an open source NoSQL database tha...
### 4. 创建helm 配置文件
## values.yaml
global:
namespaceOverride: kube-mongo
storageClass: "managed-nfs-storage"
nameOverride: violin-mongo
image:
pullPolicy: IfNotPresent
architecture: "replicaset"
replicaCount: 3
#auth:
# rootUser: "root"
# rootPassword: "123654"
# usernames:
# - "guan"
# passwords:
# - "83201048"
# databases:
# - "violin"
resources:
requests:
cpu: "0.2"
memory: 200M
limits:
cpu: "0.3"
memory: 300M
containerPorts:
mongodb: 27017
externalAccess:
enabled: true
service:
externalTrafficPolicy: "Cluster"
type: "ClusterIP"
persistence:
enabled: true
size: 5Gi
### 5. 安装 mongodb
helm install mongodb bitnami/mongodb -f values.yaml
NAME: mongodb
LAST DEPLOYED: Fri Apr 7 11:49:07 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mongodb
CHART VERSION: 13.9.4
APP VERSION: 6.0.5
** Please be patient while the chart is being deployed **
MongoDB&reg; can be accessed on the following DNS name(s) and ports from within your cluster:
mongodb-violin-mongo-0.mongodb-violin-mongo-headless.kube-mongo.svc.cluster.local:27017
mongodb-violin-mongo-1.mongodb-violin-mongo-headless.kube-mongo.svc.cluster.local:27017
mongodb-violin-mongo-2.mongodb-violin-mongo-headless.kube-mongo.svc.cluster.local:27017
To get the root password run:
export MONGODB_ROOT_PASSWORD=$(kubectl get secret --namespace kube-mongo mongodb-violin-mongo -o jsonpath="{.data.mongodb-root-password}" | base64 -d)
To get the password for "guan" run:
export MONGODB_PASSWORD=$(kubectl get secret --namespace kube-mongo mongodb-violin-mongo -o jsonpath="{.data.mongodb-passwords}" | base64 -d | awk -F',' '{print $1}')
To connect to your database, create a MongoDB&reg; client container:
kubectl run --namespace kube-mongo mongodb-violin-mongo-client --rm --tty -i --restart='Never' --env="MONGODB_ROOT_PASSWORD=$MONGODB_ROOT_PASSWORD" --image docker.io/bitnami/mongodb:6.0.5-debian-11-r4 --command -- bash
Then, run the following command:
mongosh admin --host "mongodb-violin-mongo-0.mongodb-violin-mongo-headless.kube-mongo.svc.cluster.local:27017,mongodb-violin-mongo-1.mongodb-violin-mongo-headless.kube-mongo.svc.cluster.local:27017,mongodb-violin-mongo-2.mongodb-violin-mongo-headless.kube-mongo.svc.cluster.local:27017" --authenticationDatabase admin -u root -p $MONGODB_ROOT_PASSWORD
To connect to your database nodes from outside, you need to add both primary and secondary nodes hostnames/IPs to your Mongo client. To obtain them, follow the instructions below:
### 6. connect
db.createUser({user: "root", pwd: "123654", roles: ["root"]})
---
## 4. kubernetes
<sub>bid: `2023040717276500000000000032`</sub>
## kubernetes 1.25.2 base Containerd
### 1. deploy schedule
NAME | IP | ROLES | VERSION | OS
k8s-master | 192.168.8.30 | master | 1.25.2 | ubuntu 22.04
k8s-node1 | 192.168.8.31 | worker | 1.25.2 | ubuntu 22.04
k8s-node2 | 192.168.8.32 | worker | 1.25.2 | ubuntu 22.04
### 2. preparation
#### 2.1 安装系统工具
```bash
apt-get update && apt-get install -y apt-transport-https
```
#### 2.2 安装 GPG 证书
```bash
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
```
#### 2.3 写入软件源
```bash
cat << EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
```
#### 2.4 vi hostname
```bash
vi /etc/hostname
vi /etc/hosts
reboot
```
#### 2.5 selinux
```bash
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
```
#### 2.6 禁用交换分区
```bash
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
```
#### 2.7 iptables
```bash
echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/ipv4/ip_forward
vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
sudo sysctl --system
```
#### 2.8
### 3 install kubectl kubelet kebeadm
#### 3.1 install
```bash
apt-get install -y kubelet=1.25.2-00 kubeadm=1.25.2-00 kubectl=1.25.2-00
```
### 4 Containerd
#### 4.1 install Containerd
```bash
apt-get install containerd.io
```
#### 4.2 generate config file
```bash
containerd config default | sudo tee /etc/containerd/config.toml
```
#### 4.3 edit config.toml
```bash
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6"
SystemdCgroup = true
```
#### 4.4 restart
```bash
systemctl restart containerd && systemctl enable containerd
crictl version
```
#### 4.5 edit crictl.yaml
```bash
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
```
#### 4.6 confirm crictl
```bash
crictl images
```
### 5 kubeadm
#### 5.1 kubeadm init
```bash
kubeadm init --kubernetes-version=1.25.2 \
--apiserver-advertise-address=192.168.8.30 \
--apiserver-bind-port=6443 \
--image-repository=registry.aliyuncs.com/google_containers \
--service-cidr=10.96.0.0/12 \
--cri-socket unix:///var/run/containerd/containerd.sock \
--ignore-preflight-errors=Swap \
--control-plane-endpoint=k8s-master \
--upload-certs
```
```
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of the control-plane node running the following command on each as root:
kubeadm join k8s-master:6443 --token 81jkv9.2n555fci6m6i9afx \
--discovery-token-ca-cert-hash sha256:9ffe6e7ed7cf4ad6eb0e0dbb5b6f3bae1cac6989c3870653c83fe424715b4008 \
--control-plane --certificate-key c16ea4431de14998ccb28282b5e6215ab03c9ba94287903c6a8482add718034a
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join k8s-master:6443 --token 81jkv9.2n555fci6m6i9afx \
--discovery-token-ca-cert-hash sha256:9ffe6e7ed7cf4ad6eb0e0dbb5b6f3bae1cac6989c3870653c83fe424715b4008
```
#### 5.2 kubeconfig
```bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=/etc/kubernetes/admin.conf
```
#### 5.3 kubectl
```bash
kubectl get noe
```
```
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane 135m v1.25.2
```
---
## 5. kubeadm
<sub>bid: `2023041008541300000000000036`</sub>
## 1. xxx
22.04.1-Ubuntu
```bash
cat << EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/kubernetes-xenial main
EOF
```
```bash
apt-get update
apt-get install -y kubelet=1.25.2-00 kubeadm=1.25.2-00 kubectl=1.25.2-00
```
```bash
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
```
临时关闭swap分区,当前会话生效,重启失效
永久关闭swap分区
```bash
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
```
```bash
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
sudo sysctl --system
```
```bash
echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/ipv4/ip_forward
vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
```
```bash
cat > /etc/sysconfig/network-scripts/ifcfg-eth0 <<EOF
BOOTPROTO=static
DEVICE=eth0
IPADDR=172.16.0.11
PREFIX=32
TYPE=Ethernet
USERCTL=no
ONBOOT=yes
EOF
```
vi /etc/hosts
```bash
echo "######## edit /etc/hosts ########"
echo "" >> /etc/hosts
echo 192.168.8.30 k8s-master >> /etc/hosts
echo 192.168.8.31 k8s-node1 >> /etc/hosts
echo 192.168.8.32 k8s-node2 >> /etc/hosts
```
## about docker and cri-dockerd
```bash
docker pull golang:1.20.2
```
download cri-dockerd
```bash
echo "######### https://github.com/Mirantis/cri-dockerd/releases/tag/v0.3.2 ########'
tar -zxvf cri-dockerd-0.3.2.tar.gz
```
```bash
echo "######## chuangjian guazai dian ########"
mkdir /data
cd /data
mkdir go
cd go
echo "######## download cri-dockerd ########"
echo "######## https://github.com/Mirantis/cri-dockerd/releases/tag/v0.3.2 ########'
echo "######## jieya ########"
tar -zxvf cri-dockerd-0.3.2.tar.gz
echo "######## yunxing golang container ########"
docker run -it -v /data/go:/data/go golang:1.20.2 /bin/sh
```
enter container
```bash
cd /data/go/cri-dockerd-0.3.2
mkdir bin
go build -o bin/cri-dockerd
```
out container
```bash
cd /data/go/cri-dockerd-0.3.2
install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
cp -a packaging/systemd/* /etc/systemd/system
sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
systemctl daemon-reload
systemctl enable cri-docker.service
systemctl enable --now cri-docker.socket
```
---
## 6. kubernetes containerd
<sub>bid: `2023041415557100000000000037`</sub>
## containerd
## ctr
## crictl
## nerdctl
##
---
## 7. 新增加work节点
<sub>bid: `2023061019139700000000000038`</sub>
##
---
## 8. kubelet
<sub>bid: `2024042923524000000000000040`</sub>
该写点什么么...
---
File diff suppressed because one or more lines are too long
-151
View File
@@ -1,151 +0,0 @@
[{
"_id": {
"$oid": "626e92e3ff47411696bdc502"
},
"btId": "00000000000003",
"btName": "深入理解Java虚拟机",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 0
},{
"_id": {
"$oid": "627009d357c0264f499c3112"
},
"btId": "00000000000002",
"btName": "Java and Spring",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 1
},{
"_id": {
"$oid": "6270c35457c0264f499c3114"
},
"btId": "00000000000004",
"btName": "服务器和系统",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 2
},{
"_id": {
"$oid": "62711385ce1c9f5320a2d06a"
},
"btId": "2022050319356100000000000001",
"btName": "Kubernetes 最佳实践",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 4
},{
"_id": {
"$oid": "6271e199ce1c9f5320a2d06c"
},
"btId": "2022050410146100000000000003",
"btName": "计算机网路",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 7
},{
"_id": {
"$oid": "6273350ace1c9f5320a2d06e"
},
"btId": "2022050510233200000000000005",
"btName": "AWS",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 6
},{
"_id": {
"$oid": "6275315fce1c9f5320a2d07f"
},
"btId": "2022050622313300000000000022",
"btName": "十万个为什么",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 3
},{
"_id": {
"$oid": "6282353f1425aa536ca456d2"
},
"btId": "2022051619278900000000000002",
"btName": "深入刨析Kubernetes",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 5
},{
"_id": {
"$oid": "628ae75d1425aa536ca456da"
},
"btId": "2022052309468900000000000004",
"btName": "Azure",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 8
},{
"_id": {
"$oid": "6282759a1425aa536ca456d4"
},
"btId": "2022051700024800000000000003",
"btName": "quantitative trading",
"owner": "3272499474",
"updateTime": "",
"_class": "com.g.estate.entity.BlogType",
"order": 9
},{
"_id": {
"$oid": "6352618afe546b1de2f76d41"
},
"btId": "2022102117088800000000000001",
"btName": "machine learning",
"updateTime": "",
"_class": "cn.violin.home.book.entity.BlogType",
"owner": "3272499474",
"order": 10
},{
"_id": {
"$oid": "635262bbfe546b1de2f76d44"
},
"btId": "2022102117130200000000000002",
"btName": "probability and statistics",
"updateTime": "",
"_class": "cn.violin.home.book.entity.BlogType",
"owner": "3272499474",
"order": 11
},{
"_id": {
"$oid": "63f71a39f3eea8401859f543"
},
"btId": "2023022315480800000000000001",
"btName": "Golang",
"owner": "3272499474",
"updateTime": "2023-02-23 15:48:16",
"order": 12,
"_class": "cn.violin.wiki.entity.BlogType"
},{
"_id": {
"$oid": "6432acd0da833126fae88eae"
},
"btId": "20230409",
"btName": "常用 Command",
"owner": "3272499474",
"updateTime": "2023-04-09 20:17:25",
"order": 13,
"_class": "cn.violin.wiki.entity.BlogType"
},{
"_id": {
"$oid": "6732018fd2715f2cf34fa09e"
},
"btId": "2024111121076600000000000003",
"btName": "violin-home",
"owner": "3272499474",
"updateTime": "2024-11-11 21:07:39",
"order": 14,
"_class": "cn.violin.wiki.entity.BlogType"
}]
-125
View File
@@ -1,125 +0,0 @@
# violin-home
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`2024111121076600000000000003` · 排序:14 · 文章数:3
## 目录
1. [腾讯云证书从申请到发布](#腾讯云证书从申请到发布)
2. [腾讯云账号](#腾讯云账号)
3. [gogs ci/cd](#gogs-cicd)
---
## 1. 腾讯云证书从申请到发布
<sub>bid: `2024111121075900000000000042`</sub>
### 申请
略
### 解析
略
### 手动发布
// 创建k8s secret
kubectl create secret tls https-ca-${yyyyMMdd} --cert=violin-home.cn_bundle.crt --key=violin-home.cn.key -n devops
// 编辑ingress
kubectl edit ingress violin-ingress -n devops
// 替换名字
略,保存退出
---
## 2. 腾讯云账号
<sub>bid: `2024111121297600000000000043`</sub>
### 云账号
1. 索克
账号ID:ID100031913163
qq号: 244385414
账号有效时间: 2023-06-11 ~ 2026-06-11
2. 张奎
账号ID:100031899966
微信账号:
账号有效时间: 2023-06-11 ~ 2026-06-11
---
## 3. gogs ci/cd
<sub>bid: `2024111122270400000000000044`</sub>
### 1. Service
---
apiVersion: v1
kind: Service
metadata:
labels:
app: gogs
name: gogs
namespace: devops
spec:
ports:
- name: gogs
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: gogs
type: NodePort
### 2. Deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: gogs
name: gogs
namespace: devops
spec:
replicas: 1
selector:
matchLabels:
app: gogs
template:
metadata:
creationTimestamp: null
labels:
app: gogs
spec:
containers:
- image: gogs/gogs
imagePullPolicy: IfNotPresent
name: gogs
volumeMounts:
- mountPath: /data
name: volv
volumes:
- hostPath:
path: /root/k8s/moonfdd/gogs/data
type: DirectoryOrCreate
name: volv
### 3. PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: gogs-server-data
namespace: devops
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
-120
View File
@@ -1,120 +0,0 @@
# 常用 Command
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`20230409` · 排序:13 · 文章数:3
## 目录
1. [Docker](#docker)
2. [Git](#git)
3. [Linux](#linux)
---
## 1. Docker
<sub>bid: `2023040920175500000000000033`</sub>
## docker 常用 命令
### 1. 删除 None 镜像
```
docker images | grep none | awk '{print $3}' | xargs docker rmi
```
---
## 2. Git
<sub>bid: `2023040920200300000000000034`</sub>
该写点什么么...
https://biprogy.box.com/s/f0du3rvo97p4rvazzfrq4235djxqjsvj
---
## 3. Linux
<sub>bid: `2023040920200900000000000035`</sub>
### 1. linux系统版本
```bash
uname -a
cat /proc/version
```
### 2. CPU
```bash
echo "wuli cpu geshu:"
cat /proc/cpuinfo | grep "physical id" | wc -l
echo "wuli cpu geshu:"
cat /proc/cpuinfo | grep "processor" | wc -l
echo "per cpu has cores:"
cat /proc/cpuinfo | grep "cpu cores" | uniq
```
```bash
cat /proc/cpuinfo | grep "name" | cut -f2 -d: | uniq -c
```
```bash
lscpu
```
```bash
top -c
```
## 3. memory
```bash
cat /proc/meminfo
free
```
### 4. 更改hostname
```bash
vi /etc/hostname
```
```bash
vi /etc/hosts
```
```bash
reboot
```
## 5. netstat
```bash
netstat -ano | findstr 5000
taskkill /f /pid 104152
```
## 6. ps查看进程
- 查看正处于Running的进程
```bash
ps -ef
```
- 查看所有的进程
```bash
ps aux
```
## 7. mount
mount是Linux下的一个命令,它可以将分区挂接到Linux的一个文件夹下,从而将分区和该目录联系起来,因此我们只要访问这个文件夹,就相当于访问该分区了。
- show all the mount
```bash
mount -l
```
其中 tmpfs 是临时文件系统,而tmpfs是一个文件系统,并不是块设备,只是安装它,就可以使用了。tmpfs是最好的基于RAM的文件系统
## 8. alias
- alias [别名]='真实命令'
```bash
alias ku="kubectl"
```
---
-214
View File
@@ -1,214 +0,0 @@
# 服务器和系统
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`00000000000004` · 排序:2 · 文章数:7
## 目录
1. [Windows](#windows)
2. [关于Oauth的第三方授权登录](#关于oauth的第三方授权登录)
3. [网关(gateway)](#网关gateway)
4. [自己紹介](#自己紹介)
5. [ssh 免密登录](#ssh-免密登录)
6. [订单库存](#订单库存)
7. [2024-05-02](#2024-05-02)
---
## 1. Windows
<sub>bid: `2022051820523400000000000007`</sub>
我们通过powershell安装时,经常提示
更改 Windows PowerShell 执行策略的用户首选项。
Set-ExecutionPolicy
[Doc](https://docs.microsoft.com/zh-CN/previous-versions//dd347628(v=technet.10)?redirectedfrom=MSDN)
Enable-WindowsOptionalFeature
[Doc](https://docs.microsoft.com/en-us/powershell/module/dism/enable-windowsoptionalfeature?view=windowsserver2022-ps)
PS C:\WINDOWS\system32> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Tools-All
Enable-WindowsOptionalFeature : 功能名称 Microsoft-Hyper-V-Tools-All 未知。
所在位置 行:1 字符: 1
+ Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Enable-WindowsOptionalFeature
], COMException
+ FullyQualifiedErrorId : Microsoft.Dism.Commands.EnableWindowsOptionalFea
tureCommand
---
## 2. 关于Oauth的第三方授权登录
<sub>bid: `2022102117264100000000000010`</sub>
## 关于vilin-home的 安全认证
---
采用third part(第三方)认证 + token,暂时只支持百度云认证。
采用token 是防止 设备丢失等情况发生时,可以将用户暂时剔除租户体系,保证数据安全。是作为jwt认证的一种补充手段。
基本的认证flow如下:
> 用户 -> 登录 violin-home 网站
> token check -> 没有token的话,进入wolcome 页面,进入登录诱导页面,有token则进入home页面
> 点击 百度云登录 跳转到 百度扫码 页面
> 扫码成功,返回 回调code的连接,同时使用code 访问 violin-book 进入token获取
> violin-book 获取到code后 向 百度云 进行认证,获取 token,同时进行租户check,没有租户情报的认证用户,返回sorrypage,有租户情报的认证用户,跟新认证token到redis,并且重定向到 violin-home-manage 连接
> 解析 violin-home-manage 连接,获取token,通过token ,向violin-book获取租户基本信息,然后 跳转到home页面
> 至此 认证 完了
---
## 3. 网关(gateway)
<sub>bid: `2022121609222900000000000008`</sub>
https://biprogy.box.com/s/e2k26k78uhd2x4yo4skjfghp0y7ipc2w
https://app.boxcn.net/folder
---
## 4. 自己紹介
<sub>bid: `2023021420423600000000000018`</sub>
本日は貴重な時間をいただきありがとうございます。
カンショウイと申します。今年35歳です。
卒業した大学は中国の東北大学ですが、大学院生の出身大学はつくば大学、専門はシステム情報工学です。
卒業後、1年ぶりの土木系の仕事と一年ぶりの金融知識学習をしました。2017年からITに転職、それから創科技術会社、日本ハイロン株式会社、IBM株式会社の三社で働きました。
経験したプロジェクトは10個以上で、設計、開発、テスト、POC検証などのいくつかのフェーズも参加しました。
得意な開発言語はJava、Js、Go、kubernetesです。
IBMに入社後、フルスタックエンジニア、コンサルタントとアーキテクチャとして活躍しております。
去年はクラウドネイティブ CKA と Azure Iotの資格を取りました。
この経験をぜひ御社でも生かしていきたいと考えております。
どうぞよろしくお願いいたします。
https://teams.microsoft.com/l/meetup-join/19%3ameeting_NjRlMmEwN2QtNTU1My00M2Q3LWEyNDEtODAyODE5OWFkODAy%40thread.v2/0?context=%7b%22Tid%22%3a%22b2c6da00-de63-4f6a-90ed-17e48a1f64a2%22%2c%22Oid%22%3a%2252e6675f-d902-4939-b53f-6b69aabfdf35%22%7d
---
## 5. ssh 免密登录
<sub>bid: `2023033021097900000000000028`</sub>
## ssh
### 1. ssh install
```bash
apt-get install openssh-server openssh-client
```
```bash
service ssh start
```
### 2. ssh免密登录的设置十分简单
1、cd ~回到主目录,进入.ssh文件
```bash
cd ~/.ssh
```
2、ssh-keygen -t rsa 后,连续敲三次回车,生成两个文件 id_rsa是私钥,id_rsa.pub是公钥
```bash
ssh-keygen -t rsa
```
3、将公钥拷贝到目标机器上
```bash
ssh-copy-id node1
```
简单来说,就是在master机器生成密钥对。将公钥分发给其他的机器。
node1,node2,node3,这只是单向的情况。
如果互相免密登录的话,就需要做N*N的设置
---
## 6. 订单库存
<sub>bid: `2023102715164400000000000039`</sub>
一.订单
- 商品Master表
商品ID
分类ID
商品名称
- 订单表
订单ID
收货人
收货地址
总金额
实收金额
联系电话
订单状态
日期
备注
- 订单详细表
订单ID
商品ID
日期
批次
状态: 退货还是购买
单价
数量
总金额
备注
---
二.在库管理
- 库存表
商品ID
商品数量
商品价格
进货批次
进货日期
- 入库
入库ID
入库原因:进货 还是客户退货
入库时间
- 出库
出库ID
出库原因: 销售 还是 返品厂家
出库时间
---
三.客户管理
客户名称
手机
https://teams.microsoft.com/l/meetup-join/19%3ameeting_Yzg3NWRlOTMtMjJlOS00YWYxLTk0NWYtMTFmNzcxMzIxNWIy%40thread.v2/0?context=%7b%22Tid%22%3a%223d05ac27-c0a2-42f7-bd86-26ef7db5b382%22%2c%22Oid%22%3a%22df104270-a861-48af-b9dc-7a0600128f10%22%7d
---
## 7. 2024-05-02
<sub>bid: `2024050210383100000000000041`</sub>
作業定義
---
File diff suppressed because it is too large Load Diff
@@ -1,351 +0,0 @@
# 深入理解Java虚拟机
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`00000000000003` · 排序:0 · 文章数:9
## 目录
1. [谈一下垃圾回收算法](#谈一下垃圾回收算法)
2. [Jvm](#jvm)
3. [2.1运行时数据区域](#21运行时数据区域)
4. [2.2对象内存](#22对象内存)
5. [13.1线程安全与锁优化](#131线程安全与锁优化)
6. [12.1Java内存模型和线程](#121java内存模型和线程)
7. [12.2关键字volatile](#122关键字volatile)
8. [12.3 原子性,可见性,有序性](#123-原子性可见性有序性)
9. [12.4 Happens-Before](#124-happens-before)
---
## 1. 谈一下垃圾回收算法
<sub>bid: `00000000000001`</sub>
## Garbage Collection アルゴリズム ##
---
[参考文章](https://blog.csdn.net/Extraordinarylife/article/details/124309502)
&emsp;&emsp;对于Java开发人员来说,失去了引用的对象通常会被GC回收,而我们的方法都是我们的虚拟机栈中执行的,方法执行完毕后,引用被销毁,剩余的对象自然而然就是会被GC回收。
就如参考文章所说,JVM种虚拟机栈是随线程开启而创建,线程销毁而结束。
&emsp;&emsp;由于新的垃圾回收器G1的的出现,和方法区(永久代)的废弃,取而代之的metaspace的出现,以往的游戏知识已过时。但是其中的基本算法思想还是学要学习的。
基本算法思想:
### 标记-清除(mark-sweep)
---
标记是一个过程,他是通过**可达性分析算法**来实现的。
这里标记的通常是不被清除的对象,因为这样的对象很少。因为大多数对象的都是一次性的。
清除也是一个过程,它是基于**分代收集理论**实现的。清除未被标记的对象。
这种算法很明显会产生内存碎片化,内存不连续会直接导致提前gc的发生。
为了避免内存的碎片化,就有了复制算法。
### 复制算法
---
复制算法是建立在标记清除算法的基础上的(即也存在标记和清除的过程)。
标记存活对象,复制对象到存活区,清除其他区域所有对象。
复制算法,既然是复制,就要保证左右两边的容量相等,否则会出现数组越界等情况。
这种算法典型用在年轻代的minor gc上。
基于这种算法,jvm内存 配分成eden,s0和s1,8:1:1的比例。
其中s0和s1的0和1没有任何区别。这样的设计比例较好的保证了大部分对象的产生和一小部分的对象进入存活区。虽然牺牲了1的部分的空间。
new 出来的对象都会在eden中,当eden满了后,触发minor gc,
将存活对象移动到s0,清除eden,当eden第二次满了之后,将存活对象复制到s1,清除eden和s0,以后反复如此。
### a
---
## 2. Jvm
<sub>bid: `00000000000004`</sub>
# Jvm #
---
Java Virtual Machine(Jvm)Java虚拟机
是跨平台的关键因素。
对于Jvm需要了解的有两大模块,一是内存模型,二是垃圾回收机制。
## 内存模型 ##
---
随着Java的版本的变化,内存模型也有一定的变化。
比如Java8后,Metaspace代替了permanent space。
但是内存模型这个抽象概念没有消失,java虚拟机内存通常被划分为以下几个部分。
heap:
stack:
native method stack
程序计数器
## 垃圾回收机制/Garbage collections ##
---
垃圾回收机制包括算法部分和堆内存分配两部分。
heap内存:按照java的对象的存活时间分为以下几个部分。
Young Generation:
Old Generation:
由于Meta Space是使用本地内存,他不算到heap里面。
Eden space:所有的
---
## 3. 2.1运行时数据区域
<sub>bid: `2022050519382600000000000012`</sub>
### 1.程序计数器(Program Counter Register)
---
**线程独有**:用于记录线程的指令位置(内存地址)。
&emsp;如果线程正在执行的是一个java方法,那么程序计数器记录的正在执行的虚拟机字节码指令的地址;如果,正在执行的是本地Native方法,这个计数器的值应该为空(Undefined)。
此内存区域是《Java虚拟机规范》中唯一没有规定OutofMemoryError的区域。
### 2.虚拟机栈(Java Virtual Machine Stack)
---
**线程独有**:是Java方法执行的内存模型。
&emsp;每一个方法被执行的时候,Jvm会为该方法在该线程中创建一个栈帧(Stack Frame),用于存储 **局部变量表**,**操作数栈**,**动态链接**,**方法出口**等信息。
&emsp;一个方法被调用,即为入栈(压栈),一个方法调用结束,即为出栈(弹栈)。不难发现栈是一个先进后出的QUEUE。
局部变量表中存放了编译器可知的基本类型,对象引用,returnAddress类型(指向一条字节码指令的地址)。
&emsp;这些数据类型在局部变量表中的存储空间以局部变量槽(Slot)表示。其中64位的long和double需要两个槽。其余的数据类型只占一个Slot,局部变量表的所需的内存空间在编译期间完成分配,当进入一个方法后,方法需要在栈帧中分配的变量空间是完全确定的。这个“大小”是指的槽的数量。真正一个槽多大空间是虚拟机决定的。
&emsp;虚拟机栈中有两个异常:一个是,StackOverFlowError,栈深度异常。另一个是OutofMemoryError,是可选的(当如果虚拟机栈可以动态扩展,但又申请不到足够内存时,发生,HotSpot虚拟机不允许,动态扩展)。
### 3.本地方法栈
---
**线程独有**:是Java native方法执行的空间区域。
&emsp;本地方法栈和虚拟机的作用是极其相识的,只是本地方法栈只为native method服务。
### 4.Java 堆
---
**线程共享**:是Java对象和数组的存放的主要区域。
&emsp;heap,随着java的技术的进步,所有的对象和数组都分配在堆中的z,已经不是那么绝对了。
但是java垃圾回收器管理的区域就是堆。
由于垃圾回收算法是基于分代类论的,但是随着java的垃圾回收技术的提升,堆的分配已经复杂化了,至少在G1垃圾回收器目前来看。
### 5.方法区
---
《Java虚拟机规范中的》的Non-heap。
线程共享:存储已被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓冲的数据。
其中运行时常量池作
### 6.直接内存
---
&emsp;既不是,运行时数据的一部分,也不是《虚拟机规范》中定义的区域,但这部分内存也会被频繁使用,而且可能导致OutOfMemoryError。
JDK1.4加入了NIO类,引入了一种基于通道(channel)和缓冲区(buffer)的I/O模型,它可以使用native 方法直接分配堆外内存,然后通过Java堆中的DirectByteBuffer对象,作为这块内存的引用来进行操作,从而避免了Java堆和Native堆中的来回复制。
---
## 4. 2.2对象内存
<sub>bid: `2022050620338300000000000015`</sub>
在HotSpot虚拟机里,对象在堆中的存储布局可以划分为三个部分:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)
#### 对象头(Header)
---
对象头部包括两类信息,一类是用来存储对象自身的运行时数据,包括HashCode,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,这里的偏向是指 offset,毕竟引用所指向的对象位置不是一个区域,而是一个点。
这部分数据长度在32/64中的长度为,4个和8个字节,被称为Mark Word。
比如在32位下,对象未被同步锁的情况下。
| 存储内容 | bit | state |
| - | - | - |
| HashCode | 25 | |
| 分代年龄 | 4 | |
| 存储锁标志位 | 2 | |
| 固定为0 | 1 | |
---
## 5. 13.1线程安全与锁优化
<sub>bid: `2022050710179900000000000027`</sub>
## synchronized
既可以用作对象锁也可以用做类锁
## 类锁和对象锁
synchronized 对象锁: 每个对象都有一个monitor,而一个monitor只能被一个线程所拥有,当一个线程a进入monitorenter,monitor的进入数为1,同时,其他的线程就无法获取monitor,如果a再次进入monitorenter,monitor的进入数为2,所以synchronized 是可重入锁。当a monitorexit退出对象锁,则monitor的进入数减少为1,只有monitor的进入数为0时候,即没有任何线程拥有monitor
对象锁
synchronizded method // 直接获取该方法的对象的对象锁
synchronizded(object) { // 获取object的对象锁
}
类锁
static synchronizded method
synchronizded(xxx.class) {
}
-- 类锁和对象锁不会产生竞争,二者的加锁方法不会相互影响
## 锁在哪? biased lock 偏向锁
我们知道java对象有三部分组成
对象头部 object header
实例数据 object data
对齐填充 向2的*n填充
而对象头部由Mark Word和klass pointer组成
前8个字节为Mark Word,后4个字节为klass pointer
其中Mark Word长度为jvm一个word的大小。64位jvm是64bit,即8个字节。
-------------------------------------------------
OFFSET SIZE TYPE DESCRIPTION
0 4 (object header) markword
0 4 (object header) markword
8 4 (object header) klass pointer
-------------------------------------------------
[open jdk document](http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/markOop.hpp)
// 64 bits:
// --------
// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
// size:64 ----------------------------------------------------->| (CMS free block)
//
// unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)
// JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)
// narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
// unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
unused hash unused age biased_lock lock
25 -> 31 -> 1 -> 4 -> 1 -> 2 normal object(sum = 64)
无锁状态下的mark word
Java 对象刚创建时,还没有任何线程来竞争
unused hash unused age biased_lock lock
25 -> 31 -> 1 -> 4 -> 0 -> 01
偏向状态下的mark word
偏向锁是指一段同步代码一直被一同个线程所访问,那么该线程会自动获取锁,降低获取锁的代价
偏向锁在竞争不激烈的情况下,效率非常高。
线程ID epoch unused age biased_lock lock
54 -> 2 -> 1 -> 4 -> 1 -> 01
轻量级锁状态下的mark word
当有两个线程开始竞争这个锁对象,锁会升级为轻量级锁,两个线程公平竞争,哪个线程先占有锁对象,Mark Word 就指向哪个线程的栈帧中的锁记录
锁记录指针 lock
62 -> 00
重量级锁状态的mark word
重量级锁会让其他申请的线程之间进入阻塞,性能降低。
重量级锁也就叫做同步锁,这个锁 对象 Mark Word 再次发生变化,会指向一个监视器(Monitor)对象,该监视器对象用集合的形 式,来登记和管理排队的线程。
monitor对象指针 lock
62 -> 10
## synchronized 的锁优化
JDK1.6开始的减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”。
需要注意的是锁可以升级但不能降级
## 关于 Object 和 Thread
Object 类 有native 的 wait方法
调用wait 前, obtain monitor,
调用wait 后,释放对象锁,然后当前线程进入等待状态wait set 队列中
sleep() 不释放锁,sleep 可以在没有锁的情况下调用,
---
## 6. 12.1Java内存模型和线程
<sub>bid: `2022050920343900000000000005`</sub>
### 概述
---
衡量一个服务性能好坏的,每秒事务处理数(Transactions Per second,TPS ),是重要指标之一。
### 硬件的效率和一致性
---
&emsp;由于计算机的存储效率和计算效率的相差甚大,计算机不得不引入读写速度接近于处理器运算速度的高速缓存(cache),来作为内存和cpu直接的缓冲,但也增加了计算机系统的复杂性,尤其在多核处理器时代,每个处理器都有自己的缓存,而他们又共享同一块内存,这样就导致了一个新的问题:内存一致性。
&emsp;为了解决内存一致性,各个处理器访问缓存时都遵循一些协议,比如MSI,MESI等,而java虚拟机同样有自己的内存模型,并且和上述介绍的硬件和缓存访问操作具有高度的类比性。
&emsp;除了增加高速缓存之外,为了使处理器的运算单元尽量的被充分利用,处理器可能对输入的代码进行乱序执行优化,,处理器会在计算后将乱序执行的结果重组,保证最终结果一致性。
而与处理器的乱序执行优化类似,Java虚拟机的即时编译器中也有指令重排序(Instruction Recorder)优化。
### Java 内存模型
---
主内存和工作内存。
首先要明确一点,很容易混淆的是,虚拟机栈是一个jvm运行时的存储结构,并不是运算。
从更基础的层次来说,主内存直接对应物理硬件的内存,工作内存对应于寄存器和高速缓存。
而工作内存直接存储了被该线程使用的变量的主内存副本,这里的副本,有可能是对象的引用或者,对象的某个字段,但不会有虚拟机把整个java对象复制一次的。
### 内存间的交互操作
---
Java内存模型规定了一些操作来实现内存间交互,JVM会保证它们是原子的
lock:
锁定,把变量标识为线程独占,作用于主内存变量
unlock:
解锁,把锁定的变量释放,别的线程才能使用,作用于主内存变量
read:
读取,把变量从主内存读取到工作内存
load:
载入,把read读取到的值放入工作内存的变量副本中
use:
使用,把工作内存中的一个变量的值传递给执行引擎
assign:
复制,把从执行引擎接收到的值赋给工作内存里面的变量
store:
存储,把工作内存中一个变量的值传递到主内存中
write:
写入,把store进来的数据存放到主内存的变量中
注意,Java内存模型,只要求上述两个操作必须按顺序执行,但没有要求连续执行。也就是说read和load之间store与write之间是可以插入其他的指令的。比如对主内存中a,b变量进行访问时,可能出现,read a,read b,load b,load a。
后来java设计团队,对java内存模型进行了简化,read,write,lock,unlock四种
---
## 7. 12.2关键字volatile
<sub>bid: `2022050921201400000000000006`</sub>
关键字volatile是java虚拟机提供的最轻量级的同步机制。
当一个变量被定义为volatile时,它具备两种特性。
第一种是**可见性**。
即每次get时,强制刷新。
一个误解区,字节码就是原子操作,这是不对的,一个字节码指令在解释执行时,如果是编译执行,一条字节码会有可能被转化为若干个本地机器指令。此处,用-XX:+PrintAssembly参数输出反汇编来分析。
第二种是,**有序性**。
即,禁止指令重排序(Instruction Recorder)优化。
被volatile修饰的变量,赋值后会多执行一个"lock addl"操作,这个操作相当于一个memory barrier(内存屏障),指令重拍时,不能把后面的指令排序到内存屏障前面去,只有一个处理器访问时,不需要内存屏障。
addl 是一个空操作,(把ESP寄存器的值 + 0),这个操作相当于把缓存中的变量做了一次store和write操作。
lock iddl指令把修改同步到内存时,意味着所有的之前的操作都已完成,便形成了指令重排序无法穿越内存屏障的效果。
针对于long和double的类型变量,不通虚拟机是有着不同的实现,此处不做描述。
---
## 8. 12.3 原子性,可见性,有序性
<sub>bid: `2022050921544800000000000007`</sub>
Java内存模型,是围绕着在并发过程中如何处理原子性,可见性,和有序性的这三个特点建立的。
### 原子性(Atomicity)
---
由Java内存模型直接保证的原子性操作有,read,load,assign,use,store,write这6个,我们大致可以认为,对基本类型的访问读写都是原子性的(long double类外)。
尽管,虚拟机没有把lock和unlock操作直接开放给用户,但是却提供了更高层次的字节码指令monitorenter和monitorexit来隐式地这两个操作,反映到同步块就是synchronized关键字,因此synchronzed块之间的操作也属于原子操作。
### 可见性 (Visibility)
---
可见性,即变量的修改对其他线程是可见的,无论是普通变量还是volatile变量都是会将结果刷新到主内存的,只是volatile是其他线程获取该变量时强制刷新到主内存,而普通变量并没有。
除此之外,java还有两个关键字能够实现可见性,即synchronized和final
synchronized的可见性是因为"对一个变量unlock操作之前,必须先把此变量同步回到主内存中(即执行了store,write操作)"的这条规则获得的。
而final的可见性是指,被final修饰的字段在构造器中一旦完成了初始化,并且构造器并没有把这个引用传递出去,那么其他线程就能看见final字段。
### 有序性 (Ordering)
---
Java语言提供了volatile和synchronized两个关键字来保证线程之间的操作是有序性的。
volatile本身就是禁止了指令重排序。
而synchronized是由"一个变量在同一时刻只允许有一条线程对其进行lock操作"
synchronzed能保证以上三个特性,但是并发场景会影响性能。
---
## 9. 12.4 Happens-Before
<sub>bid: `2022050922310000000000000008`</sub>
### 先行发生原则(Happens-Before)
Java内存模型中如果所有的有序性都仅靠volatile和synchronized来完成的话,会有很多操作变得啰嗦。
Java语言有一个先行发生原则(Happens-Before)。
规则:
1.程序次序规则
2.Monitor Lock Rule
3.volatile Variable Rule
4.Thread Start Rule,start方法最先执行
5.Thread Termination Rule,所有方法都优先于
6.线程中断规则。
7.对象终结规则,一个对象初始化完成先行发生于finalize()方法。
8.传递性,A》B,B》C,那么A》C
jintian
1111
---
-475
View File
@@ -1,475 +0,0 @@
# 计算机网路
> 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25
> 分类 ID:`2022050410146100000000000003` · 排序:7 · 文章数:5
## 目录
1. [curl 详解](#curl-详解)
2. [Route](#route)
3. [Tptables概念](#tptables概念)
4. [iptables 规则和ACTION](#iptables-规则和action)
5. [协议](#协议)
---
## 1. curl 详解
<sub>bid: `2023031518364800000000000023`</sub>
### Header
使用 -H 来传递参数
curl -H "tenantId=321" -H "authorization=xxxx:XXxx"
### Method
使用 -X 来指定方法
curl -X GET
### URL
对url 进行添加双引号
curl "www.baidu.com"
### example
#### 1. Get
curl -H "authorization:X:XX" -H "tenantid:sssss" -X GET "localhost:8080/violin-api/api/v1/reminder?reminder_id=xxxxxx"
#### 2. Post
curl -H "Content-Type: application/json" -H "authorization:X:XX" -H "tenantid:sssss" -X POST -d '{"title":"xxxxx","info":"xxxxxxxxxxxxx"}' "localhost:8080/violin-api/api/v1/reminder"
### 使用注意
- powershell 中的curl 只是个alise 不适用
- window下的curl 会出现编码问题,尤其"并不会编码 会导致 后台 出现下列错误
{"error":"invalid character '\\'' looking for beginning of value"}
---
## 2. Route
<sub>bid: `2023032623183000000000000024`</sub>
### 路由表
---
`ip route`
ip route 其实是没有体现网关存在。描述的是网卡和目的ip,源ip之间的关系
默认 经过 10.0.8.1 走默认网卡eth0
意思是说,下面路由要是匹配不到的话,就是经过10.0.8.1 网关(网卡设备eth0)
去 10.0.8.0/22 也走 eth0 网卡,但是源ip是10.0.8.13
如果是去172.17.0.0/16 走 docker0网卡,源ip是172.17.0.1
[root@node2 dev]# ip route
default via 10.0.8.1 dev eth0
10.0.8.0/22 dev eth0 proto kernel scope link src 10.0.8.13
169.254.0.0/16 dev eth0 scope link metric 1002
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
`route -n`
route -n 更多的体现着ip地址的设置问题,
直接可以看到默认的网关gateway是10.0.8.1,通过子网掩码,确定网络地址,访问10.0.8.0的网关是0.0.0.0 即,内部网络,不走网关。
[root@node2 dev]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.8.1 0.0.0.0 UG 0 0 0 eth0
10.0.8.0 0.0.0.0 255.255.252.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
`ip addr`
inet表示主机地址和所处网络段。
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:39:ea:c4 brd ff:ff:ff:ff:ff:ff
inet 10.0.8.13/22 brd 10.0.11.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe39:eac4/64 scope link
valid_lft forever preferred_lft forever
`Flags 标记`
U(route is up)该路由是启动的
H(target is a host)目标是一台主机(ip)
G(use gateway)需要通过外部的主机传送数据包
R(reinstate route for dynamic routing)使用动态路由时恢复路由标记
D(dynamically installed by daemon or redirect)
已经由服务器或转port功能设置为动态路由!
(reject route)这个路由将不会被接受(用来组织不安全的网段)
注:显示路由信息从上到下是从范围大到小。
`ip neigh`
10.0.8.1 这个ip地址对象的网卡是eth0还有mac,但网卡本省绑定的ip地址10.0.8.3,又和ip addr中 link src 10.0.8.3 一样。
这样就说明了一个问题,同一网段的访问,是不通过网关直接走网卡,不同网段,需要走10.0.8.1
[root@node3 ~]# ip neigh
10.0.8.1 dev eth0 lladdr fe:ee:30:30:20:26 REACHABLE
`gateway:指的是路由通过哪个gateway出去`
`Gateway是0.0.0.0或者*表示目标是本主机所属的网络,不需要路由`
### take in actions
---
---
## 3. Tptables概念
<sub>bid: `2023032623302100000000000025`</sub>
### Tptables概念
---
[新手教学](https://www.zsythink.net/archives/1199)
iptables is a package filter firewall for linux system.
iptables cad do below:
- filter package (封包过滤)
- package redirect (封包重定向)
- network address translation (网络地址转换)
to learn iptables, you should to understand the concepts of below:
#### 1. rules
---
- match :符合指定的条件,比如指定的 IP 地址和端口。
- drop :当一个包到达时,简单地丢弃,不做其它任何处理。
- accept:和丢弃相反,接受这个包,让这个包通过。
- reject:和丢弃相似,但它还会向发送这个包的源主机发送错误消息。这个错误消息可以指定,也可以自动产生
- target:指定的动作,说明如何处理一个包,比如:丢弃,接受,或拒绝。
- jump:指定的动作,说明如何处理一个包,比如:丢弃,接受,或拒绝。
- rule:一个或多个匹配及其对应的目标。
#### 2. iptables和netfilter的关系
---
iptables只是Linux防火墙的管理工具而已,位于/sbin/iptables
真正实现防火墙功能的是 netfilter,它是Linux内核中实现包过滤的内部结构。
#### 3. iptables的规则表和链
---
- 表(tables):
iptables内置了4个表,即filter表、nat表、mangle表和raw表。
分别用于实现包过滤,网络地址转换、包重构(修改)和数据跟踪处理。
- 链(chains):
一个有顺序的check list,每一条链中可以有一条或数条规则。
如果满足,系统就会根据该条规则所定义的方法处理该数据包;
否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定义的默认策略来处理数据包。
- 规则表:
1)filter表——三个链:INPUT、FORWARD、OUTPUT
作用:过滤数据包 内核模块:iptables_filter.
2)Nat表——三个链:PREROUTING、POSTROUTING、OUTPUT
作用:用于网络地址转换(IP、端口) 内核模块:iptable_nat
3)Mangle表——五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
作用:修改数据包的服务类型、TTL、并且可以配置路由实现QOS内核模块:iptable_mangle(别看这个表这么麻烦,咱们设置策略时几乎都不会用到它)
4)Raw表——两个链:OUTPUT、PREROUTING
作用:决定数据包是否被状态跟踪机制处理 内核模块:iptable_raw
- 规则链:
1)INPUT——进来的数据包应用此规则链中的策略
2)OUTPUT——外出的数据包应用此规则链中的策略
3)FORWARD——转发数据包时应用此规则链中的策略
4)PREROUTING——对数据包作路由选择前应用此链中的规则
(记住!所有的数据包进来的时侯都先由这个链处理)
5)POSTROUTING——对数据包作路由选择后应用此链中的规则
(所有的数据包出来的时侯都先由这个链处理)
---
### command
[参照](http://t.zoukankan.com/sixloop-p-iptables-save-help.html)
[命令参照](https://zhuanlan.zhihu.com/p/160840906)
iptables --help 也能看到,先列出一些常用的.
-A --append
Append to chain
-m --match match
extended match (may load extension)
-s --source address[/mask][...]
source specification
-d --destination -d address[/mask][...]
destination specification
-j --jump -j target
target for rule (may load target extension)
-p --protocol -p proto
protocol: by number or name, eg. 'tcp'
-N --new -N chain
Create a new user-defined chain
-t --table -t table
table to manipulate (default: `filter')
-i --in-interface -i [!] input name[+]
network interface name ([+] for wildcard)
-o --out-interface -o [!] output name[+]
network interface name ([+] for wildcard)
### 一些memo
---
[新手教学](https://www.zsythink.net/archives/1199)
1. 通常我们只关系nat表和filter表
`raw -> mangle -> nat -> filter`
2. 创建 chain 时候,如果不指定-t table,默认是filter表
3. ! 表示 取非
`-p ! tcp 表示不是tcp的`
4. iptables -h 中的[!]表示支持 非 规则
`[!] --protocol -p proto protocol: by number or name, eg. tcp`
5. -i -o 是匹配网卡
6. iptables -m comment 模块
`iptables -m comment --comment "xxx"`
就是对该chain进行解释。其中comment是扩展模块,常见的模块有addrtype 模块了。
`iptables -m addrtype --dst-type LOCAL -j DOCKER`
`iptables -m addrtype --help 可以看更详细解说`
addrtype表示对报文的地址类型进行匹配,-dst-type 表示destination
LOCAL:表示地址是本地地址,指本地一切地址含:127.0.0.1回环地址
7. -j DNAT 和 -j SNAT
8.
---
## 4. iptables 规则和ACTION
<sub>bid: `2023032623358600000000000026`</sub>
### 规则查询
---
`iptables -t filter -L`
`iptables -nvL INPUT`
[root@node3 ~]# iptables -nvL INPUT
# policy 表示默认规则
Chain INPUT (policy ACCEPT 344K packets, 31M bytes)
pkts bytes target prot opt in out source destination
0 0 in_test tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8000
1741K 187M KUBE-FIREWALL all -- * * 0.0.0.0/0 0.0.0.0/0
### 规则管理
---
`iptables -F INPUT`
# 清空filter表的INPUT链
iptables -F INPUT
# 添加拒绝INPUT规则
# -I 表示链首插入规则,-A 表示链尾添加规则
# 来自49.233.4.79 的 丢弃
iptables -t filter -I INPUT -s 49.233.4.79 -j DROP
# 所以就算添加了下面的ACCEPT规则,也是ping不同的,因为在链首已经被丢弃
iptables -t filter -A INPUT -s 49.233.4.79 -j ACCEPT
# 如果我再把这个规则添加到链首,就可以ping通了。
iptables -t filter -I INPUT -s 49.233.4.79 -j ACCEPT
[root@node3 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 451 packets, 45257 bytes)
pkts bytes target prot opt in out source destination
2 168 ACCEPT all -- * * 49.233.4.79 0.0.0.0/0
5 420 DROP all -- * * 49.233.4.79 0.0.0.0/0
0 0 ACCEPT all -- * * 49.233.4.79 0.0.0.0/0
### 删除规则
---
# 指定编号删除 -D INPUT 3 ,删除INPUT 链中,编号为3的规则
# 先查看规则编号 使用--line
iptables -nvL INPUT --line
iptables -t filter -D INPUT 3
# 根据匹配条件删除
iptables -t filter -D INPUT -s 49.233.4.79 -j ACCEPT
# 整体删除
iptables -t filter -F
### 修改规则
---
# 使用-R 指定链,使用数字 来指定 具有相同数字编号的规则
iptables -t filter -R INPUT 1 -s 49.233.4.79 -j REJECT
# 可以看到 REJECT是拒绝行为
[root@node1 tomcat]# ping 43.138.73.106
PING 43.138.73.106 (43.138.73.106) 56(84) bytes of data.
From 43.138.73.106 icmp_seq=1 Destination Port Unreachable
From 43.138.73.106 icmp_seq=2 Destination Port Unreachable
### 保存规则
---
service iptables save
### 匹配规则
---
1. 如果匹配不到任何规则,那么就匹配默认规则(policy)。
# 小误区,关于! 的用法理解,
iptable -t filter -F
# 不是 49.233.4.79 的都接受,但是并没有说是49.233.4.79的拒绝
# 只是说49.233.4.79的没有匹配到这个规则,因为INPUT 默认都是 ACCEPT
# 所以,49.233.4.79的也会通过
iptables -t filter -A INPUT 1 -s !49.233.4.79 -j ACCEPT
# -s -d 如果不指定,即0.0.0.0/0 即所有ip
# 多个条件是 and 关系,必须都符合
2. 匹配条件:协议类型
# 使用-p选项,指定需要匹配的报文的协议类型
# 比如我们拒绝tcp协议
iptables -t filter -F
iptables -t filter -I INPUT -s 49.233.4.79 -p tcp -j REJECT
# 这样我们ping 是可以ping通的,因为ping是icmp协议
# 而curl 43.138.73.106 是被拒绝的,因为是http(tcp)协议
# centos7中 支持以下协议
# tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh
# 不指定协议,即 -p all 任意匹配
3. 匹配条件:网卡接口
# -i -o
# -i 表示来自哪个网卡
# PREROUTING 和 INPUT FORWARD 使用
# -o 表示要去哪个网卡
# POSTROUTING 和 OUTPUT FORWARD 使用
4. -m match 扩展匹配
# 如果想要使用扩展匹配条件,则需要依赖一些扩展模块
# 即扩展匹配,需要使用-m来指定模块
iptables -A INPUT -s 49.233.4.79 -p tcp -m tcp --dport 80 -j REJECT
[root@node3 ~]# iptables -nvL INPUT --line
Chain INPUT (policy ACCEPT 14 packets, 964 bytes)
num pkts bytes target prot opt in out source destination
1 2 120 REJECT tcp -- * * 49.233.4.79 0.0.0.0/0 reject-with icmp-port-unreachable
2 0 0 REJECT tcp -- * * 49.233.4.79 0.0.0.0/0 tcp dpt:80 reject-with icmp-port-unreachable
# 可以看出 上面是使用-m tcp 使用tcp扩展模块
# 如果-p tcp 和 -m tcp 是一样的时候,-m tcp是可以省略的
# --sport 表示源端口号
# –dport 22:25 表示22,23,24,25 范围
# :22 和 80: 表示 0:22 80:65535
# 多个离散端口使用 multiport 模块
-m multiport –dports 22,36,80
5. -m iprange 扩展模块
使用iprange扩展模块可以指定”一段连续的IP地址范围”,用于匹配报文的源地址或者目标地址
# --src-range --dst-range
-m iprange --src-range 192.168.1.127-192.168.1.146
6. -m conntrack 扩展模块
conntrack 状态跟踪
conntrack共可以为连接标记五种状态:
NEW,ESTABLISHED,RELATED,INVALID,UNTRACKED
### 自定义链
---
自定义链并不能直接使用,而是需要被默认链引用才能够使
# 自定义链IN-WEB
iptables -F INPUT
iptables -N IN-WEB
# 可以看到,自定义链没有被任何默认的链引用,即无效状态。
Chain IN-WEB (0 references)
pkts bytes target prot opt in out source destination
删除 -X 自定义链,但是删除前必须要清空链上的规则
iptables -F IN-WEB
iptables -X IN-WEB
### ACTION
---
我们知道-j target ,target既可以接ACTION,也可以接Chain
我们已知的ACTION有 ACCEPT,DROP,REJECT
`ACCPET`
ACCEPT 将封包放行,进行完此处理动作后,将不再比对其它规则,直接跳往下一个规则炼。
`MARK`
MARK 将封包标上某个代号,以便提供作为后续过滤的条件判断依据,进行完此处理动作后,将会继续比对其它规则
`RETURN`
结束在目前规则炼中的过滤程序,返回主规则炼继续过滤.
如果把自定义规则炼看成是一个子程序,那么这个动作,就相当于提早结束子程序并返回到主程序中。
`SNAT`
改写封包来源 IP 为某特定 IP 或 IP 范围,可以指定 port 对应的范围,进行完此处理动作后
将直接跳往下一个规则炼(mangle:postrouting)。范例如下:
iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000
`DNAT`
DNAT 改写封包目的地 IP 为某特定 IP 或 IP 范围,可以指定 port 对应的范围,进行完此处理动作后,
将会直接跳往下一个规则炼(filter:input 或 filter:forward)。范例如下:
iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10:80-100
`REJECT`
拦阻该封包,并传送封包通知对方
`DROP`
丢弃封包不予处理,进行完此处理动作后,将不再比对其它规则,直接中断过滤程序
`REDIRECT`
...
`MASQUERADE`
...
`NAT这个概念:`
NAT是Network Address Translation的缩写,译为”网络地址转换”,NAT说白了就是修改报文的IP地址
-j SNAT --to-source xxx.xxx.xxx.x
-j DNAT --to-destination xxx.xx
### 关于链的顺序
---
- nat 表中的规则可以被哪些链使用:PREROUTING,OUTPUT,POSTROUTING(centos7中还有INPUT,centos6中没有)
- filter 表中的规则可以被哪些链使用:INPUT,FORWARD,OUTPUT
raw 和 mangle不去考虑的话
表的顺序是 nat -> filter
1. 当一个数据包进入网卡时,它首先进入PREROUTING链
nat -> PREROUTING
2.1 如果数据包就是进入本机的
nat -> INPUT
filter -> INPUT
nat -> OUTPUT
filter -> OUTPUT
2.2 如果数据包是需要转发的
filter -> FORWARD
3. 最后进入POSTROUTING
nat -> POSTROUTING
1
2
---
## 5. 协议
<sub>bid: `2023032623438200000000000027`</sub>
## 协议
传输层TCP -
网路层协议IP - 报文
数据链路层协议MAC - 帧
---
### ARP协议
---
[ARP](https://blog.csdn.net/weixin_39761696/article/details/110578444)
ADDRESS Resolution protocol 是一个通过第三层IP地址,找到第二层MAC的协议。
OSI模型把网络运营分成七层,IP地址在OSI模型的第三层,MAC地址在第二层,彼此之间不立即相处。在根据以太网接口推送IP数据时,必须先封装形式第三层(32位IP地址)、再封装第二层(48位MAC地址)的报头,但因为推送时只了解总体目标IP地址,不清楚其MAC地址,又不可以跨第二、三层,因此必须应用地址解析协义。
---