40分钟学 Go 语言高并发:负载均衡与服务治理
负载均衡与服务治理
一、知识要点总览
模块 | 核心内容 | 技术实现 | 难度 |
---|---|---|---|
负载策略 | 轮询、权重、最小连接数 | 自定义负载均衡器 | 中 |
服务降级 | 服务降级、熔断降级、限流降级 | Hystrix模式 | 高 |
熔断机制 | 熔断器状态机、失败计数、自动恢复 | Circuit Breaker | 高 |
限流设计 | 令牌桶、滑动窗口、计数器 | Rate Limiter | 中 |
让我们开始具体实现:
1. 负载均衡实现
// loadbalancer/balancer.go
package loadbalancerimport ("sync""sync/atomic""time"
)// 服务实例
type Instance struct {ID stringHost stringPort intWeight intActive boolLastActive time.TimeConnections int64 // 当前连接数FailCount int64 // 失败计数
}// 负载均衡器接口
type LoadBalancer interface {Select() (*Instance, error)UpdateInstances(instances []*Instance)MarkSuccess(instance *Instance)MarkFailed(instance *Instance)
}// 轮询负载均衡器
type RoundRobinBalancer struct {instances []*Instancecounter uint64mu sync.RWMutex
}func NewRoundRobinBalancer() *RoundRobinBalancer {return &RoundRobinBalancer{instances: make([]*Instance, 0),}
}func (b *RoundRobinBalancer) Select() (*Instance, error) {b.mu.RLock()defer b.mu.RUnlock()if len(b.instances) == 0 {return nil, ErrNoAvailableInstances}// 获取当前计数count := atomic.AddUint64(&b.counter, 1)index := int(count % uint64(len(b.instances)))return b.instances[index], nil
}// 加权轮询负载均衡器
type WeightedRoundRobinBalancer struct {instances []*Instanceweights []intcurrentWeight intmu sync.RWMutex
}func NewWeightedRoundRobinBalancer() *WeightedRoundRobinBalancer {return &WeightedRoundRobinBalancer{instances: make([]*Instance, 0),weights: make([]int, 0),}
}func (b *WeightedRoundRobinBalancer) Select() (*Instance, error) {b.mu.Lock()defer b.mu.Unlock()if len(b.instances) == 0 {return nil, ErrNoAvailableInstances}totalWeight := 0var best *InstancebestWeight := -1for i, instance := range b.instances {if !instance.Active {continue}b.weights[i] += instance.WeighttotalWeight += instance.Weightif bestWeight < b.weights[i] {bestWeight = b.weights[i]best = instance}}if best == nil {return nil, ErrNoAvailableInstances}for i := range b.weights {b.weights[i] -= totalWeight}return best, nil
}// 最小连接数负载均衡器
type LeastConnectionBalancer struct {instances []*Instancemu sync.RWMutex
}func NewLeastConnectionBalancer() *LeastConnectionBalancer {return &LeastConnectionBalancer{instances: make([]*Instance, 0),}
}func (b *LeastConnectionBalancer) Select() (*Instance, error) {b.mu.RLock()defer b.mu.RUnlock()if len(b.instances) == 0 {return nil, ErrNoAvailableInstances}var best *InstanceminConn := int64(^uint64(0) >> 1) // 最大int64值for _, instance := range b.instances {if !instance.Active {continue}connections := atomic.LoadInt64(&instance.Connections)if connections < minConn {minConn = connectionsbest = instance}}if best == nil {return nil, ErrNoAvailableInstances}// 增加连接数atomic.AddInt64(&best.Connections, 1)return best, nil
}// 更新实例列表
func (b *LeastConnectionBalancer) UpdateInstances(instances []*Instance) {b.mu.Lock()defer b.mu.Unlock()b.instances = instances
}// 标记请求成功
func (b *LeastConnectionBalancer) MarkSuccess(instance *Instance) {atomic.AddInt64(&instance.Connections, -1)atomic.StoreInt64(&instance.FailCount, 0)instance.LastActive = time.Now()
}// 标记请求失败
func (b *LeastConnectionBalancer) MarkFailed(instance *Instance) {atomic.AddInt64(&instance.Connections, -1)failCount := atomic.AddInt64(&instance.FailCount, 1)// 如果失败次数过多,标记为不可用if failCount >= 3 {instance.Active = false}
}
2. 服务降级实现
// degradation/degradation.go
package degradationimport ("context""sync""time"
)type DegradationLevel intconst (NoDegradation DegradationLevel = iotaPartialDegradationFullDegradation
)type DegradationRule struct {Name stringThreshold float64TimeWindow time.DurationLevel DegradationLevelRecoveryTime time.Duration
}type DegradationManager struct {rules map[string]*DegradationRulestates map[string]*DegradationStatemu sync.RWMutex
}type DegradationState struct {Level DegradationLevelStartTime time.TimeEndTime time.TimeMetrics map[string]float64
}func NewDegradationManager() *DegradationManager {return &DegradationManager{rules: make(map[string]*DegradationRule),states: make(map[string]*DegradationState),}
}func (m *DegradationManager) AddRule(rule *DegradationRule) {m.mu.Lock()defer m.mu.Unlock()m.rules[rule.Name] = rule
}func (m *DegradationManager) CheckDegradation(ctx context.Context, name string, value float64) DegradationLevel {m.mu.Lock()defer m.mu.Unlock()rule, exists := m.rules[name]if !exists {return NoDegradation}state, exists := m.states[name]if !exists {state = &DegradationState{Level: NoDegradation,Metrics: make(map[string]float64),}m.states[name] = state}// 更新指标state.Metrics["value"] = value// 如果当前处于降级状态,检查是否可以恢复if state.Level != NoDegradation {if time.Now().After(state.EndTime) {state.Level = NoDegradationstate.StartTime = time.Time{}state.EndTime = time.Time{}} else {return state.Level}}// 检查是否需要降级if value > rule.Threshold {state.Level = rule.Levelstate.StartTime = time.Now()state.EndTime = state.StartTime.Add(rule.RecoveryTime)return rule.Level}return NoDegradation
}// 降级处理器
type DegradationHandler struct {normal func(context.Context) (interface{}, error)degraded func(context.Context) (interface{}, error)fallback func(context.Context) (interface{}, error)
}func NewDegradationHandler(normal func(context.Context) (interface{}, error),degraded func(context.Context) (interface{}, error),fallback func(context.Context) (interface{}, error),
) *DegradationHandler {return &DegradationHandler{normal: normal,degraded: degraded,fallback: fallback,}
}func (h *DegradationHandler) Handle(ctx context.Context, level DegradationLevel) (interface{}, error) {switch level {case NoDegradation:return h.normal(ctx)case PartialDegradation:if h.degraded != nil {return h.degraded(ctx)}fallthroughcase FullDegradation:if h.fallback != nil {return h.fallback(ctx)}return nil, ErrServiceDegradeddefault:return h.normal(ctx)}
}
3. 熔断器实现
// circuitbreaker/breaker.go
package circuitbreakerimport ("context""sync""time"
)type State intconst (StateClosed State = iota // 关闭状态(正常运行)StateOpen // 打开状态(熔断)StateHalfOpen // 半开状态(尝试恢复)
)type Settings struct {Name stringMaxRequests uint32 // 熔断前的最大请求数Interval time.Duration // 统计时间窗口Timeout time.Duration // 熔断恢复时间Threshold float64 // 错误率阈值
}type CircuitBreaker struct {name stringstate Statesettings Settingscounts CountslastStateTime time.Timemu sync.RWMutex
}type Counts struct {Requests uint32TotalFailures uint32ConsecutiveFailures uint32LastFailureTime time.Time
}func NewCircuitBreaker(settings Settings) *CircuitBreaker {return &CircuitBreaker{name: settings.Name,state: StateClosed,settings: settings,lastStateTime: time.Now(),}
}func (cb *CircuitBreaker) Execute(ctx context.Context, run func() (interface{}, error)) (interface{}, error) {state := cb.GetState()switch state {case StateOpen:if !cb.shouldAttemptReset() {return nil, ErrCircuitBreakerOpen}cb.setState(StateHalfOpen)return cb.executeAndUpdateState(ctx, run)case StateHalfOpen:return cb.executeAndUpdateState(ctx, run)default: // StateClosedreturn cb.executeAndUpdateState(ctx, run)}
}func (cb *CircuitBreaker) executeAndUpdateState(ctx context.Context, run func() (interface{}, error)) (interface{}, error) {defer func() {if r := recover(); r != nil {cb.recordFailure()}}()result, err := run()if err != nil {cb.recordFailure()return nil, err}cb.recordSuccess()return result, nil
}func (cb *CircuitBreaker) recordSuccess() {cb.mu.Lock()defer cb.mu.Unlock()cb.counts.Requests++cb.counts.ConsecutiveFailures = 0if cb.state == StateHalfOpen {cb.setState(StateClosed)}
}func (cb *CircuitBreaker) recordFailure() {cb.mu.Lock()defer cb.mu.Unlock()cb.counts.Requests++cb.counts.TotalFailures++cb.counts.ConsecutiveFailures++cb.counts.LastFailureTime = time.Now()if cb.shouldTrip() {cb.setState(StateOpen)}
}func (cb *CircuitBreaker) shouldTrip() bool {if cb.counts.ConsecutiveFailures >= cb.settings.MaxRequests {return true}if cb.counts.Requests >= cb.settings.MaxRequests {failureRate := float64(cb.counts.TotalFailures) / float64(cb.counts.Requests)if failureRate >= cb.settings.Threshold {return true}}return false
}func (cb *CircuitBreaker) shouldAttemptReset() bool {return time.Since(cb.lastStateTime) >= cb.settings.Timeout
}func (cb *CircuitBreaker) GetState() State {cb.mu.RLock()defer cb.mu.RUnlock()now := time.Now()// 清理过期的计数if now.Sub(cb.lastStateTime) >= cb.settings.Interval {cb.mu.RUnlock()cb.mu.Lock()cb.counts = Counts{}cb.lastStateTime = nowstate := cb.statecb.mu.Unlock()cb.mu.RLock()return state}return cb.state
}func (cb *CircuitBreaker) setState(state State) {cb.state = statecb.lastStateTime = time.Now()if state == StateClosed {cb.counts = Counts{}}
}// 监控指标
type Metrics struct {State StateRequests uint32TotalFailures uint32ConsecutiveFailures uint32FailureRate float64LastFailureTime time.Time
}func (cb *CircuitBreaker) Metrics() Metrics {cb.mu.RLock()defer cb.mu.RUnlock()var failureRate float64if cb.counts.Requests > 0 {failureRate = float64(cb.counts.TotalFailures) / float64(cb.counts.Requests)}return Metrics{State: cb.state,Requests: cb.counts.Requests,TotalFailures: cb.counts.TotalFailures,ConsecutiveFailures: cb.counts.ConsecutiveFailures,FailureRate: failureRate,LastFailureTime: cb.counts.LastFailureTime,}
}// 熔断器管理器
type BreakerManager struct {breakers map[string]*CircuitBreakermu sync.RWMutex
}func NewBreakerManager() *BreakerManager {return &BreakerManager{breakers: make(map[string]*CircuitBreaker),}
}func (m *BreakerManager) GetBreaker(name string) (*CircuitBreaker, bool) {m.mu.RLock()defer m.mu.RUnlock()breaker, exists := m.breakers[name]return breaker, exists
}func (m *BreakerManager) AddBreaker(settings Settings) *CircuitBreaker {m.mu.Lock()defer m.mu.Unlock()breaker := NewCircuitBreaker(settings)m.breakers[settings.Name] = breakerreturn breaker
}// 自定义熔断策略
type TripStrategy interface {ShouldTrip(counts Counts) bool
}// 连续失败策略
type ConsecutiveFailuresStrategy struct {Threshold uint32
}func (s *ConsecutiveFailuresStrategy) ShouldTrip(counts Counts) bool {return counts.ConsecutiveFailures >= s.Threshold
}// 错误率策略
type ErrorRateStrategy struct {Threshold float64MinRequests uint32
}func (s *ErrorRateStrategy) ShouldTrip(counts Counts) bool {if counts.Requests < s.MinRequests {return false}failureRate := float64(counts.TotalFailures) / float64(counts.Requests)return failureRate >= s.Threshold
}
4. 限流器实现
// ratelimit/limiter.go
package ratelimitimport ("context""sync""time"
)// 令牌桶限流器
type TokenBucket struct {rate float64 // 令牌产生速率capacity float64 // 桶容量tokens float64 // 当前令牌数lastUpdate time.Time // 上次更新时间mu sync.Mutex
}func NewTokenBucket(rate float64, capacity float64) *TokenBucket {return &TokenBucket{rate: rate,capacity: capacity,tokens: capacity,lastUpdate: time.Now(),}
}func (tb *TokenBucket) Allow() bool {return tb.AllowN(1)
}func (tb *TokenBucket) AllowN(n float64) bool {tb.mu.Lock()defer tb.mu.Unlock()now := time.Now()// 计算从上次更新到现在产生的令牌数elapsed := now.Sub(tb.lastUpdate).Seconds()tb.tokens = min(tb.capacity, tb.tokens+elapsed*tb.rate)tb.lastUpdate = nowif tb.tokens < n {return false}tb.tokens -= nreturn true
}// 滑动窗口限流器
type SlidingWindow struct {capacity int // 窗口容量timeWindow time.Duration // 时间窗口大小windows map[int64]int // 各个小窗口的请求数mu sync.Mutex
}func NewSlidingWindow(capacity int, timeWindow time.Duration) *SlidingWindow {return &SlidingWindow{capacity: capacity,timeWindow: timeWindow,windows: make(map[int64]int),}
}func (sw *SlidingWindow) Allow() bool {sw.mu.Lock()defer sw.mu.Unlock()now := time.Now().UnixNano()windowStart := now - sw.timeWindow.Nanoseconds()// 清理过期的窗口for timestamp := range sw.windows {if timestamp < windowStart {delete(sw.windows, timestamp)}}// 计算当前请求数var total intfor _, count := range sw.windows {total += count}if total >= sw.capacity {return false}// 记录新请求currentWindow := now / int64(time.Second)sw.windows[currentWindow]++return true
}// 漏桶限流器
type LeakyBucket struct {rate float64 // 漏出速率capacity float64 // 桶容量water float64 // 当前水量lastLeakTime time.Time // 上次漏水时间mu sync.Mutex
}func NewLeakyBucket(rate float64, capacity float64) *LeakyBucket {return &LeakyBucket{rate: rate,capacity: capacity,lastLeakTime: time.Now(),}
}func (lb *LeakyBucket) Allow() bool {lb.mu.Lock()defer lb.mu.Unlock()now := time.Now()// 计算从上次漏水到现在漏掉的水量elapsed := now.Sub(lb.lastLeakTime).Seconds()lb.water = max(0, lb.water-elapsed*lb.rate)lb.lastLeakTime = nowif lb.water >= lb.capacity {return false}lb.water++return true
}// 分布式限流器(基于Redis)
type DistributedRateLimiter struct {redis RedisClientkey stringrate intwindow time.Duration
}type RedisClient interface {Eval(script string, keys []string, args ...interface{}) (interface{}, error)
}func NewDistributedRateLimiter(redis RedisClient, key string, rate int, window time.Duration) *DistributedRateLimiter {return &DistributedRateLimiter{redis: redis,key: key,rate: rate,window: window,}
}const limitScript = `
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = tonumber(redis.call('get', key) or "0")
if current >= limit thenreturn 0
end
redis.call('incr', key)
redis.call('expire', key, window)
return 1
`func (rl *DistributedRateLimiter) Allow(ctx context.Context) bool {result, err := rl.redis.Eval(limitScript,[]string{rl.key},rl.rate,int(rl.window.Seconds()),)if err != nil {return false}return result.(int64) == 1
}func min(a, b float64) float64 {if a < b {return a}return b
}func max(a, b float64) float64 {if a > b {return a}return b
}
5. 系统流程图
让我们通过一个流程图来展示整个系统的工作流程:
6. 使用示例
让我们看一个完整的使用示例:
// main.go
package mainimport ("context""log""net/http""time"
)func main() {// 初始化限流器rateLimiter := ratelimit.NewTokenBucket(100, 1000) // 每秒100个请求,最多积攒1000个令牌// 初始化熔断器breaker := circuitbreaker.NewCircuitBreaker(circuitbreaker.Settings{Name: "example-service",MaxRequests: 100,Interval: time.Minute,Timeout: time.Minute * 5,Threshold: 0.5, // 50%错误率触发熔断})// 初始化负载均衡器balancer := loadbalancer.NewWeightedRoundRobinBalancer()balancer.UpdateInstances([]*loadbalancer.Instance{{ID: "server1", Host: "localhost", Port: 8081, Weight: 2},{ID: "server2", Host: "localhost", Port: 8082, Weight: 1},{ID: "server3", Host: "localhost", Port: 8083, Weight: 1},})// 初始化服务降级管理器degradation := degradation.NewDegradationManager()degradation.AddRule(°radation.DegradationRule{Name: "high-load",Threshold: 0.8, // CPU使用率超过80%触发降级TimeWindow: time.Minute,Level: degradation.PartialDegradation,RecoveryTime: time.Minute * 5,})// HTTP处理器http.HandleFunc("/api/example", func(w http.ResponseWriter, r *http.Request) {// 限流检查if !rateLimiter.Allow() {http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)return}// 获取降级状态degradationLevel := degradation.CheckDegradation(r.Context(), "high-load", getCPUUsage())// 处理降级情况handler := degradation.NewDegradationHandler(// 正常处理func(ctx context.Context) (interface{}, error) {return breaker.Execute(ctx, func() (interface{}, error) {// 选择服务实例instance, err := balancer.Select()if err != nil {return nil, err}// 调用服务resp, err := callService(instance)if err != nil {// 标记失败balancer.MarkFailed(instance)return nil, err}// 标记成功balancer.MarkSuccess(instance)return resp, nil})},// 部分降级处理func(ctx context.Context) (interface{}, error) {// 返回缓存数据return getFromCache(ctx)},// 完全降级处理func(ctx context.Context) (interface{}, error) {// 返回降级默认值return getDefaultResponse(ctx)},)// 执行请求处理result, err := handler.Handle(r.Context(), degradationLevel)if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}// 返回结果w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(result)})// 监控处理器http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {metrics := map[string]interface{}{"circuit_breaker": breaker.Metrics(),"rate_limiter": map[string]interface{}{"qps": rateLimiter.QPS(),"total_requests": rateLimiter.TotalRequests(),},"load_balancer": balancer.Metrics(),}w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(metrics)})// 启动服务器log.Fatal(http.ListenAndServe(":8080", nil))
}// 辅助函数
func callService(instance *loadbalancer.Instance) (interface{}, error) {url := fmt.Sprintf("http://%s:%d/api", instance.Host, instance.Port)ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)defer cancel()req, err := http.NewRequestWithContext(ctx, "GET", url, nil)if err != nil {return nil, err}resp, err := http.DefaultClient.Do(req)if err != nil {return nil, err}defer resp.Body.Close()if resp.StatusCode != http.StatusOK {return nil, fmt.Errorf("service returned status: %d", resp.StatusCode)}var result interface{}if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {return nil, err}return result, nil
}func getFromCache(ctx context.Context) (interface{}, error) {// 实现缓存读取逻辑cache := redis.NewClient(&redis.Options{Addr: "localhost:6379",})defer cache.Close()value, err := cache.Get(ctx, "cache_key").Result()if err != nil {return nil, err}var result interface{}if err := json.Unmarshal([]byte(value), &result); err != nil {return nil, err}return result, nil
}func getDefaultResponse(ctx context.Context) (interface{}, error) {// 返回降级默认响应return map[string]interface{}{"status": "degraded","data": map[string]interface{}{"message": "Service is temporarily degraded","fallback_data": []string{"default", "response", "data"},},}, nil
}func getCPUUsage() float64 {var status syscall.Statfs_tif err := syscall.Statfs("/", &status); err != nil {return 0}// 获取CPU使用率percent, err := cpu.Percent(time.Second, false)if err != nil {return 0}if len(percent) > 0 {return percent[0]}return 0
}// 配置项
type Config struct {RateLimit struct {QPS float64 `yaml:"qps"`Capacity float64 `yaml:"capacity"`} `yaml:"rate_limit"`CircuitBreaker struct {MaxRequests uint32 `yaml:"max_requests"`Interval time.Duration `yaml:"interval"`Timeout time.Duration `yaml:"timeout"`Threshold float64 `yaml:"threshold"`} `yaml:"circuit_breaker"`LoadBalancer struct {Instances []struct {ID string `yaml:"id"`Host string `yaml:"host"`Port int `yaml:"port"`Weight int `yaml:"weight"`} `yaml:"instances"`} `yaml:"load_balancer"`Degradation struct {Rules []struct {Name string `yaml:"name"`Threshold float64 `yaml:"threshold"`TimeWindow time.Duration `yaml:"time_window"`Level string `yaml:"level"`RecoveryTime time.Duration `yaml:"recovery_time"`} `yaml:"rules"`} `yaml:"degradation"`
}func loadConfig(filename string) (*Config, error) {data, err := ioutil.ReadFile(filename)if err != nil {return nil, err}var config Configif err := yaml.Unmarshal(data, &config); err != nil {return nil, err}return &config, nil
}
让我们继续完成使用示例的实现:
7. 配置示例
让我们看一个配置文件的示例:
# config.yaml
rate_limit:qps: 100capacity: 1000circuit_breaker:max_requests: 100interval: 60stimeout: 300sthreshold: 0.5load_balancer:instances:- id: server1host: localhostport: 8081weight: 2- id: server2host: localhostport: 8082weight: 1- id: server3host: localhostport: 8083weight: 1degradation:rules:- name: high-loadthreshold: 0.8time_window: 60slevel: partialrecovery_time: 300s- name: error-ratethreshold: 0.3time_window: 60slevel: fullrecovery_time: 300s
8. 关键功能说明
-
负载均衡:
- 轮询策略
- 加权轮询
- 最小连接数
- 实例健康检查
- 动态更新实例列表
-
服务降级:
- 多级降级策略
- 基于指标的降级
- 自动恢复机制
- 降级处理器
-
熔断机制:
- 状态管理
- 失败计数
- 自动恢复
- 半开状态试探
-
限流设计:
- 令牌桶算法
- 滑动窗口
- 漏桶算法
- 分布式限流
这个完整的服务治理系统提供了:
- 全面的服务保护机制
- 灵活的配置选项
- 可扩展的设计
- 完整的监控指标
- 多种降级策略
- 分布式支持
怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!
相关文章:
40分钟学 Go 语言高并发:负载均衡与服务治理
负载均衡与服务治理 一、知识要点总览 模块核心内容技术实现难度负载策略轮询、权重、最小连接数自定义负载均衡器中服务降级服务降级、熔断降级、限流降级Hystrix模式高熔断机制熔断器状态机、失败计数、自动恢复Circuit Breaker高限流设计令牌桶、滑动窗口、计数器Rate Lim…...
Python 从入门到实战45(Pandas数据操作)
我们的目标是:通过这一套资料学习下来,可以熟练掌握python基础,然后结合经典实例、实践相结合,使我们完全掌握python,并做到独立完成项目开发的能力。 上篇文章我们学习了pandas数据读写的相关基础知识。今天学习一下…...
node js 历史版本下载
此为node历史版本下载地址 https://nodejs.org/dist/https://nodejs.org/dist/...
无代码探索AI大模型:腾讯云函数计算的卓越实践
在数字化转型的浪潮中,人工智能(AI)技术已经成为企业提升竞争力的关键。然而,对于许多业务人员来说,技术门槛高、开发周期长等问题限制了他们快速探索和应用AI大模型的能力。同时,对于缺乏GPU资源的开发者来…...
网页数据抓取:融合BeautifulSoup和Scrapy的高级爬虫技术
网页数据抓取:融合BeautifulSoup和Scrapy的高级爬虫技术 在当今的大数据时代,网络爬虫技术已经成为获取信息的重要手段之一。Python凭借其强大的库支持,成为了进行网页数据抓取的首选语言。在众多的爬虫库中,BeautifulSoup和Scra…...
vivado中,generate output product 和Create HDL wrapper的作用
generate output product 以zynq的ip核举例,没有generate output product之前,在ip source 什么也看不到。 但是同样的一个ip核,generate output product之后,会生成综合,布线和仿真文件,约束文件等等。 …...
欧盟R156法规注意事项及实例展示
欧盟 R156 法规即《关于批准车辆的软件升级和软件升级管理体系统一规定的法规》,其注意事项及实例如下: 注意事项: 软件升级管理体系方面: 体系建立与维持:汽车制造商和供应商必须建立完善的软件升级管理体系ÿ…...
HTML语义化的案例分析
HTML语义化的案例分析:对比实际网站中语义化与非语义化标签的差异 在现代Web开发中,HTML语义化被广泛认为是提升网页结构和可访问性的重要做法。HTML语义化不仅仅是为了让代码更清晰,更是为了增强搜索引擎优化(SEO)&a…...
使用 pyperclip 进行跨平台剪贴板操作
简介:pyperclip 是一个轻量级的 Python 库,支持在不同操作系统(Windows、macOS、Linux)中进行剪贴板的复制和粘贴。这个库的设计简单易用,非常适合需要频繁进行文本复制粘贴操作的场景。 历史攻略: 使用f…...
微信小程序报错:http://159.75.169.224:7300不在以下 request 合法域名列表中,请参考文档
要解决此问题,需打开微信小程序开发者工具进行设置,打开详情-本地设置重新运行,该报错就没有啦...
Java:181 基于springboot的考编论坛管理系统
作者主页:舒克日记 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本系统一共管理员,用户角色。 主要功能:收货地址管理、经验交流平台管理、公告信息管理、跳蚤市场管理、商品留言管理、商品订…...
通义千问sft-甄嬛对话
流程步骤 https://www.datawhale.cn/activity/110/21/76?rankingPage1 按照上面的流程,准备好数据之后就可以直接对7b的模型进行指令微调了,整个流程不是很复杂,操作起来比较方便。但是发布服务等了较长时间,以为出了bug 结果展…...
如何配置Jackson以忽略Java类中为null或空(empty)的字段
Jackson库提供了JsonInclude注解和ObjectMapper配置选项,可以用来控制是否在JSON输出中包含null或空值的字段。 默认情况下,Jackson会包含所有字段,不论其值为何。 本教程将展示如何使用Include.NON_NULL来忽略null值字段,以及使…...
设置笔记本同时连接内外网
原理:通过笔记本和手机相连,实现双网卡功能能。笔记本连接内网wifi、同时手机端开启usb网络共享,笔记本就有了两个网,然配置那个访问外网,那个访问内网。 1.笔记本wifi连接内网wifi 2.手机端共享网络。 手机打开 -【…...
让文章更具说服力:如何巧妙运用逻辑
在写作的过程中,不论是创作小说、撰写学术论文,还是撰写营销文案,逻辑的运用都至关重要。一个没有逻辑支撑的文章,很容易让读者产生困惑、迷失方向,甚至失去阅读兴趣。因此,如何巧妙地运用逻辑,…...
阿里云云服务器Docker-Execrise
申请云服务器 阿里云每个人可以免费申请三个月的使用的服务器可以用作学习使用建议申请规格2核4g的,2g的有点捉襟见肘了选择服务器建议alibaba-linux服务器,就是linux;选择windows可能由于2核4g的限制,docker不匹配系统起码我就是…...
解决 MySQL 启动失败与大小写问题,重置数据库
技术文档:解决 MySQL 启动失败与大小写问题,重置数据库 1. 问题背景 在使用 MySQL 时,可能遇到以下问题: MySQL 启动失败,日志显示 “permission denied” 或 “Can’t create directory” 错误。MySQL 在修改配置文…...
启智畅想集装箱箱号识别算法,2台相机即可实现较高识别率
启智畅想集装箱箱号识别算法,在货车通道中使用时,一般配备2台相机即可。启智畅想集装箱箱号识别算法,在货车通道中使用时,一般配备2台相机即可实现对集装箱箱号的精准捕捉与识别。这两台相机分别安装在货车通道的后侧和随意侧面&a…...
【C++】指针与智慧的邂逅:C++内存管理的诗意
文章目录 RAII 智能指针auto_ptrunique_ptr shared_ptr模拟实现定制删除器循环引用 和 weak_ptr RAII RAII(Resource Acquisition Is Initialization)是一种广泛应用于 C 等编程语言中的编程范式,它的核心思想是:资源的获取和释放…...
python中的高阶函数
1、什么是高阶函数? 高阶函数是指将函数作为参数传入。就是高阶函数 2、高阶函数有哪些? map 映射函数 >>> print(list(map(lambda x:x*x,range(1,11)))) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] >>> print(list(map(lambda x:st…...
spark关联hive 报 Filesystem Close 错误
请看如下问题: 假如我想将一个sql语句插入hive表中时,比如 insert into table tmp.app_user_active_range partition (dt2022-11-04) 报如下错误: 我的环境是pyspark,pyspark中操作hive,使用datagrip关联spark,在da…...
MySQL主从同步详解
文章目录 MySQL主从同步概述MySQL主从同步原理MySQL主从同步结构模式MySQL主从同步搭建搭建步骤一主一从实验环境master主机slave1主机验证主从同步 一主多从master主机slave2主机验证主从同步 MySQL主从同步复制模式 读写分离技术MaxScale简介部署MaxScale服务器授权用户maste…...
Python 单元测试基础脚本
单元测试的概念: 单元测试是针对程序中最小可测试单元进行检查和验证的过程。在Python中,通常一个函数或方法就是一个测试单元。 unittest框架: Python自带了一个名为unittest的单元测试框架,它受JUnit启发,为开发者提…...
鸿蒙开发-在ArkTS中实现socket功能
基本概念 在 ArkTS 中实现 Socket 功能主要涉及到网络通信中的套接字(Socket)编程。Socket 是一种用于在不同设备(如客户端和服务器)之间进行双向通信的接口,它允许应用程序发送和接收数据。在网络编程中,有两种主要的 Socket 类型:基于 TCP…...
【设计模式系列】策略模式(二十四)
一、什么是策略模式 策略模式(Strategy Pattern)是软件设计模式中的一种行为型模式。它定义了一系列算法,并将每一个算法封装起来,使它们可以互换使用,算法的变化不会影响使用算法的用户。策略模式让算法的变化独立于…...
D92【python 接口自动化学习】- pytest基础用法
day92 pytest的skip和skipif用法 学习日期:20241208 学习目标:pytest基础用法 -- pytest的skip和skipif用法 学习笔记: 测试用例跳过 skip和skipif用法,测试用例跳过 pytest.mark.skip 跳过标记的用例 pytest.mark.skipif(1 …...
spring中的@Bean和@Component有什么区别?
定义和作用范围 Bean: 是一个方法级别的注解。它主要用于在Java配置类(使用Configuration注解的类)中定义一个Bean。这个方法返回的对象会被Spring容器管理。例如,假设我们有一个配置类AppConfig: import org.sprin…...
docker入门
安装 官方下载 系统:CentOS 7.9 配置docker yum源。 sudo yum install -y yum-utils sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo启动docker 关机后下次开机又得执行 sudo systemctl start dock…...
HDR视频技术之六:色调映射
图像显示技术的最终目的就是使得显示的图像效果尽量接近人们在自然界中观察到的对应的场景。 HDR 图像与视频有着更高的亮度、更深的位深、更广的色域,因此它无法在常见的普通显示器上显示。 入门级的显示器与播放设备(例如普通人家使用的电视࿰…...
MySQL高可用之MHA
华子目录 MHA概述为什么要用MHA什么是MHAMHA的组成MHA的特点故障切换备选主库的算法 MHA工作原理MHA环境搭建环境准备开始部署MHAMHA软件使用介绍配置MHA的管理环境创建MHA管理的模板文件 测试 模拟故障MySQL-master切换手动切换(在master存活状态下切换)…...
区块链——基本概念、技术原理
一、区块链基本概念 (一)区块链定义 区块链(Blockchain)是指通过去中心化和去信任的方式集体维护一个可靠数据库的技术方案。通俗一点说,区块链技术就指一种全民参与记账的方式,是一种防篡改、共享的、可…...
docker 部署共享文档ZFile
1、拉取ZFile镜像 docker pull crpi-k5k93ldwfc7o75ip.cn-hangzhou.personal.cr.aliyuncs.com/tirling-pdf/zfile:latest 2、创建文件夹和进入文件夹 mkdir zfile && cd zfile 3、创建docker-compose.yml配置文件。 vim docker-compose.yml version: 3.3 service…...
C# 自定义组件实现表格的多层表头功能
在 WinForms 中,想要实现多层表头功能时,DataGridView 本身并不支持该功能,而且又不希望使用第三方控件,因此选择通过自定义组件来实现这一需求。 首先,展示一下程序实现的效果: 接下来,创建一…...
给Squid代理添加HTTP basic认证
HTTP basic认证是一种简单的认证机制,要求用户在请求资源前提供有效的用户名和密码。 实例: 给Squid代理添加HTTP basic认证 要求: 只允许用户名为peter,密码为123的请求通过认证, 其他请求返回407(Proxy认证失败) 步骤 1 使用htpasswd工具,生成用户…...
使用伪装IP地址和MAC地址进行Nmap扫描
使用伪装IP地址和MAC地址进行Nmap扫描 在某些网络设置中,攻击者可以使用伪装的IP地址甚至伪装的MAC地址进行系统扫描。这种扫描方式只有在可以保证捕获响应的情况下才有意义。如果从某个随机的网络尝试使用伪装的IP地址进行扫描,很可能无法接收到任何响…...
Oceanbase离线集群部署
准备工作 两台服务器 服务器的配置参照官网要求来 服务器名配置服务器IPoceanbase116g8h192.168.10.239oceanbase216g8h192.168.10.239 这里选oceanbase1作为 obd机器 oceanbase安装包 选择社区版本的时候自己系统的安装包 ntp时间同步rpm包 联网机器下载所需的软件包 …...
剑指Offer-1 存在重复元素
记录学习过程 题目连接 题目连接 题目描述 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。 示例一、 输入:nums [1,2,3,1] 输出:true 解释&…...
react跳转传参的方法
传参 首先下载命令行 npm react-router-dom 然后引入此代码 前面跳转的是页面 后面传的是你需要传的参数接参 引入此方法 useLocation():这是 react-router-dom 提供的一个钩子,用于获取当前路由的位置对象location.state:这是从其他页面传…...
【Java若依框架】RuoYi-Vue的前端和后端配置步骤和启动步骤
🎙告诉你:Java是世界上最美好的语言 💎比较擅长的领域:前端开发 是的,我需要您的: 🧡点赞❤️关注💙收藏💛 是我持续下去的动力! 目录 一. 作者有话说 …...
CSS学习记录04
CSS边框 CSS border 属性指定元素边框的样式、宽度和颜色。border-style 属性指定要显示的边框类型。dotted - 定义点线边框dashed - 定义虚线边框solid - 定义实线边框double - 定义双边框groove - 定义3D坡口边框,效果取决于border-color值ridge - 定义3D脊线边框…...
Kafka怎么发送JAVA对象并在消费者端解析出JAVA对象--示例
1、在pom.xml中加入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-stream-kafka</artifactId><version>3.1.6</version></dependency> 2、配置application.yml 加入Kafk…...
vue3【实战】图表【组件封装】Chart ( 原生 ECharts ,支持自适配屏幕缩放,动态响应图表配置修改)
效果预览 技术方案 vue3 ( vite | TS | AutoImport ) Element Plus UnoCSS ECharts 技术要点 ECharts 实例的类型 let myChart: echarts.ECharts | null null默认生成随机 id id: {type: String,default: () > Math.random().toString(36).substring(2, 8)},深度监听图…...
Oracle系统性能监控工具oswatcher演示
1、关于 OSW OSWatcher 的使用符合 Oracle 的标准许可条款,并且不需要额外的许可即可使用!!!! OSWatcher (oswbb) 是一种 UNIX shell 脚本的集合,主要用于收集和归档操作系统和网络的度量,以便…...
Unix、GNU、BSD 风格中 ps 参数的区别
注:本文为“不同风格中 ps 命令参数的区别”相关文章合辑。 未去重。 BSD 风格和 UNIX 风格中 ps 参数的区别 作者:Daniel Stori 译者:LCTT Name1e5s | 2017-06-17 10:53 One Last Question ps aux 以及 ps -elf 都是查看进程的方式&…...
Jenkins环境一站式教程:从安装到配置,打造高效CI/CD流水线环境-Ubuntu 22.04.5 环境离线安装配置 Jenkins 2.479.1
文章目录 Jenkins环境一站式教程:从安装到配置,打造高效CI/CD流水线环境-Ubuntu 22.04.5 环境离线安装配置 Jenkins 2.479.1一、环境准备1.1 机器规划1.2 环境配置1.2.1 设置主机名1.2.2 停止和禁用防火墙1.2.3 更新系统 二、安装配置Jenkins2.1 安装JDK…...
百度文心一言全解析
一、技术基础 模型架构 多层神经网络构建:深度神经网络结构,包含多个隐藏层,有效处理复杂语言信息。注意力机制运用:精准聚焦文本关键部分,理解语义关联与重要性分布。多头注意力并行:多维度分析文本&#…...
在python中使用布尔逻辑
布尔是python中常见类型。它的值只能是两项内容之一:true或false. 编写"if"语句 若要在python中表达条件逻辑,可以使用if语句。——编写If语句离不开逻辑运算符:等于、不等于、小于、大于或等于、大于和大于或等于。 在python中…...
【Web】AlpacaHack Round 7 (Web) 题解
Treasure Hunt flag在md5值拼接flagtxt的文件里,如 d/4/1/d/8/c/d/9/8/f/0/0/b/2/0/4/e/9/8/0/0/9/9/8/e/c/f/8/4/2/7/e/f/l/a/g/t/x/t 访问已经存在的目录状态码是301 访问不存在的目录状态码是404 基于此差异可以写爆破脚本 这段waf可以用url编码绕过 做个lab …...
汽车48V电气系统
汽车48V电气系统 汽车48V电气系统汽车48V电气系统设计汽车48V电气系统测试汽车48V系统是48V供电和12V供电共存的么?48V供电系统是如何与12V供电系统共存的?48V电气系统测试的难点有哪些?在汽车48V电气系统通信测试中,如何向12V的控制器和48V的控制器供电?汽车48V电气系统通…...
完美解决Qt Qml窗口全屏软键盘遮挡不显示
1、前提 说明:我使用的是第三方软键盘 QVirtualKeyboard QVirtualKeyboard: Qt5虚拟键盘支持中英文,仿qt官方的virtualkeyboard模块,但使用QWidget实现。 - Gitee.com 由于参考了几篇文章尝试但没有效果,链接如下: 文章一:可能…...